feat(agents): 展示云端通俗技能与工具文案

This commit is contained in:
brother7 committed 2026-10-13 10:25:11 +08:00
1 parent 23aa927441
commit 821fd6ffbe
16 files changed
+118 -23

No files matched your search

+9 -1
View File
@@ -52,7 +52,10 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
if (path.endsWith('/recovery/recent')) { recent = body; return result({ saved: true }); }
if (path.endsWith('/actions')) {
const input = body.input ?? {};
if (body.operation === 'catalog') return result({ models: [{ id: 'test-model', name: '创作模型' }], resources: {}, pricing: null });
if (body.operation === 'catalog') return result({ models: [{ id: 'test-model', name: '创作模型' }], resources: {
tools: [{ key: 'web_search', name: '上网查资料', description: '在网上查找相关信息。' }],
skills: [{ key: 'deep-research', name: '查资料,做研究', description: '比较不同说法,再整理出结论和出处。' }],
}, pricing: null });
if (body.operation === 'knowledge') return result({ databases: knowledgeCreated ? [{ kb_id: 'kb', name: '我的创作资料' }] : [], models: ++knowledgeCatalogLoads === 1 ? [] : [{ id: 'fixture:test-embedding', name: '资料向量模型', dimension: 1024 }] });
if (body.operation === 'createKnowledge') { knowledgeCreated = true; return result({ kb_id: 'kb', name: '我的创作资料' }); }
if (body.operation === 'processKnowledge') { knowledgeStage = 0; return result({ task_id: 'process-document' }); }
@@ -145,6 +148,11 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await expect(page.getByRole('tabpanel', { name: '高级设置' })).toBeVisible();
await expect(page.getByLabel('特别要求')).toBeHidden();
await expect(page.getByRole('button', { name: '能力', exact: true })).toHaveAttribute('aria-current', 'page');
await page.getByRole('button', { name: '选择工具', exact: true }).click();
await expect(page.getByRole('checkbox', { name: /上网查资料.*在网上查找相关信息/ })).toBeVisible();
await page.getByRole('button', { name: '选择技能', exact: true }).click();
await page.getByLabel('搜索技能', { exact: true }).fill('出处');
await expect(page.getByRole('checkbox', { name: /查资料,做研究.*出处/ })).toBeVisible();
await advancedTab.click();
await expect(advancedTab).toHaveAttribute('aria-selected', 'true');
await page.screenshot({ path: testInfo.outputPath('cloud-agent-advanced-tab.png') });
+8 -4
View File
@@ -35,7 +35,7 @@ test('personal chat displays thinking, tools and Markdown, then restores them af
id: 1, message_id: 'answer', role: 'assistant', run_id: run.agent_run_id, request_id: run.request_id, created_at: '',
content: '## 整理结果\n\n| 项目 | 状态 |\n| --- | --- |\n| 资料 | 已核对 |\n\n**可以使用**',
reasoning_content: '先核对来源,再整理结果。',
tool_calls: [{ id: 'lookup', name: '资料检索', args: { query: '实际检索资料' }, status: 'success', tool_call_result: { content: '找到两条资料' } }],
tool_calls: [{ id: 'lookup', name: 'web_search', display_name: '上网查资料', display_description: '在网上查找相关信息。', args: { query: '实际检索资料' }, status: 'success', tool_call_result: { content: '找到两条资料' } }],
}] : [] });
if (body.operation === 'run') return result({ ...run, status: complete ? 'completed' : 'running' });
if (body.operation === 'viewed') return result({});
@@ -71,7 +71,7 @@ test('personal chat displays thinking, tools and Markdown, then restores them af
const process = page.getByTestId('cloud-message-process');
await expect(page.getByLabel('智能体思考过程')).toBeVisible();
await emit([
{ stream_event: { type: 'tool_call', message_id: 'answer', tool_call_id: 'lookup', name: '资料检索', args: { query: '测试资料' } } },
{ stream_event: { type: 'tool_call', message_id: 'answer', tool_call_id: 'lookup', name: 'web_search', display_name: '上网查资料', display_description: '在网上查找相关信息。', args: { query: '测试资料' } } },
{ event: { method: 'tools', data: { event: 'tool-started', tool_call_id: 'lookup', input: { query: '实际检索资料' } } } },
{ event: { method: 'tools', data: { event: 'tool-finished', tool_call_id: 'lookup', output: { content: '找到两条资料' } } } },
{ stream_event: { type: 'message_delta', message_id: 'answer', content: '## 整理结果\n\n| 项目 | 状态 |\n| --- | --- |\n| 资料 | 已核对 |\n\n**可以使用**' } },
@@ -79,8 +79,10 @@ test('personal chat displays thinking, tools and Markdown, then restores them af
await expect(page.getByRole('heading', { name: '整理结果' })).toBeVisible();
await expect(page.getByRole('table')).toBeVisible();
await process.locator(':scope > summary').click();
await process.getByText('资料检索 · 已完成', { exact: true }).click();
await process.getByText('上网查资料 · 已完成', { exact: true }).click();
await expect(process.getByText('找到两条资料', { exact: true })).toBeVisible();
await expect(process.getByText('在网上查找相关信息。', { exact: true })).toBeVisible();
await expect(process.getByText('工具标识:web_search', { exact: true })).toBeVisible();
await expect(process.getByText('"实际检索资料"', { exact: false })).toBeVisible();
await page.screenshot({ path: testInfo.outputPath('personal-chat-process.png') });
await app.evaluate(() => (globalThis as unknown as { finishRenderRun: () => void }).finishRenderRun());
@@ -91,7 +93,9 @@ test('personal chat displays thinking, tools and Markdown, then restores them af
await expect(page.getByRole('heading', { name: '整理结果' })).toBeVisible();
await page.getByTestId('cloud-message-process').locator(':scope > summary').click();
await expect(page.getByLabel('智能体思考过程')).toHaveText('先核对来源,再整理结果。');
await expect(page.getByText('资料检索 · 已完成', { exact: true })).toBeVisible();
await page.getByText('上网查资料 · 已完成', { exact: true }).click();
await expect(page.getByText('在网上查找相关信息。', { exact: true })).toBeVisible();
await expect(page.getByText('工具标识:web_search', { exact: true })).toBeVisible();
await page.screenshot({ path: testInfo.outputPath('personal-chat-reopened.png') });
} finally { await closeElectronApp(app); }
});
+3 -1
View File
@@ -48,9 +48,11 @@ describe('Main cloud Agents boundary', () => {
it('projects saved reasoning and tool results for both personal and channel history without raw metadata', () => {
const message = { id: 1, role: 'assistant', content: 'answer', reasoning_content: 'thought', message_id: 'model-1',
extra_metadata: { internal: true }, tool_calls: [{ id: 'call-1', name: 'search', args: { query: 'topic' },
display_name: '上网查资料', display_description: '在网上查找相关信息。',
status: 'success', internal: 'hidden', tool_call_result: { content: 'result', secret: 'hidden' } }] };
const expected = { id: 1, role: 'assistant', content: 'answer', reasoning_content: 'thought', message_id: 'model-1',
tool_calls: [{ id: 'call-1', name: 'search', args: { query: 'topic' }, status: 'success', tool_call_result: { content: 'result' } }] };
tool_calls: [{ id: 'call-1', name: 'search', display_name: '上网查资料', display_description: '在网上查找相关信息。',
args: { query: 'topic' }, status: 'success', tool_call_result: { content: 'result' } }] };
for (const input of [
{ operation: 'history', input: { thread_id: 'thread-1' } },
{ operation: 'channelConversation', input: { session_id: 'session-1' } },
+1 -1
View File
@@ -52,7 +52,7 @@ it('keeps one child creation intent after a lost response and waits for Skill in
await waitFor(() => expect(screen.queryByLabelText('子智能体名称')).not.toBeInTheDocument());
const calls = api.call.mock.calls.filter(call => call[0] === 'createChild');
expect(calls).toHaveLength(2); expect(calls[0][1]).toEqual(calls[1][1]);
fireEvent.click(screen.getByRole('button', { name: '上传 Skill' }));
fireEvent.click(screen.getByRole('button', { name: '上传技能' }));
const confirm = await screen.findByRole('button', { name: '确认安装到个人能力' });
expect(api.call.mock.calls.some(call => call[0] === 'confirmSkill')).toBe(false);
fireEvent.click(confirm);
+12 -3
View File
@@ -547,7 +547,10 @@ it('searches capabilities while retaining existing selections outside the result
api.list.mockResolvedValue({ agents: [configured], next_cursor: null });
const base = api.call.getMockImplementation()!;
api.call.mockImplementation(async (operation, input) => operation === 'catalog' ? {
models: [{ id: 'test-model', name: '写作模型' }], resources: { tools: [{ key: 'search', name: '资料搜索', description: '搜索素材' }, { key: 'clock', name: '当前时间' }] }, pricing: null,
models: [{ id: 'test-model', name: '写作模型' }], resources: {
tools: [{ key: 'web_search', name: '上网查资料', description: '在网上查找相关信息。' }, { key: 'clock', name: '当前时间' }],
skills: [{ key: 'deep-research', name: '查资料,做研究', description: '比较不同说法,再整理出结论和出处。' }],
}, pricing: null,
} : base(operation, input));
api.save.mockImplementation(async (_slug, input) => ({ ...configured, ...input, draft_revision: 2 }));
open();
@@ -561,9 +564,15 @@ it('searches capabilities while retaining existing selections outside the result
fireEvent.mouseDown(screen.getByRole('tab', { name: '高级设置' }), { button: 0, ctrlKey: false });
expect(screen.getByLabelText('搜索工具')).toHaveValue('资料');
expect(screen.queryByRole('checkbox', { name: '当前时间' })).not.toBeInTheDocument();
fireEvent.click(screen.getByRole('checkbox', { name: /资料搜索/ }));
fireEvent.click(screen.getByRole('checkbox', { name: /上网查资料/ }));
fireEvent.click(screen.getByRole('button', { name: '完成选择' }));
expect(screen.getByRole('checkbox', { name: /missing-tool/ })).toBeChecked();
fireEvent.click(screen.getByRole('button', { name: '选择技能', exact: true }));
fireEvent.change(screen.getByLabelText('搜索技能'), { target: { value: '出处' } });
fireEvent.click(screen.getByRole('checkbox', { name: /查资料,做研究/ }));
fireEvent.click(screen.getByRole('checkbox', { name: '开始对话前,先读好已选技能的使用方法' }));
fireEvent.click(screen.getByRole('button', { name: '保存草稿' }));
await waitFor(() => expect(api.save).toHaveBeenCalledWith(draft.slug, expect.objectContaining({ configuration: expect.objectContaining({ tools: ['missing-tool', 'search'] }) })));
await waitFor(() => expect(api.save).toHaveBeenCalledWith(draft.slug, expect.objectContaining({
configuration: expect.objectContaining({ tools: ['missing-tool', 'web_search'], skills: ['deep-research'], preload_skills: ['deep-research'] }),
})));
});
+5 -2
View File
@@ -74,14 +74,17 @@ it('associates tool arguments and results by call identity, keeps failures visib
render(<CloudChat slug="agent" />);
await waitFor(() => expect(api.events).toHaveBeenCalled());
await emit([
{ stream_event: { type: 'tool_call_delta', message_id: 'm', tool_call_id: 'search', name: '查资料', args_delta: '{"query":', index: 0 } },
{ stream_event: { type: 'tool_call_delta', message_id: 'm', tool_call_id: 'search', name: 'web_search',
display_name: '上网查资料', display_description: '在网上查找相关信息。', args_delta: '{"query":', index: 0 } },
{ stream_event: { type: 'tool_call_delta', message_id: 'm', args_delta: '"天气"}', index: 0 } },
{ stream_event: { type: 'tool_call', message_id: 'm', tool_call_id: 'write', name: '写文件', args: { path: '/a' }, index: 1 } },
{ event: { method: 'tools', data: { event: 'tool-finished', tool_call_id: 'write', output: { content: '磁盘不足', status: 'error' } } } },
{ event: { method: 'tools', data: { event: 'tool-finished', tool_call_id: 'search', output: { content: '晴天', status: 'success' } } } },
], '101-0');
const process = screen.getByTestId('cloud-message-process');
expect(process).toHaveTextContent('查资料 · 已完成');
expect(process).toHaveTextContent('上网查资料 · 已完成');
expect(process).toHaveTextContent('在网上查找相关信息。');
expect(process).toHaveTextContent('工具标识:web_search');
expect(process).toHaveTextContent('写文件 · 失败');
expect(within(process).getByText('{"query":"天气"}')).toBeInTheDocument();
expect(within(process).getByText('晴天')).toBeInTheDocument();