refactor(storage): 统一消息存储到 Core 层

问题:Server 端只存储最终文本响应,工具调用的中间消息丢失。

解决方案:
- Agent.chat() 返回 ChatResult,包含完整消息链
- Server SessionManager 简化为只管理会话元数据
- 消息 API 改为从 Core Storage 读取
- 移除 Server 端的消息存储和 addMessage 方法

影响范围:
- core: Agent.chat() 返回类型变更
- server: SessionManager 接口变更,移除消息存储
- server: GET /sessions/:id/messages 从 Core 读取
- server: 移除 POST /sessions/:id/messages 端点
This commit is contained in:
2025-12-15 10:04:22 +08:00
parent a657af9bb7
commit 6342a46e59
14 changed files with 273 additions and 503 deletions
+9 -4
View File
@@ -6,7 +6,7 @@ import {
type Tool as AITool,
type LanguageModel,
} from 'ai';
import type { Tool, ToolResult, Message, AgentConfig, UserInput, ContentBlock } from '../types/index.js';
import type { Tool, ToolResult, Message, AgentConfig, UserInput, ContentBlock, ChatResult } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
import { ToolRegistry } from '../tools/registry.js';
import { SessionManager } from '../session/index.js';
@@ -311,8 +311,9 @@ export class Agent {
* 发送消息并处理响应(流式)
* @param userMessage 用户消息文本或包含图片的 UserInput
* @param onStream 流式输出回调
* @returns ChatResult 包含最终文本和完整的响应消息链
*/
async chat(userMessage: string | UserInput, onStream?: (text: string) => void): Promise<string> {
async chat(userMessage: string | UserInput, onStream?: (text: string) => void): Promise<ChatResult> {
// 处理带图片的消息
let processedMessage = userMessage;
@@ -331,7 +332,8 @@ export class Agent {
processedMessage = visionResult;
} else {
// 失败,返回错误信息
return '无法处理图片:当前模型不支持图片理解,且 Vision 服务未配置或调用失败。';
const errorText = '无法处理图片:当前模型不支持图片理解,且 Vision 服务未配置或调用失败。';
return { text: errorText, messages: [] };
}
}
}
@@ -465,7 +467,10 @@ export class Agent {
// 持久化会话
await this.persistSession();
return fullResponse;
return {
text: fullResponse,
messages: responseMessages,
};
}
/**
+1 -1
View File
@@ -19,7 +19,7 @@ export { SessionManager } from './session/index.js';
export type { SessionData, SessionSummary } from './session/types.js';
// Types
export type { UserInput } from './types/index.js';
export type { UserInput, ChatResult } from './types/index.js';
// Permission
export { getPermissionManager } from './permission/index.js';
+8
View File
@@ -88,6 +88,14 @@ export interface ConversationContext {
workingDirectory: string;
}
// Chat 返回结果(包含完整的消息链)
export interface ChatResult {
/** 最终文本响应 */
text: string;
/** 完整的响应消息链(包含 tool-call 和 tool-result */
messages: unknown[];
}
// 将自定义 Tool 转换为 Vercel AI SDK 的 zod schema
export function buildZodSchema(parameters: Record<string, ToolParameter>): z.ZodObject<Record<string, z.ZodTypeAny>> {
const schemaObj: Record<string, z.ZodTypeAny> = {};
+2 -1
View File
@@ -391,6 +391,7 @@ describe('Agent - chat with images', () => {
});
expect(result).toBeDefined();
expect(result.text).toBeDefined();
});
it('不支持 vision 时返回错误消息(Vision 未配置)', async () => {
@@ -408,6 +409,6 @@ describe('Agent - chat with images', () => {
],
});
expect(result).toContain('无法处理图片');
expect(result.text).toContain('无法处理图片');
});
});