fix(agents): show only explicitly delivered chat files
This commit is contained in:
1 parent
922b09bda0
commit
e78459b384
12 files changed
+429
-62
No files matched your search
@@ -67,6 +67,7 @@ const longWord = 'an-unbroken-story-notebook-'.repeat(24);
|
||||
const richReply = [
|
||||
'## 一起把小发现变成故事',
|
||||
'你可以先选一个最喜欢的发现,再让角色去试一试。',
|
||||
'[下载故事笔记](sandbox:/故事笔记.md)',
|
||||
`这个很长的名字也应该完整保留:${longWord}`,
|
||||
`[查看完整故事线索](https://example.invalid/story/${longWord})`,
|
||||
['| 今天的线索 | 可以接着想什么 |', '| --- | --- |',
|
||||
@@ -102,7 +103,7 @@ type FixtureSeed = { threads: CloudThread[]; histories: Record<string, CloudHist
|
||||
type FixtureStream = EventTarget & { readyState: number; url: string };
|
||||
type FixtureState = FixtureSeed & { calls: FixtureCall[]; attachments: CloudAttachment[]; streams: FixtureStream[] };
|
||||
type FixtureWindow = Window & { __cloudChatFixture: FixtureState };
|
||||
type FixtureKind = 'empty' | 'history' | 'running' | 'approval' | 'thinking';
|
||||
type FixtureKind = 'empty' | 'history' | 'running' | 'approval' | 'thinking' | 'delivery';
|
||||
|
||||
async function installFixture(page: Page, kind: FixtureKind) {
|
||||
const isRunning = kind === 'running' || kind === 'thinking';
|
||||
@@ -113,7 +114,14 @@ async function installFixture(page: Page, kind: FixtureKind) {
|
||||
const run = isRunning ? makeRun(first, 'running') : kind === 'approval' ? makeRun(first, 'interrupted', interrupt) : null;
|
||||
const seed: FixtureSeed = kind === 'empty' ? { threads: [], histories: {} } : {
|
||||
threads: [first, second], histories: {
|
||||
[first.thread_id]: kind === 'thinking' ? { ...makeHistory(first, false, run), messages: [] } : makeHistory(first, kind !== 'approval', run),
|
||||
[first.thread_id]: kind === 'thinking' ? { ...makeHistory(first, false, run), messages: [] }
|
||||
: kind === 'delivery' ? { ...makeHistory(first), messages: [
|
||||
{ id: 1, role: 'user', content: '[用户提到的文件](sandbox:/user.txt)', request_id: 'delivery-user', run_id: null, created_at: date },
|
||||
{ id: 2, role: 'assistant', request_id: 'delivery-answer', run_id: null, created_at: date,
|
||||
content: '[下载完成的小程序](sandbox:/deliverable.py)\n\n准备时用到了 /internal.py、/call.txt、/cache.json 和 /plain.txt。\n\n`[行内示例](sandbox:/inline.py)`\n\n```markdown\n[代码示例](sandbox:/example.py)\n```',
|
||||
reasoning_content: '[思考过程](sandbox:/thought.txt)',
|
||||
},
|
||||
] } : makeHistory(first, kind !== 'approval', run),
|
||||
[second.thread_id]: makeHistory(second),
|
||||
},
|
||||
};
|
||||
@@ -166,7 +174,8 @@ async function installFixture(page: Page, kind: FixtureKind) {
|
||||
if (!state.attachments.some(item => item.file_id === attachment.file_id)) state.attachments.push(attachment);
|
||||
return result({ attachments: [attachment] });
|
||||
}
|
||||
case 'files': return result({ files: [{ name: '故事笔记.md', is_dir: false, path: '/故事笔记.md', size: 1024 }] });
|
||||
case 'files': return result({ files: ['故事笔记.md', 'deliverable.py', 'internal.py', 'call.txt', 'cache.json', 'plain.txt', 'inline.py', 'example.py', 'user.txt', 'thought.txt']
|
||||
.map(name => ({ name, is_dir: false, path: '/' + name, directory_path: '/', size: 1024 })) });
|
||||
case 'run': return result(Object.values(state.histories).find(item => item.run?.agent_run_id === args?.run_id)?.run);
|
||||
case 'cancelRun': return result({ status: 'cancel_requested' });
|
||||
case 'resume': {
|
||||
@@ -258,6 +267,28 @@ test('long Agent identity and attachment entry fit on a short narrow window', as
|
||||
expect(errors).toEqual([]);
|
||||
});
|
||||
|
||||
test('the file Sheet counts only uploads and files explicitly delivered in the assistant answer', async ({ page }) => {
|
||||
const errors = await openChat(page, 'delivery', 375, 640);
|
||||
const entry = page.getByRole('button', { name: '附件,共 2 个文件', exact: true });
|
||||
await expect(entry).toBeVisible();
|
||||
await entry.click();
|
||||
const panel = page.getByRole('dialog', { name: '本次对话的附件' });
|
||||
const generated = panel.getByRole('region', { name: '助手生成的' });
|
||||
await expect(generated.getByRole('button', { name: /^保存 / })).toHaveCount(1);
|
||||
await expect(generated.getByRole('button', { name: '保存 deliverable.py', exact: true })).toBeVisible();
|
||||
for (const name of ['故事笔记.md', 'internal.py', 'call.txt', 'cache.json', 'plain.txt', 'inline.py', 'example.py', 'user.txt', 'thought.txt']) {
|
||||
await expect(generated.getByText(name, { exact: true })).toHaveCount(0);
|
||||
}
|
||||
await generated.getByRole('button', { name: '保存 deliverable.py', exact: true }).click();
|
||||
await expect.poll(() => page.evaluate(() => (window as unknown as FixtureWindow).__cloudChatFixture.calls
|
||||
.filter(call => call.path === '/api/cloud-agents/files/save').map(call => call.input))).toEqual([{ thread_id: 'story-first', path: '/deliverable.py' }]);
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(entry).toBeFocused();
|
||||
await expectComposerBounds(page);
|
||||
expect((await operations(page)).some(item => ['submit', 'preview', 'resume', 'deleteAttachment'].includes(String(item?.operation)))).toBe(false);
|
||||
expect(errors).toEqual([]);
|
||||
});
|
||||
|
||||
for (const width of [375, 768, 1024, 1440]) {
|
||||
test(`friendly empty conversation keeps the composer reachable at ${width}px`, async ({ page }) => {
|
||||
const errors = await openChat(page, 'empty', width, width === 375 ? 640 : 760);
|
||||
|
||||
Reference in new issue
Block a user