refactor: unify agent session persistence

This commit is contained in:
2026-06-04 15:02:27 +08:00
parent 04ded0ceb0
commit 0ecb2babf3
22 changed files with 542 additions and 497 deletions
+16 -12
View File
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
import { logger } from "../logger.js";
import { type OpencodeRuntimeAdapter } from "../runtime/opencode.js";
import { ToolSessionContextStore } from "../session/toolContextStore.js";
import { SessionRuntimeContextStore } from "../sessions/runtimeContextStore.js";
import { toActorKey, toProjectKey } from "../utils/fileStore.js";
export type SessionBinding = {
@@ -26,12 +26,11 @@ export type ChatRequestContext = SessionContext & {
export class ChatSessionBridge {
private readonly abortControllers = new Map<string, AbortController>();
private readonly toolContextStore = new ToolSessionContextStore();
private readonly sessionRuntimeContextStore = new SessionRuntimeContextStore();
constructor(private readonly runtime: OpencodeRuntimeAdapter) {}
async resolve(context: {
clientSessionId?: string;
sessionId?: string;
accessToken?: string;
projectId?: string;
@@ -42,15 +41,19 @@ export class ChatSessionBridge {
requestContext: ChatRequestContext;
created: boolean;
}> {
const requestContext = this.buildRequestContext(context);
let requestContext = this.buildRequestContext(context);
const existingSessionId = context.sessionId?.trim();
await this.abortActiveRuntime(requestContext.clientSessionId, existingSessionId);
let sessionId = existingSessionId;
let created = false;
if (!sessionId) {
const session = await this.runtime.createSession(requestContext.clientSessionId);
const session = await this.runtime.createSession();
sessionId = session.id;
requestContext = {
...requestContext,
clientSessionId: sessionId,
};
created = true;
}
const binding: SessionBinding = {
@@ -58,7 +61,7 @@ export class ChatSessionBridge {
sessionId,
startedAt: Date.now(),
};
await this.toolContextStore.write({
await this.sessionRuntimeContextStore.write({
accessToken: requestContext.accessToken,
actorKey: requestContext.actorKey,
allowLearningWrite: true,
@@ -107,7 +110,7 @@ export class ChatSessionBridge {
};
}
async deleteConversationSession(context: {
async deleteSession(context: {
clientSessionId: string;
sessionId: string;
}) {
@@ -121,29 +124,30 @@ export class ChatSessionBridge {
await this.runtime.abortSession(sessionId).catch((error) => {
logger.warn(
{ clientSessionId, sessionId, err: error },
"failed to abort conversation runtime session",
"failed to abort runtime session",
);
});
await this.runtime.waitForSessionIdle(sessionId).catch((error) => {
logger.warn(
{ clientSessionId, sessionId, err: error },
"failed while waiting for conversation runtime session to become idle",
"failed while waiting for runtime session to become idle",
);
});
await this.toolContextStore.remove(sessionId).catch((error) => {
await this.sessionRuntimeContextStore.remove(sessionId).catch((error) => {
logger.debug({ sessionId, err: error }, "failed to cleanup runtime tool context");
});
}
private buildRequestContext(context: {
clientSessionId?: string;
sessionId?: string;
accessToken?: string;
projectId?: string;
traceId?: string;
userId?: string;
}): ChatRequestContext {
const sessionId = context.sessionId?.trim();
return {
clientSessionId: context.clientSessionId?.trim() || this.createClientSessionId(),
clientSessionId: sessionId || this.createClientSessionId(),
accessToken: context.accessToken,
actorKey: toActorKey(context.userId),
projectId: context.projectId,