feat: 支持智能体文档附件与轻量读取

- 建立文档上传、异步读取、对象存储、补偿与聊天绑定闭环

- 按智能体 20K 上下文预算选择文档片段并保留稳定引用

- 统一聊天文件卡片、类型图标、草稿恢复与可靠下载
This commit is contained in:
2026-07-29 01:32:19 +08:00
parent fceedd02cd
commit d45c67a317
72 changed files with 5876 additions and 237 deletions

View File

@@ -1,14 +1,14 @@
// @vitest-environment happy-dom
import { useUserStore } from '@easyflow/stores';
import { createPinia, setActivePinia } from 'pinia';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useUserStore } from '@easyflow/stores';
import { clearAgentChatBrowserCache } from '#/utils/agent-chat-cache';
import { sendAgentChat } from './api';
import { agentChatRuntimeManager } from './agentChatRuntimeManager';
import { sendAgentChat } from './api';
vi.mock('./api', () => ({
generateAgentSessionId: vi.fn(),
@@ -27,7 +27,7 @@ describe('agentChatRuntimeManager', () => {
vi.useRealTimers();
});
it('replaces draft image URLs and isolates snapshots by account', async () => {
it('replaces accepted attachments and isolates snapshots by account', async () => {
let callbacks: any;
vi.mocked(sendAgentChat).mockImplementation((_data, options) => {
callbacks = options;
@@ -45,6 +45,16 @@ describe('agentChatRuntimeManager', () => {
await agentChatRuntimeManager.start({
agentId: 'agent-1',
documentUploadIds: ['document-upload-1'],
documents: [
{
downloadUrl:
'/api/v1/agent/media/document/content?reference=draft%3Adocument-upload-1',
name: 'draft.docx',
status: 'ready',
uploadId: 'document-upload-1',
},
],
images: [
{
name: 'draft.png',
@@ -60,6 +70,16 @@ describe('agentChatRuntimeManager', () => {
data: JSON.stringify({
domain: 'SYSTEM',
payload: {
attachments: [
{
attachmentRef: 'formal:101:201:document:0',
downloadUrl:
'/api/v1/agent/media/document/content?reference=formal:101:201:document:0',
name: 'draft.docx',
readSnapshotId: 'snapshot-1',
size: 2048,
},
],
images: [
{
imageRef: 'formal:101:201:0:png',
@@ -86,6 +106,20 @@ describe('agentChatRuntimeManager', () => {
'/api/v1/agent/media/content?reference=formal:101:201:0:png',
}),
);
expect(
userMessage?.type === 'message' ? userMessage.documents?.[0] : null,
).toEqual(
expect.objectContaining({
attachmentRef: 'formal:101:201:document:0',
readSnapshotId: 'snapshot-1',
status: 'ready',
}),
);
expect(vi.mocked(sendAgentChat).mock.calls[0]?.[0]).toEqual(
expect.objectContaining({
documentUploadIds: ['document-upload-1'],
}),
);
userStore.setUserInfo({
...firstAccount,