import { ACPX_BACKEND_ID, AcpxRuntime as BaseAcpxRuntime, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, type AcpAgentRegistry, type AcpRuntimeDoctorReport, type AcpRuntimeEvent, type AcpRuntimeHandle, type AcpRuntimeOptions, type AcpRuntimeStatus, } from "acpx/runtime"; import type { AcpRuntime } from "../runtime-api.js"; type AcpSessionStore = AcpRuntimeOptions["sessionStore"]; type AcpSessionRecord = Parameters[0]; type AcpLoadedSessionRecord = Awaited>; type ResetAwareSessionStore = AcpSessionStore & { markFresh: (sessionKey: string) => void; }; function readSessionRecordName(record: AcpSessionRecord): string { if (typeof record !== "object" || record === null) { return ""; } const { name } = record as { name?: unknown }; return typeof name === "string" ? name.trim() : ""; } function createResetAwareSessionStore(baseStore: AcpSessionStore): ResetAwareSessionStore { const freshSessionKeys = new Set(); return { async load(sessionId: string): Promise { const normalized = sessionId.trim(); if (normalized && freshSessionKeys.has(normalized)) { return undefined; } return await baseStore.load(sessionId); }, async save(record: AcpSessionRecord): Promise { await baseStore.save(record); const sessionName = readSessionRecordName(record); if (sessionName) { freshSessionKeys.delete(sessionName); } }, markFresh(sessionKey: string): void { const normalized = sessionKey.trim(); if (normalized) { freshSessionKeys.add(normalized); } }, }; } type AcpxRuntimeLike = AcpRuntime & { probeAvailability(): Promise; isHealthy(): boolean; doctor(): Promise; }; export class AcpxRuntime implements AcpxRuntimeLike { private readonly sessionStore: ResetAwareSessionStore; private readonly delegate: BaseAcpxRuntime; constructor( options: AcpRuntimeOptions, testOptions?: ConstructorParameters[1], ) { this.sessionStore = createResetAwareSessionStore(options.sessionStore); this.delegate = new BaseAcpxRuntime( { ...options, sessionStore: this.sessionStore, }, testOptions, ); } isHealthy(): boolean { return this.delegate.isHealthy(); } probeAvailability(): Promise { return this.delegate.probeAvailability(); } doctor(): Promise { return this.delegate.doctor(); } ensureSession(input: Parameters[0]): Promise { return this.delegate.ensureSession(input); } runTurn(input: Parameters[0]): AsyncIterable { return this.delegate.runTurn(input); } getCapabilities(): ReturnType { return this.delegate.getCapabilities(); } getStatus(input: Parameters>[0]): Promise { return this.delegate.getStatus(input); } setMode(input: Parameters>[0]): Promise { return this.delegate.setMode(input); } setConfigOption(input: Parameters>[0]): Promise { return this.delegate.setConfigOption(input); } cancel(input: Parameters[0]): Promise { return this.delegate.cancel(input); } async prepareFreshSession(input: { sessionKey: string }): Promise { this.sessionStore.markFresh(input.sessionKey); } close(input: Parameters[0]): Promise { return this.delegate .close({ handle: input.handle, reason: input.reason, }) .then(() => { if (input.discardPersistentState) { this.sessionStore.markFresh(input.handle.sessionKey); } }); } } export { ACPX_BACKEND_ID, createAcpRuntime, createAgentRegistry, createFileSessionStore, decodeAcpxRuntimeHandleState, encodeAcpxRuntimeHandleState, }; export type { AcpAgentRegistry, AcpRuntimeOptions, AcpSessionRecord, AcpSessionStore };