fix(coding): remediate data service review findings
This commit is contained in:
@@ -237,6 +237,7 @@ describe.each(ASSETS)('generated Data Service SDK (%s)', (assetName) => {
|
||||
describe('bundled Data Service Skill packaging', () => {
|
||||
it('ships both canonical assets and an ordered workflow with explicit completion criteria', async () => {
|
||||
const skill = await readFile(path.resolve('resources/coding-skills/data-service/SKILL.md'), 'utf8');
|
||||
const readme = await readFile(path.resolve('README.md'), 'utf8');
|
||||
const tsAsset = await readFile(path.join(ASSET_ROOT, 'makelore-data.ts'), 'utf8');
|
||||
const jsAsset = await readFile(path.join(ASSET_ROOT, 'makelore-data.js'), 'utf8');
|
||||
|
||||
@@ -254,9 +255,14 @@ describe('bundled Data Service Skill packaging', () => {
|
||||
expect(skill.indexOf('read-back')).toBeLessThan(skill.indexOf('report'));
|
||||
expect(skill).toContain('src/lib/makelore-data.js');
|
||||
expect(skill).toContain('makelore-data.js');
|
||||
expect(skill).toContain('injectProjectData: true');
|
||||
expect(skill).not.toContain('inject_project_data');
|
||||
expect(skill).toContain('逐字复制');
|
||||
expect(skill).toContain('no-op');
|
||||
expect(skill).toContain('冲突');
|
||||
expect(readme).toContain('data-service');
|
||||
expect(readme).toContain('显式请求');
|
||||
expect(readme).toContain('预览');
|
||||
const packaged = await listProductCodingSkills(path.resolve('resources/coding-skills'));
|
||||
const dataService = packaged.find(({ id }) => id === 'data-service');
|
||||
expect(dataService).toMatchObject({ id: 'data-service', name: 'data-service' });
|
||||
|
||||
@@ -14,5 +14,6 @@ describe('Data Service Host API registration', () => {
|
||||
const worksIndex = routeList?.[1].indexOf('handleWorksRoutes') ?? -1;
|
||||
expect(dataServiceIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(worksIndex).toBeGreaterThan(dataServiceIndex);
|
||||
expect(source).not.toContain('handleDataServiceRoute = handleDataServiceRoutes');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -244,7 +244,7 @@ describe('Pi worker process', () => {
|
||||
'--no-context-files',
|
||||
'--no-approve',
|
||||
'--tools',
|
||||
'read,bash,edit,write,grep,find,ls,ask_user,subagent,agent_browser,game_asset_browser,game_asset_review,task_state,changed_file,runtime_context',
|
||||
'read,bash,edit,write,grep,find,ls,ask_user,subagent,agent_browser,game_asset_browser,game_asset_review,task_state,changed_file,runtime_context,data_service_configure,data_service_inspect,data_service_list_projects,data_service_get_document,data_service_list_documents,data_service_put_document,data_service_delete_document,data_service_remove_collection,data_service_reset,data_service_remove_project',
|
||||
'--model', 'model-a',
|
||||
]);
|
||||
expect(buildPiRpcArgs('sessions', ['--no-session'], ['read', 'grep', 'find', 'ls']))
|
||||
|
||||
@@ -292,6 +292,16 @@ describe('locked Pi worker process smoke', () => {
|
||||
'task_state',
|
||||
'changed_file',
|
||||
'runtime_context',
|
||||
'data_service_configure',
|
||||
'data_service_inspect',
|
||||
'data_service_list_projects',
|
||||
'data_service_get_document',
|
||||
'data_service_list_documents',
|
||||
'data_service_put_document',
|
||||
'data_service_delete_document',
|
||||
'data_service_remove_collection',
|
||||
'data_service_reset',
|
||||
'data_service_remove_project',
|
||||
]));
|
||||
expect(worker.stderrDiagnostic).not.toContain('Failed to load extension');
|
||||
await expect(worker.stop('test_injection')).resolves.toMatchObject({ mode: 'stdin-close', code: 0 });
|
||||
|
||||
@@ -127,13 +127,58 @@ describe('preview data session manager', () => {
|
||||
expect(manager.getSnapshot()).toBeNull();
|
||||
});
|
||||
|
||||
it('requires an HTTP loopback Origin and invalidates on browser lifecycle events', async () => {
|
||||
it('accepts HTTP/HTTPS loopback Origins, including their default ports', async () => {
|
||||
const { manager, projectPath } = await createManager();
|
||||
for (const origin of [
|
||||
'http://localhost',
|
||||
'http://localhost:80',
|
||||
'https://localhost',
|
||||
'https://localhost:443',
|
||||
'http://127.0.0.1',
|
||||
'https://127.0.0.1:443',
|
||||
'http://[::1]',
|
||||
'https://[::1]:443',
|
||||
]) {
|
||||
await expect(manager.open({ projectPath, origin, browserGeneration: 1 }))
|
||||
.resolves.toMatchObject({ origin: new URL(origin).origin });
|
||||
}
|
||||
await expect(manager.open({
|
||||
projectPath,
|
||||
origin: 'https://example.com:443',
|
||||
browserGeneration: 1,
|
||||
})).rejects.toMatchObject({ code: 'invalid_origin' });
|
||||
await expect(manager.open({
|
||||
projectPath,
|
||||
origin: 'http://localhost:80/path',
|
||||
browserGeneration: 1,
|
||||
})).rejects.toMatchObject({ code: 'invalid_origin' });
|
||||
});
|
||||
|
||||
it('requires matching browser generation before invalidating lifecycle events', async () => {
|
||||
const { manager, projectPath } = await createManager();
|
||||
await manager.open({ projectPath, origin: 'http://127.0.0.1:13210', browserGeneration: 2 });
|
||||
|
||||
manager.handleAgentBrowserLifecycle({
|
||||
type: 'closed',
|
||||
projectId: '11111111-1111-4111-8111-111111111111',
|
||||
projectPath,
|
||||
generation: 1,
|
||||
url: 'http://127.0.0.1:13210/',
|
||||
});
|
||||
expect(manager.getSnapshot()).not.toBeNull();
|
||||
|
||||
manager.handleAgentBrowserLifecycle({
|
||||
type: 'closed',
|
||||
projectId: '11111111-1111-4111-8111-111111111111',
|
||||
projectPath,
|
||||
generation: 2,
|
||||
url: 'http://127.0.0.1:13210/',
|
||||
});
|
||||
expect(manager.getSnapshot()).toBeNull();
|
||||
});
|
||||
|
||||
it('invalidates on browser lifecycle events from the current generation', async () => {
|
||||
const { manager, projectPath } = await createManager();
|
||||
|
||||
const lifecycleTypes: AgentBrowserLifecycleEvent['type'][] = [
|
||||
'cross-origin-navigation',
|
||||
|
||||
Reference in New Issue
Block a user