mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
Tighten plugin authoring completion regressions
This commit is contained in:
parent
f7beb42950
commit
91691f3e66
2 changed files with 74 additions and 0 deletions
|
|
@ -394,6 +394,76 @@ child.on('exit', (code, signal) => {
|
|||
}
|
||||
});
|
||||
|
||||
it('allows plugin authoring to succeed when the requested generated-plugin artifacts exist before close', async () => {
|
||||
const projectId = `proj-plugin-authoring-success-${randomUUID()}`;
|
||||
|
||||
const createProjectResponse = await fetch(`${baseUrl}/api/projects`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
id: projectId,
|
||||
name: 'Plugin authoring artifact success fixture',
|
||||
skillId: null,
|
||||
designSystemId: null,
|
||||
}),
|
||||
});
|
||||
expect(createProjectResponse.status).toBe(200);
|
||||
const conversationsResponse = await fetch(`${baseUrl}/api/projects/${projectId}/conversations`);
|
||||
expect(conversationsResponse.status).toBe(200);
|
||||
const conversationsBody = await conversationsResponse.json() as {
|
||||
conversations: Array<{ id: string }>;
|
||||
};
|
||||
const conversationId = conversationsBody.conversations[0]?.id;
|
||||
expect(conversationId).toBeTruthy();
|
||||
|
||||
await withFakeAgent(
|
||||
'opencode',
|
||||
`
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
process.stdin.resume();
|
||||
process.stdin.on('end', () => {
|
||||
const pluginDir = path.join(process.cwd(), 'generated-plugin');
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(pluginDir, 'open-design.json'), JSON.stringify({ name: 'generated-plugin' }, null, 2));
|
||||
fs.writeFileSync(path.join(pluginDir, 'SKILL.md'), '# Generated plugin\\n');
|
||||
console.log(JSON.stringify({ type: 'step_start' }));
|
||||
console.log(JSON.stringify({ type: 'text', part: { text: '我来帮你创建一个通用的 Open Design 插件脚手架。先读取文档规范,再生成插件文件。' } }));
|
||||
console.log(JSON.stringify({ type: 'step_finish', part: { tokens: { input: 1, output: 1 } } }));
|
||||
process.exit(0);
|
||||
});
|
||||
`,
|
||||
async () => {
|
||||
const createResponse = await fetch(`${baseUrl}/api/runs`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
agentId: 'opencode',
|
||||
projectId,
|
||||
conversationId,
|
||||
pluginId: 'od-plugin-authoring',
|
||||
message: '请创建一个可刷新、可审计、由 API 驱动的 Open Design 插件脚手架。',
|
||||
}),
|
||||
});
|
||||
expect(createResponse.status).toBe(202);
|
||||
const { runId } = await createResponse.json() as { runId: string };
|
||||
|
||||
const eventsResponse = await fetch(`${baseUrl}/api/runs/${runId}/events`);
|
||||
const eventsBody = await readSseUntil(eventsResponse, 'event: final');
|
||||
const statusBody = await waitForRunStatus(baseUrl, runId);
|
||||
|
||||
expect(eventsBody).toContain('先读取文档规范,再生成插件文件');
|
||||
expect(statusBody.status).toBe('succeeded');
|
||||
|
||||
const filesResponse = await fetch(`${baseUrl}/api/projects/${projectId}/files`);
|
||||
expect(filesResponse.status).toBe(200);
|
||||
const filesBody = await filesResponse.json() as { files: Array<{ name: string }> };
|
||||
expect(filesBody.files.some((file) => file.name === 'generated-plugin/open-design.json')).toBe(true);
|
||||
expect(filesBody.files.some((file) => file.name === 'generated-plugin/SKILL.md')).toBe(true);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('does not report plugin authoring as succeeded when the agent only emits planning text without artifacts', async () => {
|
||||
const projectId = `proj-plugin-authoring-${randomUUID()}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -392,6 +392,10 @@ pnpm exec playwright test -c playwright.config.ts ui/design-systems-manager.test
|
|||
- `generated-plugin/SKILL.md`
|
||||
- daemon 会把本轮转成 `failed`,而不是错误地保留 `succeeded`
|
||||
|
||||
2. `allows plugin authoring to succeed when the requested generated-plugin artifacts exist before close`
|
||||
- 覆盖同一条 guard 的对称路径:只要关键插件产物已经落地,就不会被误伤成失败
|
||||
- 锁住 daemon 的判断是“缺少目标产物才失败”,而不是“只要文本看起来像计划句就失败”
|
||||
|
||||
|
||||
### 6. Grok Build prompt inline argv 契约
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue