feat(server): improve context management (#15448)

#### PR Dependency Tree


* **PR #15448** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added workspace artifact upload, browsing, removal, deduplication, and
library ownership support.
* Copilot now supports scoped document and artifact search, canvas
reading, live editor context, and frontend tools.
* Added scope and focus selectors with source-resolution receipts in
chat.
* Added embedding health, progress, synchronization, and retrieval
capabilities.
* Added BYOK policy visibility, provider restrictions, endpoint dialect
selection, and validation.
* Added delegated editor interactions and userdata document
authorization.

* **Bug Fixes**
* Improved attachment handling, cancellation, access control, retrieval
fallbacks, workspace synchronization, and configuration validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-08-10 09:27:58 +08:00
committed by GitHub
parent 42322d13fe
commit ee899a267b
311 changed files with 20468 additions and 14806 deletions
@@ -18,6 +18,37 @@ import type {
import type { GfxModel } from '@blocksuite/std/gfx';
import { type Page } from '@playwright/test';
export class EditorUtils {
public static async waitForCurrentDocSynced(page: Page) {
await page.evaluate(async () => {
const [, , workspaceId, docId] = location.pathname.split('/');
const workspace = (
window as typeof window & {
currentWorkspace?: {
engine: {
doc: {
waitForSynced(docId: string, abort: AbortSignal): Promise<void>;
};
};
};
}
).currentWorkspace;
if (!workspaceId || !docId || !workspace) {
throw new Error('Current document is unavailable');
}
const abort = AbortSignal.timeout(60_000);
await Promise.all([
workspace.engine.doc.waitForSynced(docId, abort),
workspace.engine.doc.waitForSynced('db$docProperties', abort),
]);
const response = await fetch(
`/api/workspaces/${workspaceId}/docs/${docId}`
);
if (!response.ok) {
throw new Error('Current document could not be persisted');
}
});
}
public static async focusToEditor(page: Page) {
const title = getBlockSuiteEditorTitle(page);
await title.focus();
@@ -351,8 +382,7 @@ export class EditorUtils {
await page.keyboard.press('Enter');
}
}
// sleep 1 sec to wait the doc sync
await page.waitForTimeout(1000);
await this.waitForCurrentDocSynced(page);
}
public static async createTagAndDoc(
@@ -1,4 +1,3 @@
import { cleanupWorkspace, runPrisma } from '@affine-test/kit/utils/cloud';
import { expect, type Page } from '@playwright/test';
const WORKSPACE_EMBEDDING_SWITCH_TEST_ID = 'workspace-embedding-setting-switch';
@@ -95,7 +94,7 @@ export class SettingsPanelUtils {
await page
.getByTestId('workspace-embedding-setting-attachment-uploading-item')
.waitFor({ state: 'hidden' });
.waitFor({ state: 'hidden', timeout: 30_000 });
}
}
@@ -226,7 +225,6 @@ export class SettingsPanelUtils {
timeout: number,
status = 'synced'
) {
await cleanupWorkspace(page.url().split('/').slice(-2)[0] || '');
await expect(async () => {
await this.openSettingsPanel(page);
const title = page.getByTestId('embedding-progress-title');
@@ -266,17 +264,17 @@ export class SettingsPanelUtils {
'workspace-embedding-setting-attachment-item'
);
await expect(attachmentItems).toHaveCount(expectedFileCount);
await expect(
attachmentList.getByTestId(
'workspace-embedding-setting-attachment-uploading-item'
)
).toHaveCount(0);
}).toPass({ timeout });
const workspaceId = page.url().split('/').slice(-2)[0] || '';
await cleanupWorkspace(workspaceId);
await expect(async () => {
const embeddedFileCount = await runPrisma(client =>
client.aiWorkspaceFiles.count({
where: { workspaceId, embeddings: { some: {} } },
})
);
expect(embeddedFileCount).toBe(expectedFileCount);
await expect(
page.getByTestId('workspace-embedding-setting-attachment-ready-item')
).toHaveCount(expectedFileCount);
}).toPass({ timeout });
}
}
@@ -58,16 +58,8 @@ export class TestUtils {
await waitForEditorLoad(page);
}
public async setupTestEnvironment(page: Page, defaultModel?: string) {
const selectedModel = defaultModel ?? 'gpt-5.6-luna';
public async setupTestEnvironment(page: Page) {
await skipOnboarding(page.context());
await page.context().addInitScript(model => {
window.localStorage.setItem(
'global-state:AIModelId',
JSON.stringify(model)
);
}, selectedModel);
await openHomePage(page);
await this.createNewPage(page);
}