fix(server): 修复消息持久化问题

- 在 adapter.ts 中为 Agent 绑定 Core SessionManager
- 添加 getOrCreateSessionManager 函数创建和恢复会话
- 修改 getOrCreateAgent 为异步函数
- 在 sessions.ts 中转换 AI SDK 消息格式为字符串
This commit is contained in:
2025-12-15 10:45:58 +08:00
parent bbce1de60c
commit b8fcb65f73
2 changed files with 103 additions and 9 deletions
+80 -3
View File
@@ -47,11 +47,32 @@ interface ChatResult {
messages: unknown[];
}
/**
* Session Manager 接口(Core 的 SessionManager
*/
interface SessionManagerInstance {
init(workdir: string): Promise<unknown>;
getSession(): { id: string; messages: unknown[] } | null;
setMessages(messages: unknown[]): Promise<void>;
setDiscoveredTools(tools: string[]): Promise<void>;
save(): Promise<void>;
close(): Promise<void>;
restoreSession(sessionId: string): Promise<unknown | null>;
}
/**
* Session Manager 构造函数接口
*/
interface SessionManagerConstructor {
new (): SessionManagerInstance;
}
/**
* Agent 实例接口
*/
interface AgentInstance {
setRegistry(registry: unknown): void;
setSessionManager(manager: SessionManagerInstance): void;
chat(message: string, onStream?: (chunk: string) => void): Promise<ChatResult>;
getToolCount(): { core: number; discovered: number; total: number };
getContextUsageFormatted(): string;
@@ -106,6 +127,7 @@ interface AgentRegistryInterface {
*/
interface CoreModule {
Agent: AgentConstructor;
SessionManager: SessionManagerConstructor;
toolRegistry: ToolRegistry;
loadConfig: () => unknown;
saveConfig: (config: Record<string, unknown>) => void;
@@ -124,6 +146,9 @@ let coreModule: CoreModule | null = null;
// Agent 实例缓存(每个 session 一个)
const agentCache: Map<string, AgentInstance> = new Map();
// SessionManager 实例缓存(每个 session 一个)
const sessionManagerCache: Map<string, SessionManagerInstance> = new Map();
// 配置错误缓存(用于向客户端返回友好错误)
let lastConfigError: { provider: string; message: string } | null = null;
@@ -182,7 +207,7 @@ export function isCoreAvailable(): boolean {
*
* @returns Agent 实例,或 nullCore 不可用或配置错误)
*/
export function getOrCreateAgent(sessionId: string): AgentInstance | null {
export async function getOrCreateAgent(sessionId: string): Promise<AgentInstance | null> {
// 清除之前的配置错误
lastConfigError = null;
@@ -205,6 +230,12 @@ export function getOrCreateAgent(sessionId: string): AgentInstance | null {
const permissionManager = coreModule.getPermissionManager();
permissionManager.setAskCallback(createServerPermissionCallback(sessionId));
// 创建并初始化 SessionManager(用于消息持久化)
const sessionMgr = await getOrCreateSessionManager(sessionId);
if (sessionMgr) {
agent.setSessionManager(sessionMgr);
}
agentCache.set(sessionId, agent);
return agent;
} catch (error) {
@@ -223,10 +254,56 @@ export function getOrCreateAgent(sessionId: string): AgentInstance | null {
}
}
/**
* 获取或创建 SessionManager 实例
*/
async function getOrCreateSessionManager(sessionId: string): Promise<SessionManagerInstance | null> {
if (!coreModule) {
return null;
}
// 检查缓存
if (sessionManagerCache.has(sessionId)) {
return sessionManagerCache.get(sessionId)!;
}
try {
// 获取 session 的工作目录
const serverSessionManager = getSessionManager();
const session = serverSessionManager.get(sessionId);
const workdir = session?.workdir || process.cwd();
// 创建新的 Core SessionManager
const sessionMgr = new coreModule.SessionManager();
// 初始化(这会创建或加载项目)
await sessionMgr.init(workdir);
// 尝试恢复指定的 session(如果存在)
const restored = await sessionMgr.restoreSession(sessionId);
if (restored) {
console.log(`[Agent] Restored session ${sessionId} with ${(restored as { messages: unknown[] }).messages?.length || 0} messages`);
}
sessionManagerCache.set(sessionId, sessionMgr);
return sessionMgr;
} catch (error) {
console.error(`[Agent] Failed to create SessionManager for ${sessionId}:`, error);
return null;
}
}
/**
* 销毁 Agent 实例
*/
export function destroyAgent(sessionId: string): void {
export async function destroyAgent(sessionId: string): Promise<void> {
// 关闭并清理 SessionManager
const sessionMgr = sessionManagerCache.get(sessionId);
if (sessionMgr) {
await sessionMgr.close();
sessionManagerCache.delete(sessionId);
}
agentCache.delete(sessionId);
}
@@ -241,7 +318,7 @@ export async function processMessage(sessionId: string, content: string): Promis
emitStatusEvent(sessionId, 'processing', { message: '正在处理...' });
// 获取 Agent
const agent = getOrCreateAgent(sessionId);
const agent = await getOrCreateAgent(sessionId);
if (!agent) {
// 检查是否为配置错误
+23 -6
View File
@@ -134,13 +134,30 @@ sessionsRouter.get('/:id/messages', async (c) => {
});
}
// 为消息添加 IDCore 的 ModelMessage 格式没有 id 字段
// 为消息添加 ID 并转换内容格式(AI SDK 格式 -> 字符串
const messagesWithId = sessionData.messages.map(
(msg: { role: string; content: unknown }, index: number) => ({
...msg,
id: `${msg.role}-${id}-${index}`,
timestamp: new Date().toISOString(),
})
(msg: { role: string; content: unknown }, index: number) => {
// 转换 AI SDK 内容格式为字符串
let content: string;
if (typeof msg.content === 'string') {
content = msg.content;
} else if (Array.isArray(msg.content)) {
// AI SDK 格式: [{type: "text", text: "..."}, ...]
content = msg.content
.filter((block: { type?: string }) => block.type === 'text')
.map((block: { text?: string }) => block.text || '')
.join('');
} else {
content = String(msg.content);
}
return {
id: `${msg.role}-${id}-${index}`,
role: msg.role,
content,
timestamp: new Date().toISOString(),
};
}
);
return c.json({