@averyyy/pi-server 0.80.3-piclient.5 → 0.80.3-piclient.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/bin/update.js +6 -170
- package/dist/pi-server-protocol.d.ts +13 -0
- package/dist/pi-server-protocol.d.ts.map +1 -0
- package/dist/pi-server-protocol.js +32 -0
- package/dist/pi-server-protocol.js.map +1 -0
- package/dist/request-chunks.d.ts +15 -5
- package/dist/request-chunks.d.ts.map +1 -1
- package/dist/request-chunks.js +123 -27
- package/dist/request-chunks.js.map +1 -1
- package/dist/server.d.ts +6 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +178 -24
- package/dist/server.js.map +1 -1
- package/dist/session-persistence.d.ts.map +1 -1
- package/dist/session-persistence.js +104 -3
- package/dist/session-persistence.js.map +1 -1
- package/dist/session-store.d.ts +10 -0
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +46 -12
- package/dist/session-store.js.map +1 -1
- package/package.json +3 -3
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server as HttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\ttype ProxyAssistantMessageEvent,\n\tprepareCompaction,\n\ttype SessionTreeEntry,\n} from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessageEvent,\n\ttype Context,\n\tcreateModels,\n\tcreateProvider,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai\";\nimport { streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport type { ServerConfig } from \"./config.ts\";\nimport { loadConfig } from \"./config.ts\";\nimport { encodeErrorEvent, encodeProxyEvent } from \"./event-encoding.ts\";\nimport { CHUNK_ENDPOINT, type RequestChunkBody, receiveRequestChunk } from \"./request-chunks.ts\";\nimport { deletePersistedSession, loadPersistedSessions, savePersistedSession } from \"./session-persistence.ts\";\nimport {\n\tappendCompactionEntry,\n\tappendMessages,\n\tappendSessionEntries,\n\tdeleteSession as deleteSessionFromStore,\n\tdropLastAssistantError,\n\tgetOrCreateSession,\n\tgetSession,\n\tgetSessionBranch,\n\thashSessionEntries,\n\tlistSessions,\n\treplaceMessages,\n\treplaceSessionTree,\n\ttype SessionState,\n\ttype SessionStaticContext,\n\tsetStaticContext,\n\tswitchSessionLeaf,\n} from \"./session-store.ts\";\n\nexport { loadConfig, type ServerConfig } from \"./config.ts\";\n\ninterface SessionInitBody {\n\tsessionId: string;\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface StreamRequestBody {\n\tsessionId: string;\n\tmodel: Model<any>;\n\toptions?: SimpleStreamOptions;\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionSyncBody {\n\tsessionId: string;\n\tmessages: Message[];\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionAppendBody {\n\tsessionId: string;\n\tmessages: Message[];\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionTreeSyncBody {\n\tsessionId: string;\n\tentries: SessionTreeEntry[];\n\tleafId: string | null;\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionTreeSwitchBody {\n\tsessionId: string;\n\tleafId: string | null;\n}\n\ninterface SessionCompactBody {\n\tsessionId: string;\n\tmodel: Model<any>;\n\toptions?: SimpleStreamOptions;\n\tsettings?: CompactionSettings;\n\tcustomInstructions?: string;\n}\n\nfunction createRequestModels(model: Model<any>, options: SimpleStreamOptions) {\n\tconst models = createModels();\n\tmodels.setProvider(\n\t\tcreateProvider({\n\t\t\tid: model.provider,\n\t\t\tname: model.provider,\n\t\t\tmodels: [model],\n\t\t\tauth: {\n\t\t\t\tapiKey: {\n\t\t\t\t\tname: \"pi-server request auth\",\n\t\t\t\t\tresolve: async () => ({ auth: { apiKey: options.apiKey, headers: options.headers } }),\n\t\t\t\t},\n\t\t\t},\n\t\t\tapi: {\n\t\t\t\tstream: (requestModel, context, streamOptions) => streamSimple(requestModel, context, streamOptions),\n\t\t\t\tstreamSimple: (requestModel, context, streamOptions) => streamSimple(requestModel, context, streamOptions),\n\t\t\t},\n\t\t}),\n\t);\n\treturn models;\n}\n\ninterface SessionIdBody {\n\tsessionId: string;\n}\n\nconst STREAM_HEARTBEAT = \": keep-alive\\n\\n\";\nconst STREAM_HEARTBEAT_INTERVAL_MS = 25_000;\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst chunks: Buffer[] = [];\n\t\treq.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n\t\treq.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n\t\treq.on(\"error\", reject);\n\t});\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n\tconst data = JSON.stringify(body);\n\tres.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(data) });\n\tres.end(data);\n}\n\nfunction logRequestError(req: IncomingMessage, error: unknown): void {\n\tconst message = error instanceof Error ? error.stack || error.message : String(error);\n\tconsole.error(`${req.method ?? \"UNKNOWN\"} ${req.url ?? \"/\"} failed: ${message}`);\n}\n\nfunction authenticate(config: ServerConfig, req: IncomingMessage): boolean {\n\tif (!config.authToken) return true;\n\tconst header = req.headers.authorization;\n\tif (!header) return false;\n\tconst token = header.startsWith(\"Bearer \") ? header.slice(7) : header;\n\treturn token === config.authToken;\n}\n\ninterface ResolvedStream {\n\tmodel: Model<any>;\n\toptions: SimpleStreamOptions;\n}\n\nfunction sessionResponseBody(session: SessionState) {\n\treturn {\n\t\tsessionId: session.sessionId,\n\t\tstaticContextHash: session.staticContextHash,\n\t\ttreeHash: hashSessionEntries(session.entries),\n\t\tmessageCount: session.messages.length,\n\t\tentryCount: session.entries.length,\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t};\n}\n\nfunction persistSession(config: ServerConfig, session: SessionState): void {\n\tsavePersistedSession(config.sessionStoreDir, session);\n}\n\nexport function resolveStreamOptions(\n\t_config: ServerConfig,\n\tmodel: Model<any>,\n\tbody: StreamRequestBody,\n): ResolvedStream {\n\treturn { model, options: { ...(body.options ?? {}) } };\n}\n\nfunction handleSessionInit(config: ServerConfig, body: SessionInitBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t} else {\n\t\tgetOrCreateSession(body.sessionId);\n\t}\n\tconst session = getSession(body.sessionId)!;\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionUpdate(\n\tconfig: ServerConfig,\n\tbody: SessionInitBody & { staticContext: SessionStaticContext },\n\tres: ServerResponse,\n): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.staticContext) {\n\t\tsendJson(res, 400, { error: \"staticContext is required for update\" });\n\t\treturn;\n\t}\n\tsetStaticContext(body.sessionId, body.staticContext);\n\tconst session = getSession(body.sessionId)!;\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionSync(config: ServerConfig, body: SessionSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.messages)) {\n\t\tsendJson(res, 400, { error: \"messages is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = replaceMessages(body.sessionId, body.messages);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionAppend(config: ServerConfig, body: SessionAppendBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.messages)) {\n\t\tsendJson(res, 400, { error: \"messages is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = appendMessages(body.sessionId, body.messages);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeSync(config: ServerConfig, body: SessionTreeSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.entries)) {\n\t\tsendJson(res, 400, { error: \"entries is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = replaceSessionTree(body.sessionId, body.entries, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeAppend(config: ServerConfig, body: SessionTreeSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.entries)) {\n\t\tsendJson(res, 400, { error: \"entries is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = appendSessionEntries(body.sessionId, body.entries, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeSwitch(config: ServerConfig, body: SessionTreeSwitchBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tconst session = switchSessionLeaf(body.sessionId, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nasync function handleSessionCompact(\n\tconfig: ServerConfig,\n\tbody: SessionCompactBody,\n\tres: ServerResponse,\n): Promise<void> {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.model) {\n\t\tsendJson(res, 400, { error: \"model is required\" });\n\t\treturn;\n\t}\n\n\tconst session = getSession(body.sessionId);\n\tif (!session) {\n\t\tsendJson(res, 404, { error: \"session not found\" });\n\t\treturn;\n\t}\n\n\tconst entries = getSessionBranch(session);\n\tconst preparationResult = prepareCompaction(entries, body.settings ?? DEFAULT_COMPACTION_SETTINGS);\n\tif (!preparationResult.ok) {\n\t\tsendJson(res, 400, { error: preparationResult.error.message });\n\t\treturn;\n\t}\n\tif (!preparationResult.value) {\n\t\tsendJson(res, 400, { error: \"Nothing to compact\" });\n\t\treturn;\n\t}\n\n\tconst options = body.options ?? {};\n\tconst result = await compact(\n\t\tpreparationResult.value,\n\t\tcreateRequestModels(body.model, options),\n\t\tbody.model,\n\t\tbody.customInstructions,\n\t\tundefined,\n\t\toptions.reasoning,\n\t);\n\tif (!result.ok) {\n\t\tsendJson(res, 500, { error: result.error.message });\n\t\treturn;\n\t}\n\n\tconst { session: updatedSession, entry: compactionEntry } = appendCompactionEntry(body.sessionId, result.value);\n\tpersistSession(config, updatedSession);\n\tsendJson(res, 200, {\n\t\tsuccess: true,\n\t\tcompaction: result.value satisfies CompactResult,\n\t\tcompactionEntry,\n\t\t...sessionResponseBody(updatedSession),\n\t\tstaticContext: updatedSession.staticContext,\n\t\tentries: updatedSession.entries,\n\t\tmessages: updatedSession.messages,\n\t});\n}\n\nfunction handleDropLastAssistantError(config: ServerConfig, body: SessionIdBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tconst dropped = dropLastAssistantError(body.sessionId);\n\tconst session = getSession(body.sessionId);\n\tif (session) {\n\t\tpersistSession(config, session);\n\t}\n\tconst messageCount = session?.messages.length ?? 0;\n\tsendJson(res, 200, { success: true, dropped, messageCount });\n}\n\nfunction handleSessionHistory(sessionId: string, from: number | undefined, res: ServerResponse): void {\n\tconst session = getSession(sessionId);\n\tif (!session) {\n\t\tsendJson(res, 404, { error: \"session not found\" });\n\t\treturn;\n\t}\n\tconst baseMessageCount = from ?? 0;\n\tsendJson(res, 200, {\n\t\tsessionId: session.sessionId,\n\t\tstaticContext: session.staticContext,\n\t\tstaticContextHash: session.staticContextHash,\n\t\ttreeHash: hashSessionEntries(session.entries),\n\t\tmessageCount: session.messages.length,\n\t\tentryCount: session.entries.length,\n\t\tleafId: session.leafId,\n\t\tentries: session.entries,\n\t\tbaseMessageCount,\n\t\tmessages: session.messages.slice(baseMessageCount),\n\t});\n}\n\nfunction handleStream(config: ServerConfig, body: StreamRequestBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.model) {\n\t\tsendJson(res, 400, { error: \"model is required\" });\n\t\treturn;\n\t}\n\n\tconst session = getOrCreateSession(body.sessionId);\n\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t\tpersistSession(config, session);\n\t}\n\n\tif (!session.staticContext && !body.staticContext) {\n\t\tsendJson(res, 400, { error: \"Session has no static context. Initialize with /api/session/init first.\" });\n\t\treturn;\n\t}\n\n\tconst context: Context = {\n\t\tsystemPrompt: session.staticContext?.systemPrompt,\n\t\tmessages: session.messages,\n\t\ttools: session.staticContext?.tools,\n\t};\n\n\tconst { model: resolvedModel, options: streamOptions } = resolveStreamOptions(config, body.model, body);\n\n\tres.writeHead(200, {\n\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\"Cache-Control\": \"no-cache\",\n\t\tConnection: \"keep-alive\",\n\t});\n\tres.flushHeaders();\n\tres.write(STREAM_HEARTBEAT);\n\n\tconst heartbeat = setInterval(() => {\n\t\tif (!res.writableEnded) {\n\t\t\tres.write(STREAM_HEARTBEAT);\n\t\t}\n\t}, STREAM_HEARTBEAT_INTERVAL_MS);\n\theartbeat.unref();\n\n\tlet stream: AsyncIterable<AssistantMessageEvent>;\n\ttry {\n\t\tstream = streamSimple(resolvedModel, context, streamOptions);\n\t} catch (err) {\n\t\tclearInterval(heartbeat);\n\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\tres.end();\n\t\treturn;\n\t}\n\n\t(async () => {\n\t\ttry {\n\t\t\tfor await (const event of stream) {\n\t\t\t\tconst proxyEvent = toProxyEvent(event);\n\t\t\t\tif (proxyEvent) {\n\t\t\t\t\tres.write(encodeProxyEvent(proxyEvent));\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tclearInterval(heartbeat);\n\t\t}\n\n\t\tres.end();\n\t})().catch((err) => {\n\t\tclearInterval(heartbeat);\n\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\tres.end();\n\t});\n}\n\nasync function handlePostRequest(\n\tconfig: ServerConfig,\n\tpathname: string,\n\tbody: unknown,\n\tres: ServerResponse,\n): Promise<boolean> {\n\tif (pathname === \"/api/session/init\") {\n\t\thandleSessionInit(config, body as SessionInitBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/update\") {\n\t\thandleSessionUpdate(config, body as SessionInitBody & { staticContext: SessionStaticContext }, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/sync\") {\n\t\thandleSessionSync(config, body as SessionSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/append\") {\n\t\thandleSessionAppend(config, body as SessionAppendBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/sync\") {\n\t\thandleSessionTreeSync(config, body as SessionTreeSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/append\") {\n\t\thandleSessionTreeAppend(config, body as SessionTreeSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/switch\") {\n\t\thandleSessionTreeSwitch(config, body as SessionTreeSwitchBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/drop-last-assistant-error\") {\n\t\thandleDropLastAssistantError(config, body as SessionIdBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/compact\") {\n\t\tawait handleSessionCompact(config, body as SessionCompactBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/stream\") {\n\t\thandleStream(config, body as StreamRequestBody, res);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nexport function createPiServer(configOverride?: Partial<ServerConfig>): HttpServer {\n\tconst config = loadConfig(configOverride);\n\tloadPersistedSessions(config.sessionStoreDir);\n\n\tconst server = createServer(async (req, res) => {\n\t\tconst url = new URL(req.url ?? \"/\", `http://${config.host}:${config.port}`);\n\n\t\tif (req.method === \"GET\" && url.pathname === \"/health\") {\n\t\t\tsendJson(res, 200, { status: \"ok\" });\n\t\t\treturn;\n\t\t}\n\n\t\tif (!authenticate(config, req)) {\n\t\t\tsendJson(res, 401, { error: \"Unauthorized\" });\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"GET\" && url.pathname === \"/api/sessions\") {\n\t\t\tsendJson(res, 200, { sessions: listSessions() });\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"GET\" && url.pathname.startsWith(\"/api/session/\") && url.pathname.endsWith(\"/history\")) {\n\t\t\tconst encodedSessionId = url.pathname.slice(\"/api/session/\".length, -\"/history\".length);\n\t\t\tconst fromParam = url.searchParams.get(\"from\");\n\t\t\tconst from = fromParam === null ? undefined : Number(fromParam);\n\t\t\tif (from !== undefined && (!Number.isInteger(from) || from < 0)) {\n\t\t\t\tsendJson(res, 400, { error: \"from must be a non-negative integer\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thandleSessionHistory(decodeURIComponent(encodedSessionId), from, res);\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"POST\" && url.pathname === CHUNK_ENDPOINT) {\n\t\t\ttry {\n\t\t\t\tconst body = JSON.parse(await readBody(req)) as RequestChunkBody;\n\t\t\t\tconst chunkResult = receiveRequestChunk(body);\n\t\t\t\tif (!chunkResult.complete) {\n\t\t\t\t\tsendJson(res, 200, chunkResult.ack);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait handlePostRequest(config, chunkResult.target, JSON.parse(chunkResult.bodyJson) as unknown, res);\n\t\t\t} catch (err) {\n\t\t\t\tlogRequestError(req, err);\n\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\tsendJson(res, 400, { error: err instanceof Error ? err.message : String(err) });\n\t\t\t\t} else {\n\t\t\t\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\t\t\t\tres.end();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"POST\") {\n\t\t\ttry {\n\t\t\t\tconst body = JSON.parse(await readBody(req)) as unknown;\n\t\t\t\tif (await handlePostRequest(config, url.pathname, body, res)) return;\n\t\t\t} catch (err) {\n\t\t\t\tlogRequestError(req, err);\n\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\tsendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });\n\t\t\t\t} else {\n\t\t\t\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\t\t\t\tres.end();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (req.method === \"DELETE\" && url.pathname.startsWith(\"/api/session/\")) {\n\t\t\tconst sessionId = decodeURIComponent(url.pathname.slice(\"/api/session/\".length));\n\t\t\tdeleteSessionFromStore(sessionId);\n\t\t\tdeletePersistedSession(config.sessionStoreDir, sessionId);\n\t\t\tsendJson(res, 200, { deleted: sessionId });\n\t\t\treturn;\n\t\t}\n\n\t\tsendJson(res, 404, { error: \"Not found\" });\n\t});\n\n\treturn server;\n}\n\nfunction toProxyEvent(event: AssistantMessageEvent): ProxyAssistantMessageEvent | undefined {\n\tswitch (event.type) {\n\t\tcase \"start\":\n\t\t\treturn { type: \"start\" };\n\t\tcase \"text_start\":\n\t\t\treturn { type: \"text_start\", contentIndex: event.contentIndex };\n\t\tcase \"text_delta\":\n\t\t\treturn { type: \"text_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"text_end\":\n\t\t\treturn {\n\t\t\t\ttype: \"text_end\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tcontentSignature:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"text\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { textSignature?: string }).textSignature\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\tcase \"thinking_start\":\n\t\t\treturn { type: \"thinking_start\", contentIndex: event.contentIndex };\n\t\tcase \"thinking_delta\":\n\t\t\treturn { type: \"thinking_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"thinking_end\":\n\t\t\treturn {\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tcontentSignature:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"thinking\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { thinkingSignature?: string }).thinkingSignature\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\tcase \"toolcall_start\":\n\t\t\treturn {\n\t\t\t\ttype: \"toolcall_start\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tid:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"toolCall\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { id: string }).id\n\t\t\t\t\t\t: \"\",\n\t\t\t\ttoolName:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"toolCall\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { name: string }).name\n\t\t\t\t\t\t: \"\",\n\t\t\t};\n\t\tcase \"toolcall_delta\":\n\t\t\treturn { type: \"toolcall_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"toolcall_end\":\n\t\t\treturn { type: \"toolcall_end\", contentIndex: event.contentIndex };\n\t\tcase \"done\":\n\t\t\treturn { type: \"done\", reason: event.reason, usage: event.message.usage };\n\t\tcase \"error\":\n\t\t\treturn {\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: event.reason,\n\t\t\t\terrorMessage: event.error.errorMessage,\n\t\t\t\tusage: event.error.usage,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nexport function startServer(configOverride?: Partial<ServerConfig>): HttpServer {\n\tconst config = loadConfig(configOverride);\n\tconst server = createPiServer(configOverride);\n\tserver.listen(config.port, config.host, () => {\n\t\tconsole.log(`pi-server listening on ${config.host}:${config.port}`);\n\t});\n\treturn server;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type Server as HttpServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n\ttype CompactionPreparationOptions,\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\ttype ProxyAssistantMessageEvent,\n\tprepareCompaction,\n\ttype SessionTreeEntry,\n} from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessage,\n\ttype AssistantMessageEvent,\n\ttype Context,\n\tcreateModels,\n\tcreateProvider,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n} from \"@earendil-works/pi-ai\";\nimport { streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport type { ServerConfig } from \"./config.ts\";\nimport { loadConfig } from \"./config.ts\";\nimport { encodeErrorEvent, encodeProxyEvent } from \"./event-encoding.ts\";\nimport { CHUNK_ENDPOINT, type RequestChunkBody, receiveRequestChunk } from \"./request-chunks.ts\";\nimport { deletePersistedSession, loadPersistedSessions, savePersistedSession } from \"./session-persistence.ts\";\nimport {\n\tappendCompactionEntry,\n\tappendMessages,\n\tappendSessionEntries,\n\tdeleteSession as deleteSessionFromStore,\n\tdropLastAssistantError,\n\tgetOrCreateSession,\n\tgetSession,\n\tgetSessionBranch,\n\tlistSessions,\n\treplaceMessages,\n\treplaceSessionTree,\n\ttype SessionState,\n\ttype SessionStaticContext,\n\tsetStaticContext,\n\tswitchSessionLeaf,\n} from \"./session-store.ts\";\n\nexport { loadConfig, type ServerConfig } from \"./config.ts\";\n\ninterface SessionInitBody {\n\tsessionId: string;\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface StreamRequestBody {\n\tsessionId: string;\n\trunId?: string;\n\tmodel: Model<any>;\n\toptions?: SimpleStreamOptions;\n\tstaticContext?: SessionStaticContext;\n\tephemeralMessages?: Message[];\n\tcontextOverlay?: Message[];\n}\n\ninterface SessionSyncBody {\n\tsessionId: string;\n\tmessages: Message[];\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionAppendBody {\n\tsessionId: string;\n\tmessages: Message[];\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionTreeSyncBody {\n\tsessionId: string;\n\tentries: SessionTreeEntry[];\n\tleafId: string | null;\n\tstaticContext?: SessionStaticContext;\n}\n\ninterface SessionTreeSwitchBody {\n\tsessionId: string;\n\tleafId: string | null;\n}\n\ninterface SessionCompactBody {\n\tsessionId: string;\n\tmodel: Model<any>;\n\toptions?: SimpleStreamOptions;\n\tsettings?: CompactionSettings;\n\tpreparation?: CompactionPreparationOptions;\n\tcustomInstructions?: string;\n\tbaseTreeHash?: string;\n\tfullResponse?: boolean;\n}\n\nfunction createRequestModels(model: Model<any>, options: SimpleStreamOptions) {\n\tconst models = createModels();\n\tmodels.setProvider(\n\t\tcreateProvider({\n\t\t\tid: model.provider,\n\t\t\tname: model.provider,\n\t\t\tmodels: [model],\n\t\t\tauth: {\n\t\t\t\tapiKey: {\n\t\t\t\t\tname: \"pi-server request auth\",\n\t\t\t\t\tresolve: async () => ({ auth: { apiKey: options.apiKey, headers: options.headers } }),\n\t\t\t\t},\n\t\t\t},\n\t\t\tapi: {\n\t\t\t\tstream: (requestModel, context, streamOptions) => streamSimple(requestModel, context, streamOptions),\n\t\t\t\tstreamSimple: (requestModel, context, streamOptions) => streamSimple(requestModel, context, streamOptions),\n\t\t\t},\n\t\t}),\n\t);\n\treturn models;\n}\n\ninterface SessionIdBody {\n\tsessionId: string;\n}\n\ninterface StreamRunRecord {\n\tsessionId: string;\n\trunId: string;\n\tstatus: \"running\" | \"completed\" | \"failed\";\n\tevents: ProxyAssistantMessageEvent[];\n\tmessage?: AssistantMessage;\n\terrorMessage?: string;\n\tcreatedAt: number;\n\tupdatedAt: number;\n}\n\nconst STREAM_HEARTBEAT = \": keep-alive\\n\\n\";\nconst STREAM_HEARTBEAT_INTERVAL_MS = 25_000;\nconst streamRuns = new Map<string, StreamRunRecord>();\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst chunks: Buffer[] = [];\n\t\treq.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n\t\treq.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n\t\treq.on(\"error\", reject);\n\t});\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n\tconst data = JSON.stringify(body);\n\tres.writeHead(status, { \"Content-Type\": \"application/json\", \"Content-Length\": Buffer.byteLength(data) });\n\tres.end(data);\n}\n\nfunction logRequestError(req: IncomingMessage, error: unknown): void {\n\tconst message = error instanceof Error ? error.stack || error.message : String(error);\n\tconsole.error(`${req.method ?? \"UNKNOWN\"} ${req.url ?? \"/\"} failed: ${message}`);\n}\n\nfunction authenticate(config: ServerConfig, req: IncomingMessage): boolean {\n\tif (!config.authToken) return true;\n\tconst header = req.headers.authorization;\n\tif (!header) return false;\n\tconst token = header.startsWith(\"Bearer \") ? header.slice(7) : header;\n\treturn token === config.authToken;\n}\n\ninterface ResolvedStream {\n\tmodel: Model<any>;\n\toptions: SimpleStreamOptions;\n}\n\nfunction sessionResponseBody(session: SessionState) {\n\treturn {\n\t\tsessionId: session.sessionId,\n\t\tstaticContextHash: session.staticContextHash,\n\t\ttreeHash: session.treeHash,\n\t\tmessageCount: session.messages.length,\n\t\tentryCount: session.entries.length,\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t};\n}\n\nfunction persistSession(config: ServerConfig, session: SessionState): void {\n\tsavePersistedSession(config.sessionStoreDir, session);\n}\n\nfunction runKey(sessionId: string, runId: string): string {\n\treturn `${sessionId}\\0${runId}`;\n}\n\nfunction getStreamRun(sessionId: string, runId: string): StreamRunRecord | undefined {\n\treturn streamRuns.get(runKey(sessionId, runId));\n}\n\nfunction startStreamRun(sessionId: string, runId: string): StreamRunRecord {\n\tconst existing = getStreamRun(sessionId, runId);\n\tif (existing?.status === \"completed\" || existing?.status === \"failed\") return existing;\n\tconst now = Date.now();\n\tconst run: StreamRunRecord = existing ?? {\n\t\tsessionId,\n\t\trunId,\n\t\tstatus: \"running\",\n\t\tevents: [],\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t};\n\trun.status = \"running\";\n\trun.updatedAt = now;\n\tstreamRuns.set(runKey(sessionId, runId), run);\n\treturn run;\n}\n\nfunction recordStreamRunEvent(run: StreamRunRecord | undefined, event: ProxyAssistantMessageEvent): void {\n\tif (!run) return;\n\trun.events.push(event);\n\trun.updatedAt = Date.now();\n}\n\nfunction completeStreamRun(run: StreamRunRecord | undefined, message: AssistantMessage): void {\n\tif (!run) return;\n\trun.status = \"completed\";\n\trun.message = message;\n\trun.errorMessage = undefined;\n\trun.updatedAt = Date.now();\n}\n\nfunction failStreamRun(run: StreamRunRecord | undefined, errorMessage: string): void {\n\tif (!run) return;\n\trun.status = \"failed\";\n\trun.errorMessage = errorMessage;\n\trun.updatedAt = Date.now();\n}\n\nfunction sessionHistoryFullResponseBody(session: SessionState, baseMessageCount: number) {\n\treturn {\n\t\tsessionId: session.sessionId,\n\t\tstaticContext: session.staticContext,\n\t\tstaticContextHash: session.staticContextHash,\n\t\ttreeHash: session.treeHash,\n\t\tmessageCount: session.messages.length,\n\t\tentryCount: session.entries.length,\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t\tentries: session.entries,\n\t\tbaseMessageCount,\n\t\tmessages: session.messages.slice(baseMessageCount),\n\t};\n}\n\nfunction sessionTreePatchResponseBody(\n\tsession: SessionState,\n\tbaseMessageCount: number,\n\tentriesFrom: number,\n\tbaseRevision: number | undefined,\n) {\n\treturn {\n\t\tsessionId: session.sessionId,\n\t\tstaticContext: session.staticContext,\n\t\tstaticContextHash: session.staticContextHash,\n\t\ttreeHash: session.treeHash,\n\t\tmessageCount: session.messages.length,\n\t\tentryCount: session.entries.length,\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t\tbaseMessageCount,\n\t\tmessages: session.messages.slice(baseMessageCount),\n\t\ttreePatch: {\n\t\t\tentriesFrom,\n\t\t\tbaseRevision,\n\t\t\tentries: session.entries.slice(entriesFrom),\n\t\t\tleafId: session.leafId,\n\t\t\trevision: session.revision,\n\t\t},\n\t};\n}\n\nexport function resolveStreamOptions(\n\t_config: ServerConfig,\n\tmodel: Model<any>,\n\tbody: StreamRequestBody,\n): ResolvedStream {\n\treturn { model, options: { ...(body.options ?? {}) } };\n}\n\nfunction handleSessionInit(config: ServerConfig, body: SessionInitBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t} else {\n\t\tgetOrCreateSession(body.sessionId);\n\t}\n\tconst session = getSession(body.sessionId)!;\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionUpdate(\n\tconfig: ServerConfig,\n\tbody: SessionInitBody & { staticContext: SessionStaticContext },\n\tres: ServerResponse,\n): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.staticContext) {\n\t\tsendJson(res, 400, { error: \"staticContext is required for update\" });\n\t\treturn;\n\t}\n\tsetStaticContext(body.sessionId, body.staticContext);\n\tconst session = getSession(body.sessionId)!;\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionSync(config: ServerConfig, body: SessionSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.messages)) {\n\t\tsendJson(res, 400, { error: \"messages is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = replaceMessages(body.sessionId, body.messages);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionAppend(config: ServerConfig, body: SessionAppendBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.messages)) {\n\t\tsendJson(res, 400, { error: \"messages is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = appendMessages(body.sessionId, body.messages);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeSync(config: ServerConfig, body: SessionTreeSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.entries)) {\n\t\tsendJson(res, 400, { error: \"entries is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = replaceSessionTree(body.sessionId, body.entries, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeAppend(config: ServerConfig, body: SessionTreeSyncBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!Array.isArray(body.entries)) {\n\t\tsendJson(res, 400, { error: \"entries is required\" });\n\t\treturn;\n\t}\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t}\n\tconst session = appendSessionEntries(body.sessionId, body.entries, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nfunction handleSessionTreeSwitch(config: ServerConfig, body: SessionTreeSwitchBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tconst session = switchSessionLeaf(body.sessionId, body.leafId ?? null);\n\tpersistSession(config, session);\n\tsendJson(res, 200, sessionResponseBody(session));\n}\n\nasync function handleSessionCompact(\n\tconfig: ServerConfig,\n\tbody: SessionCompactBody,\n\tres: ServerResponse,\n): Promise<void> {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.model) {\n\t\tsendJson(res, 400, { error: \"model is required\" });\n\t\treturn;\n\t}\n\n\tconst session = getSession(body.sessionId);\n\tif (!session) {\n\t\tsendJson(res, 404, { error: \"session not found\" });\n\t\treturn;\n\t}\n\n\tconst entries = getSessionBranch(session);\n\tconst preparationResult = prepareCompaction(entries, body.settings ?? DEFAULT_COMPACTION_SETTINGS, body.preparation);\n\tif (!preparationResult.ok) {\n\t\tsendJson(res, 400, { error: preparationResult.error.message });\n\t\treturn;\n\t}\n\tif (!preparationResult.value) {\n\t\tsendJson(res, 400, { error: \"Nothing to compact\" });\n\t\treturn;\n\t}\n\n\tconst options = body.options ?? {};\n\tconst result = await compact(\n\t\tpreparationResult.value,\n\t\tcreateRequestModels(body.model, options),\n\t\tbody.model,\n\t\tbody.customInstructions,\n\t\tundefined,\n\t\toptions.reasoning,\n\t);\n\tif (!result.ok) {\n\t\tsendJson(res, 500, { error: result.error.message });\n\t\treturn;\n\t}\n\n\tconst baseTreeHash = session.treeHash;\n\tconst baseEntryCount = session.entries.length;\n\tconst { session: updatedSession, entry: compactionEntry } = appendCompactionEntry(body.sessionId, result.value);\n\tpersistSession(config, updatedSession);\n\tif (!body.fullResponse && body.baseTreeHash === baseTreeHash) {\n\t\tsendJson(res, 200, {\n\t\t\tsuccess: true,\n\t\t\tcompaction: result.value satisfies CompactResult,\n\t\t\tcompactionEntry,\n\t\t\t...sessionResponseBody(updatedSession),\n\t\t\tstaticContext: updatedSession.staticContext,\n\t\t\ttreePatch: {\n\t\t\t\tbaseTreeHash,\n\t\t\t\tentriesFrom: baseEntryCount,\n\t\t\t\tentries: [compactionEntry],\n\t\t\t\tleafId: updatedSession.leafId,\n\t\t\t\trevision: updatedSession.revision,\n\t\t\t},\n\t\t});\n\t\treturn;\n\t}\n\tsendJson(res, 200, {\n\t\tsuccess: true,\n\t\tcompaction: result.value satisfies CompactResult,\n\t\tcompactionEntry,\n\t\t...sessionResponseBody(updatedSession),\n\t\tstaticContext: updatedSession.staticContext,\n\t\tentries: updatedSession.entries,\n\t\tmessages: updatedSession.messages,\n\t});\n}\n\nfunction handleDropLastAssistantError(config: ServerConfig, body: SessionIdBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tconst dropped = dropLastAssistantError(body.sessionId);\n\tconst session = getSession(body.sessionId);\n\tif (session) {\n\t\tpersistSession(config, session);\n\t}\n\tconst messageCount = session?.messages.length ?? 0;\n\tsendJson(res, 200, { success: true, dropped, messageCount });\n}\n\nfunction handleSessionHistory(\n\tsessionId: string,\n\tfrom: number | undefined,\n\tentriesFrom: number | undefined,\n\trevision: number | undefined,\n\tbaseTreeHash: string | undefined,\n\tres: ServerResponse,\n): void {\n\tconst session = getSession(sessionId);\n\tif (!session) {\n\t\tsendJson(res, 404, { error: \"session not found\" });\n\t\treturn;\n\t}\n\tconst baseMessageCount = from ?? 0;\n\tif (\n\t\tentriesFrom !== undefined &&\n\t\tentriesFrom <= session.entries.length &&\n\t\t(revision === undefined || revision <= session.revision) &&\n\t\t(baseTreeHash === undefined || baseTreeHash === session.prefixHashes[entriesFrom])\n\t) {\n\t\tsendJson(res, 200, sessionTreePatchResponseBody(session, baseMessageCount, entriesFrom, revision));\n\t\treturn;\n\t}\n\tsendJson(res, 200, sessionHistoryFullResponseBody(session, baseMessageCount));\n}\n\nfunction handleSessionRun(sessionId: string, runId: string, res: ServerResponse): void {\n\tconst run = getStreamRun(sessionId, runId);\n\tif (!run) {\n\t\tsendJson(res, 404, { error: \"run not found\" });\n\t\treturn;\n\t}\n\tsendJson(res, 200, run);\n}\n\nexport function buildStreamContext(\n\tsession: SessionState,\n\tbody: Pick<StreamRequestBody, \"contextOverlay\" | \"ephemeralMessages\">,\n): Context {\n\tconst messages = body.contextOverlay ?? [...session.messages, ...(body.ephemeralMessages ?? [])];\n\treturn {\n\t\tsystemPrompt: session.staticContext?.systemPrompt,\n\t\tmessages,\n\t\ttools: session.staticContext?.tools,\n\t};\n}\n\nfunction handleStream(config: ServerConfig, body: StreamRequestBody, res: ServerResponse): void {\n\tif (!body.sessionId) {\n\t\tsendJson(res, 400, { error: \"sessionId is required\" });\n\t\treturn;\n\t}\n\tif (!body.model) {\n\t\tsendJson(res, 400, { error: \"model is required\" });\n\t\treturn;\n\t}\n\n\tconst session = getOrCreateSession(body.sessionId);\n\n\tif (body.staticContext) {\n\t\tsetStaticContext(body.sessionId, body.staticContext);\n\t\tpersistSession(config, session);\n\t}\n\n\tif (!session.staticContext && !body.staticContext) {\n\t\tsendJson(res, 400, { error: \"Session has no static context. Initialize with /api/session/init first.\" });\n\t\treturn;\n\t}\n\n\tif (body.ephemeralMessages !== undefined && !Array.isArray(body.ephemeralMessages)) {\n\t\tsendJson(res, 400, { error: \"ephemeralMessages must be an array\" });\n\t\treturn;\n\t}\n\tif (body.contextOverlay !== undefined && !Array.isArray(body.contextOverlay)) {\n\t\tsendJson(res, 400, { error: \"contextOverlay must be an array\" });\n\t\treturn;\n\t}\n\n\tconst context = buildStreamContext(session, body);\n\tconst existingRun = body.runId ? getStreamRun(body.sessionId, body.runId) : undefined;\n\n\tconst { model: resolvedModel, options: streamOptions } = resolveStreamOptions(config, body.model, body);\n\n\tres.writeHead(200, {\n\t\t\"Content-Type\": \"text/event-stream\",\n\t\t\"Cache-Control\": \"no-cache\",\n\t\tConnection: \"keep-alive\",\n\t});\n\tres.flushHeaders();\n\tres.write(STREAM_HEARTBEAT);\n\n\tif (existingRun?.status === \"completed\") {\n\t\tfor (const event of existingRun.events) {\n\t\t\tres.write(encodeProxyEvent(event));\n\t\t}\n\t\tres.end();\n\t\treturn;\n\t}\n\n\tconst run = body.runId ? startStreamRun(body.sessionId, body.runId) : undefined;\n\n\tconst heartbeat = setInterval(() => {\n\t\tif (!res.writableEnded) {\n\t\t\tres.write(STREAM_HEARTBEAT);\n\t\t}\n\t}, STREAM_HEARTBEAT_INTERVAL_MS);\n\theartbeat.unref();\n\n\tlet stream: AsyncIterable<AssistantMessageEvent>;\n\ttry {\n\t\tstream = streamSimple(resolvedModel, context, streamOptions);\n\t} catch (err) {\n\t\tclearInterval(heartbeat);\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tfailStreamRun(run, message);\n\t\tres.write(encodeErrorEvent(message));\n\t\tres.end();\n\t\treturn;\n\t}\n\n\t(async () => {\n\t\ttry {\n\t\t\tfor await (const event of stream) {\n\t\t\t\tconst proxyEvent = toProxyEvent(event);\n\t\t\t\tif (proxyEvent) {\n\t\t\t\t\trecordStreamRunEvent(run, proxyEvent);\n\t\t\t\t\tres.write(encodeProxyEvent(proxyEvent));\n\t\t\t\t}\n\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\tcompleteStreamRun(run, event.message);\n\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\tfailStreamRun(run, event.error.errorMessage ?? event.reason);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tclearInterval(heartbeat);\n\t\t}\n\n\t\tres.end();\n\t})().catch((err) => {\n\t\tclearInterval(heartbeat);\n\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\tfailStreamRun(run, message);\n\t\tres.write(encodeErrorEvent(message));\n\t\tres.end();\n\t});\n}\n\nasync function handlePostRequest(\n\tconfig: ServerConfig,\n\tpathname: string,\n\tbody: unknown,\n\tres: ServerResponse,\n): Promise<boolean> {\n\tif (pathname === \"/api/session/init\") {\n\t\thandleSessionInit(config, body as SessionInitBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/update\") {\n\t\thandleSessionUpdate(config, body as SessionInitBody & { staticContext: SessionStaticContext }, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/sync\") {\n\t\thandleSessionSync(config, body as SessionSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/append\") {\n\t\thandleSessionAppend(config, body as SessionAppendBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/sync\") {\n\t\thandleSessionTreeSync(config, body as SessionTreeSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/append\") {\n\t\thandleSessionTreeAppend(config, body as SessionTreeSyncBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/tree/switch\") {\n\t\thandleSessionTreeSwitch(config, body as SessionTreeSwitchBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/drop-last-assistant-error\") {\n\t\thandleDropLastAssistantError(config, body as SessionIdBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/session/compact\") {\n\t\tawait handleSessionCompact(config, body as SessionCompactBody, res);\n\t\treturn true;\n\t}\n\n\tif (pathname === \"/api/stream\") {\n\t\thandleStream(config, body as StreamRequestBody, res);\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nexport function createPiServer(configOverride?: Partial<ServerConfig>): HttpServer {\n\tconst config = loadConfig(configOverride);\n\tloadPersistedSessions(config.sessionStoreDir);\n\n\tconst server = createServer(async (req, res) => {\n\t\tconst url = new URL(req.url ?? \"/\", `http://${config.host}:${config.port}`);\n\n\t\tif (req.method === \"GET\" && url.pathname === \"/health\") {\n\t\t\tsendJson(res, 200, { status: \"ok\" });\n\t\t\treturn;\n\t\t}\n\n\t\tif (!authenticate(config, req)) {\n\t\t\tsendJson(res, 401, { error: \"Unauthorized\" });\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"GET\" && url.pathname === \"/api/sessions\") {\n\t\t\tsendJson(res, 200, { sessions: listSessions() });\n\t\t\treturn;\n\t\t}\n\n\t\tconst runMatch = /^\\/api\\/session\\/([^/]+)\\/runs\\/([^/]+)$/.exec(url.pathname);\n\t\tif (req.method === \"GET\" && runMatch) {\n\t\t\thandleSessionRun(decodeURIComponent(runMatch[1]), decodeURIComponent(runMatch[2]), res);\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"GET\" && url.pathname.startsWith(\"/api/session/\") && url.pathname.endsWith(\"/history\")) {\n\t\t\tconst encodedSessionId = url.pathname.slice(\"/api/session/\".length, -\"/history\".length);\n\t\t\tconst fromParam = url.searchParams.get(\"from\");\n\t\t\tconst from = fromParam === null ? undefined : Number(fromParam);\n\t\t\tif (from !== undefined && (!Number.isInteger(from) || from < 0)) {\n\t\t\t\tsendJson(res, 400, { error: \"from must be a non-negative integer\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entriesFromParam = url.searchParams.get(\"entriesFrom\");\n\t\t\tconst entriesFrom = entriesFromParam === null ? undefined : Number(entriesFromParam);\n\t\t\tif (entriesFrom !== undefined && (!Number.isInteger(entriesFrom) || entriesFrom < 0)) {\n\t\t\t\tsendJson(res, 400, { error: \"entriesFrom must be a non-negative integer\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst revisionParam = url.searchParams.get(\"revision\");\n\t\t\tconst revision = revisionParam === null ? undefined : Number(revisionParam);\n\t\t\tif (revision !== undefined && (!Number.isInteger(revision) || revision < 0)) {\n\t\t\t\tsendJson(res, 400, { error: \"revision must be a non-negative integer\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thandleSessionHistory(\n\t\t\t\tdecodeURIComponent(encodedSessionId),\n\t\t\t\tfrom,\n\t\t\t\tentriesFrom,\n\t\t\t\trevision,\n\t\t\t\turl.searchParams.get(\"baseTreeHash\") ?? undefined,\n\t\t\t\tres,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"POST\" && url.pathname === CHUNK_ENDPOINT) {\n\t\t\ttry {\n\t\t\t\tconst body = JSON.parse(await readBody(req)) as RequestChunkBody;\n\t\t\t\tconst chunkResult = receiveRequestChunk(body);\n\t\t\t\tif (!chunkResult.complete) {\n\t\t\t\t\tsendJson(res, 200, chunkResult.ack);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait handlePostRequest(config, chunkResult.target, JSON.parse(chunkResult.bodyJson) as unknown, res);\n\t\t\t} catch (err) {\n\t\t\t\tlogRequestError(req, err);\n\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\tsendJson(res, 400, { error: err instanceof Error ? err.message : String(err) });\n\t\t\t\t} else {\n\t\t\t\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\t\t\t\tres.end();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (req.method === \"POST\") {\n\t\t\ttry {\n\t\t\t\tconst body = JSON.parse(await readBody(req)) as unknown;\n\t\t\t\tif (await handlePostRequest(config, url.pathname, body, res)) return;\n\t\t\t} catch (err) {\n\t\t\t\tlogRequestError(req, err);\n\t\t\t\tif (!res.headersSent) {\n\t\t\t\t\tsendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });\n\t\t\t\t} else {\n\t\t\t\t\tres.write(encodeErrorEvent(err instanceof Error ? err.message : String(err)));\n\t\t\t\t\tres.end();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (req.method === \"DELETE\" && url.pathname.startsWith(\"/api/session/\")) {\n\t\t\tconst sessionId = decodeURIComponent(url.pathname.slice(\"/api/session/\".length));\n\t\t\tdeleteSessionFromStore(sessionId);\n\t\t\tdeletePersistedSession(config.sessionStoreDir, sessionId);\n\t\t\tsendJson(res, 200, { deleted: sessionId });\n\t\t\treturn;\n\t\t}\n\n\t\tsendJson(res, 404, { error: \"Not found\" });\n\t});\n\n\treturn server;\n}\n\nfunction toProxyEvent(event: AssistantMessageEvent): ProxyAssistantMessageEvent | undefined {\n\tswitch (event.type) {\n\t\tcase \"start\":\n\t\t\treturn { type: \"start\" };\n\t\tcase \"text_start\":\n\t\t\treturn { type: \"text_start\", contentIndex: event.contentIndex };\n\t\tcase \"text_delta\":\n\t\t\treturn { type: \"text_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"text_end\":\n\t\t\treturn {\n\t\t\t\ttype: \"text_end\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tcontentSignature:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"text\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { textSignature?: string }).textSignature\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\tcase \"thinking_start\":\n\t\t\treturn { type: \"thinking_start\", contentIndex: event.contentIndex };\n\t\tcase \"thinking_delta\":\n\t\t\treturn { type: \"thinking_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"thinking_end\":\n\t\t\treturn {\n\t\t\t\ttype: \"thinking_end\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tcontentSignature:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"thinking\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { thinkingSignature?: string }).thinkingSignature\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\tcase \"toolcall_start\":\n\t\t\treturn {\n\t\t\t\ttype: \"toolcall_start\",\n\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\tid:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"toolCall\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { id: string }).id\n\t\t\t\t\t\t: \"\",\n\t\t\t\ttoolName:\n\t\t\t\t\tevent.partial.content[event.contentIndex]?.type === \"toolCall\"\n\t\t\t\t\t\t? (event.partial.content[event.contentIndex] as { name: string }).name\n\t\t\t\t\t\t: \"\",\n\t\t\t};\n\t\tcase \"toolcall_delta\":\n\t\t\treturn { type: \"toolcall_delta\", contentIndex: event.contentIndex, delta: event.delta };\n\t\tcase \"toolcall_end\":\n\t\t\treturn { type: \"toolcall_end\", contentIndex: event.contentIndex };\n\t\tcase \"done\":\n\t\t\treturn { type: \"done\", reason: event.reason, usage: event.message.usage };\n\t\tcase \"error\":\n\t\t\treturn {\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: event.reason,\n\t\t\t\terrorMessage: event.error.errorMessage,\n\t\t\t\tusage: event.error.usage,\n\t\t\t};\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nexport function startServer(configOverride?: Partial<ServerConfig>): HttpServer {\n\tconst config = loadConfig(configOverride);\n\tconst server = createPiServer(configOverride);\n\tserver.listen(config.port, config.host, () => {\n\t\tconsole.log(`pi-server listening on ${config.host}:${config.port}`);\n\t});\n\treturn server;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-persistence.d.ts","sourceRoot":"","sources":["../src/session-persistence.ts"],"names":[],"mappings":"AAIA,OAAO,EAIN,KAAK,YAAY,EAEjB,MAAM,oBAAoB,CAAC;AAsI5B,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAanE;AAED,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAezF;AAED,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAEvF","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SessionTreeEntry } from \"@earendil-works/pi-agent-core\";\nimport {\n\texportSessionState,\n\ttype PersistedSessionState,\n\trestoreSessionState,\n\ttype SessionState,\n\ttype SessionStaticContext,\n} from \"./session-store.ts\";\n\nconst PERSISTED_SESSION_VERSION = 1;\nconst REPLACE_RETRY_DELAYS_MS = [25, 50, 100, 200, 400];\n\ninterface PersistedSessionFile {\n\tversion: 1;\n\tsession: PersistedSessionState;\n}\n\nfunction sessionFileName(sessionId: string): string {\n\treturn `${createHash(\"sha256\").update(sessionId).digest(\"hex\")}.json`;\n}\n\nfunction sessionPath(sessionStoreDir: string, sessionId: string): string {\n\treturn join(sessionStoreDir, sessionFileName(sessionId));\n}\n\nfunction isRetryableRenameError(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn process.platform === \"win32\" && code === \"EPERM\";\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction replaceFileSync(sourcePath: string, targetPath: string): void {\n\tfor (let attempt = 0; attempt <= REPLACE_RETRY_DELAYS_MS.length; attempt++) {\n\t\ttry {\n\t\t\trenameSync(sourcePath, targetPath);\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tif (!isRetryableRenameError(error) || attempt === REPLACE_RETRY_DELAYS_MS.length) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tsleepSync(REPLACE_RETRY_DELAYS_MS[attempt]);\n\t\t}\n\t}\n}\n\nfunction assertRecord(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertString(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string`);\n\t}\n}\n\nfunction assertNumber(value: unknown, path: string): asserts value is number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new Error(`${path} must be a finite number`);\n\t}\n}\n\nfunction assertNullableString(value: unknown, path: string): asserts value is string | null {\n\tif (value !== null && typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string or null`);\n\t}\n}\n\nfunction assertStaticContext(value: unknown): asserts value is SessionStaticContext | undefined {\n\tif (value === undefined) return;\n\tassertRecord(value, \"session.staticContext\");\n\tconst systemPrompt = value.systemPrompt;\n\tif (systemPrompt !== undefined && typeof systemPrompt !== \"string\") {\n\t\tthrow new Error(\"session.staticContext.systemPrompt must be a string\");\n\t}\n\tconst tools = value.tools;\n\tif (tools !== undefined) {\n\t\tif (!Array.isArray(tools)) {\n\t\t\tthrow new Error(\"session.staticContext.tools must be an array\");\n\t\t}\n\t\tfor (const [index, tool] of tools.entries()) {\n\t\t\tassertRecord(tool, `session.staticContext.tools[${index}]`);\n\t\t\tassertString(tool.name, `session.staticContext.tools[${index}].name`);\n\t\t\tassertString(tool.description, `session.staticContext.tools[${index}].description`);\n\t\t\tif (tool.parameters === undefined) {\n\t\t\t\tthrow new Error(`session.staticContext.tools[${index}].parameters is required`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction assertSessionTreeEntries(value: unknown): asserts value is SessionTreeEntry[] {\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(\"session.entries must be an array\");\n\t}\n\tfor (const [index, entry] of value.entries()) {\n\t\tassertRecord(entry, `session.entries[${index}]`);\n\t\tassertString(entry.type, `session.entries[${index}].type`);\n\t\tassertString(entry.id, `session.entries[${index}].id`);\n\t\tassertNullableString(entry.parentId, `session.entries[${index}].parentId`);\n\t\tassertString(entry.timestamp, `session.entries[${index}].timestamp`);\n\t\tif (entry.type === \"message\") {\n\t\t\tassertRecord(entry.message, `session.entries[${index}].message`);\n\t\t}\n\t}\n}\n\nfunction assertPersistedSessionState(value: unknown): asserts value is PersistedSessionState {\n\tassertRecord(value, \"session\");\n\tassertString(value.sessionId, \"session.sessionId\");\n\tassertStaticContext(value.staticContext);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, \"session.leafId\");\n\tassertNumber(value.revision, \"session.revision\");\n\tassertNumber(value.createdAt, \"session.createdAt\");\n\tassertNumber(value.updatedAt, \"session.updatedAt\");\n}\n\nfunction parsePersistedSessionFile(raw: string, sourcePath: string): PersistedSessionFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session file contains invalid JSON: ${sourcePath}`, { cause: error });\n\t}\n\tassertRecord(parsed, \"persisted session file\");\n\tif (parsed.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session version in ${sourcePath}`);\n\t}\n\tassertPersistedSessionState(parsed.session);\n\treturn {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: parsed.session,\n\t};\n}\n\nexport function loadPersistedSessions(sessionStoreDir: string): void {\n\tif (!existsSync(sessionStoreDir)) return;\n\tconst entries = readdirSync(sessionStoreDir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".json\")) continue;\n\t\tconst filePath = join(sessionStoreDir, entry.name);\n\t\tconst persisted = parsePersistedSessionFile(readFileSync(filePath, \"utf-8\"), filePath);\n\t\tconst expectedFileName = sessionFileName(persisted.session.sessionId);\n\t\tif (entry.name !== expectedFileName) {\n\t\t\tthrow new Error(`Persisted session file name does not match sessionId: ${filePath}`);\n\t\t}\n\t\trestoreSessionState(persisted.session);\n\t}\n}\n\nexport function savePersistedSession(sessionStoreDir: string, session: SessionState): void {\n\tmkdirSync(sessionStoreDir, { recursive: true });\n\tconst filePath = sessionPath(sessionStoreDir, session.sessionId);\n\tconst tempPath = `${filePath}.${randomUUID()}.tmp`;\n\tconst body: PersistedSessionFile = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: exportSessionState(session),\n\t};\n\ttry {\n\t\twriteFileSync(tempPath, JSON.stringify(body), \"utf-8\");\n\t\treplaceFileSync(tempPath, filePath);\n\t} catch (error) {\n\t\trmSync(tempPath, { force: true });\n\t\tthrow error;\n\t}\n}\n\nexport function deletePersistedSession(sessionStoreDir: string, sessionId: string): void {\n\trmSync(sessionPath(sessionStoreDir, sessionId), { force: true });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-persistence.d.ts","sourceRoot":"","sources":["../src/session-persistence.ts"],"names":[],"mappings":"AAaA,OAAO,EAKN,KAAK,YAAY,EAEjB,MAAM,oBAAoB,CAAC;AA8N5B,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAkBnE;AAkCD,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAazF;AAED,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAIvF","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport {\n\tappendFileSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SessionTreeEntry } from \"@earendil-works/pi-agent-core\";\nimport {\n\texportSessionState,\n\tmarkSessionPersisted,\n\ttype PersistedSessionState,\n\trestoreSessionState,\n\ttype SessionState,\n\ttype SessionStaticContext,\n} from \"./session-store.ts\";\n\nconst PERSISTED_SESSION_VERSION = 1;\nconst WAL_SNAPSHOT_INTERVAL = 32;\nconst REPLACE_RETRY_DELAYS_MS = [25, 50, 100, 200, 400];\n\ninterface PersistedSessionFile {\n\tversion: 1;\n\tsession: PersistedSessionState;\n}\n\ninterface PersistedSessionWalRecord {\n\tversion: 1;\n\tsessionId: string;\n\tbaseEntryCount: number;\n\tentries: SessionTreeEntry[];\n\tleafId: string | null;\n\trevision: number;\n\tupdatedAt: number;\n\tstaticContext: SessionStaticContext | undefined;\n}\n\ninterface PersistedSessionMeta {\n\tentryCount: number;\n\twalRecords: number;\n}\n\nconst persistedSessions = new Map<string, PersistedSessionMeta>();\n\nfunction sessionFileName(sessionId: string): string {\n\treturn `${createHash(\"sha256\").update(sessionId).digest(\"hex\")}.json`;\n}\n\nfunction sessionPath(sessionStoreDir: string, sessionId: string): string {\n\treturn join(sessionStoreDir, sessionFileName(sessionId));\n}\n\nfunction walPath(sessionStoreDir: string, sessionId: string): string {\n\treturn `${sessionPath(sessionStoreDir, sessionId)}.wal`;\n}\n\nfunction persistedSessionKey(sessionStoreDir: string, sessionId: string): string {\n\treturn `${sessionStoreDir}\\0${sessionId}`;\n}\n\nfunction isRetryableRenameError(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn process.platform === \"win32\" && code === \"EPERM\";\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction replaceFileSync(sourcePath: string, targetPath: string): void {\n\tfor (let attempt = 0; attempt <= REPLACE_RETRY_DELAYS_MS.length; attempt++) {\n\t\ttry {\n\t\t\trenameSync(sourcePath, targetPath);\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tif (!isRetryableRenameError(error) || attempt === REPLACE_RETRY_DELAYS_MS.length) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tsleepSync(REPLACE_RETRY_DELAYS_MS[attempt]);\n\t\t}\n\t}\n}\n\nfunction assertRecord(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertString(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string`);\n\t}\n}\n\nfunction assertNumber(value: unknown, path: string): asserts value is number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new Error(`${path} must be a finite number`);\n\t}\n}\n\nfunction assertNullableString(value: unknown, path: string): asserts value is string | null {\n\tif (value !== null && typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string or null`);\n\t}\n}\n\nfunction assertStaticContext(value: unknown): asserts value is SessionStaticContext | undefined {\n\tif (value === undefined) return;\n\tassertRecord(value, \"session.staticContext\");\n\tconst systemPrompt = value.systemPrompt;\n\tif (systemPrompt !== undefined && typeof systemPrompt !== \"string\") {\n\t\tthrow new Error(\"session.staticContext.systemPrompt must be a string\");\n\t}\n\tconst tools = value.tools;\n\tif (tools !== undefined) {\n\t\tif (!Array.isArray(tools)) {\n\t\t\tthrow new Error(\"session.staticContext.tools must be an array\");\n\t\t}\n\t\tfor (const [index, tool] of tools.entries()) {\n\t\t\tassertRecord(tool, `session.staticContext.tools[${index}]`);\n\t\t\tassertString(tool.name, `session.staticContext.tools[${index}].name`);\n\t\t\tassertString(tool.description, `session.staticContext.tools[${index}].description`);\n\t\t\tif (tool.parameters === undefined) {\n\t\t\t\tthrow new Error(`session.staticContext.tools[${index}].parameters is required`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction assertSessionTreeEntries(value: unknown): asserts value is SessionTreeEntry[] {\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(\"session.entries must be an array\");\n\t}\n\tfor (const [index, entry] of value.entries()) {\n\t\tassertRecord(entry, `session.entries[${index}]`);\n\t\tassertString(entry.type, `session.entries[${index}].type`);\n\t\tassertString(entry.id, `session.entries[${index}].id`);\n\t\tassertNullableString(entry.parentId, `session.entries[${index}].parentId`);\n\t\tassertString(entry.timestamp, `session.entries[${index}].timestamp`);\n\t\tif (entry.type === \"message\") {\n\t\t\tassertRecord(entry.message, `session.entries[${index}].message`);\n\t\t}\n\t}\n}\n\nfunction assertPersistedSessionState(value: unknown): asserts value is PersistedSessionState {\n\tassertRecord(value, \"session\");\n\tassertString(value.sessionId, \"session.sessionId\");\n\tassertStaticContext(value.staticContext);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, \"session.leafId\");\n\tassertNumber(value.revision, \"session.revision\");\n\tassertNumber(value.createdAt, \"session.createdAt\");\n\tassertNumber(value.updatedAt, \"session.updatedAt\");\n}\n\nfunction assertPersistedWalRecord(\n\tvalue: unknown,\n\tsourcePath: string,\n\tlineNumber: number,\n): asserts value is PersistedSessionWalRecord {\n\tconst path = `${sourcePath}:${lineNumber}`;\n\tassertRecord(value, path);\n\tif (value.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session WAL version in ${path}`);\n\t}\n\tassertString(value.sessionId, `${path}.sessionId`);\n\tassertNumber(value.baseEntryCount, `${path}.baseEntryCount`);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, `${path}.leafId`);\n\tassertNumber(value.revision, `${path}.revision`);\n\tassertNumber(value.updatedAt, `${path}.updatedAt`);\n\tassertStaticContext(value.staticContext);\n}\n\nfunction parsePersistedSessionFile(raw: string, sourcePath: string): PersistedSessionFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session file contains invalid JSON: ${sourcePath}`, { cause: error });\n\t}\n\tassertRecord(parsed, \"persisted session file\");\n\tif (parsed.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session version in ${sourcePath}`);\n\t}\n\tassertPersistedSessionState(parsed.session);\n\treturn {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: parsed.session,\n\t};\n}\n\nfunction parseWalLine(raw: string, sourcePath: string, lineNumber: number): PersistedSessionWalRecord {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session WAL contains invalid JSON: ${sourcePath}:${lineNumber}`, { cause: error });\n\t}\n\tassertPersistedWalRecord(parsed, sourcePath, lineNumber);\n\treturn parsed;\n}\n\nfunction applyWalRecord(session: PersistedSessionState, record: PersistedSessionWalRecord): void {\n\tif (record.sessionId !== session.sessionId) {\n\t\tthrow new Error(`Persisted session WAL sessionId does not match snapshot: ${record.sessionId}`);\n\t}\n\tif (record.baseEntryCount < session.entries.length) {\n\t\tif (record.baseEntryCount + record.entries.length <= session.entries.length) return;\n\t\tthrow new Error(`Persisted session WAL overlaps snapshot for ${record.sessionId}`);\n\t}\n\tif (record.baseEntryCount !== session.entries.length) {\n\t\tthrow new Error(`Persisted session WAL has a gap for ${record.sessionId}`);\n\t}\n\tsession.entries.push(...record.entries.map((entry) => ({ ...entry })));\n\tsession.leafId = record.leafId;\n\tsession.revision = record.revision;\n\tsession.updatedAt = record.updatedAt;\n\tsession.staticContext = record.staticContext;\n}\n\nfunction applyPersistedWal(sessionStoreDir: string, session: PersistedSessionState): number {\n\tconst filePath = walPath(sessionStoreDir, session.sessionId);\n\tif (!existsSync(filePath)) return 0;\n\tconst lines = readFileSync(filePath, \"utf-8\").split(\"\\n\");\n\tlet applied = 0;\n\tfor (const [index, line] of lines.entries()) {\n\t\tif (!line) continue;\n\t\tapplyWalRecord(session, parseWalLine(line, filePath, index + 1));\n\t\tapplied++;\n\t}\n\treturn applied;\n}\n\nexport function loadPersistedSessions(sessionStoreDir: string): void {\n\tif (!existsSync(sessionStoreDir)) return;\n\tconst entries = readdirSync(sessionStoreDir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".json\")) continue;\n\t\tconst filePath = join(sessionStoreDir, entry.name);\n\t\tconst persisted = parsePersistedSessionFile(readFileSync(filePath, \"utf-8\"), filePath);\n\t\tconst expectedFileName = sessionFileName(persisted.session.sessionId);\n\t\tif (entry.name !== expectedFileName) {\n\t\t\tthrow new Error(`Persisted session file name does not match sessionId: ${filePath}`);\n\t\t}\n\t\tconst walRecords = applyPersistedWal(sessionStoreDir, persisted.session);\n\t\trestoreSessionState(persisted.session);\n\t\tpersistedSessions.set(persistedSessionKey(sessionStoreDir, persisted.session.sessionId), {\n\t\t\tentryCount: persisted.session.entries.length,\n\t\t\twalRecords,\n\t\t});\n\t}\n}\n\nfunction writeSnapshot(sessionStoreDir: string, session: SessionState): void {\n\tmkdirSync(sessionStoreDir, { recursive: true });\n\tconst filePath = sessionPath(sessionStoreDir, session.sessionId);\n\tconst tempPath = `${filePath}.${randomUUID()}.tmp`;\n\tconst body: PersistedSessionFile = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: exportSessionState(session),\n\t};\n\ttry {\n\t\twriteFileSync(tempPath, JSON.stringify(body), \"utf-8\");\n\t\treplaceFileSync(tempPath, filePath);\n\t\trmSync(walPath(sessionStoreDir, session.sessionId), { force: true });\n\t} catch (error) {\n\t\trmSync(tempPath, { force: true });\n\t\tthrow error;\n\t}\n}\n\nfunction appendWalRecord(sessionStoreDir: string, session: SessionState, baseEntryCount: number): void {\n\tconst record: PersistedSessionWalRecord = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsessionId: session.sessionId,\n\t\tbaseEntryCount,\n\t\tentries: session.persistenceChange?.kind === \"wal\" ? session.persistenceChange.entries : [],\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t\tupdatedAt: session.updatedAt,\n\t\tstaticContext: session.staticContext,\n\t};\n\tappendFileSync(walPath(sessionStoreDir, session.sessionId), `${JSON.stringify(record)}\\n`, \"utf-8\");\n}\n\nexport function savePersistedSession(sessionStoreDir: string, session: SessionState): void {\n\tconst key = persistedSessionKey(sessionStoreDir, session.sessionId);\n\tconst meta = persistedSessions.get(key);\n\tif (meta && !session.persistenceChange) return;\n\tif (!meta || session.persistenceChange?.kind === \"snapshot\" || meta.walRecords >= WAL_SNAPSHOT_INTERVAL) {\n\t\twriteSnapshot(sessionStoreDir, session);\n\t\tpersistedSessions.set(key, { entryCount: session.entries.length, walRecords: 0 });\n\t\tmarkSessionPersisted(session);\n\t\treturn;\n\t}\n\tappendWalRecord(sessionStoreDir, session, meta.entryCount);\n\tpersistedSessions.set(key, { entryCount: session.entries.length, walRecords: meta.walRecords + 1 });\n\tmarkSessionPersisted(session);\n}\n\nexport function deletePersistedSession(sessionStoreDir: string, sessionId: string): void {\n\trmSync(sessionPath(sessionStoreDir, sessionId), { force: true });\n\trmSync(walPath(sessionStoreDir, sessionId), { force: true });\n\tpersistedSessions.delete(persistedSessionKey(sessionStoreDir, sessionId));\n}\n"]}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { exportSessionState, restoreSessionState, } from "./session-store.js";
|
|
4
|
+
import { exportSessionState, markSessionPersisted, restoreSessionState, } from "./session-store.js";
|
|
5
5
|
const PERSISTED_SESSION_VERSION = 1;
|
|
6
|
+
const WAL_SNAPSHOT_INTERVAL = 32;
|
|
6
7
|
const REPLACE_RETRY_DELAYS_MS = [25, 50, 100, 200, 400];
|
|
8
|
+
const persistedSessions = new Map();
|
|
7
9
|
function sessionFileName(sessionId) {
|
|
8
10
|
return `${createHash("sha256").update(sessionId).digest("hex")}.json`;
|
|
9
11
|
}
|
|
10
12
|
function sessionPath(sessionStoreDir, sessionId) {
|
|
11
13
|
return join(sessionStoreDir, sessionFileName(sessionId));
|
|
12
14
|
}
|
|
15
|
+
function walPath(sessionStoreDir, sessionId) {
|
|
16
|
+
return `${sessionPath(sessionStoreDir, sessionId)}.wal`;
|
|
17
|
+
}
|
|
18
|
+
function persistedSessionKey(sessionStoreDir, sessionId) {
|
|
19
|
+
return `${sessionStoreDir}\0${sessionId}`;
|
|
20
|
+
}
|
|
13
21
|
function isRetryableRenameError(error) {
|
|
14
22
|
if (!(error instanceof Error))
|
|
15
23
|
return false;
|
|
@@ -101,6 +109,20 @@ function assertPersistedSessionState(value) {
|
|
|
101
109
|
assertNumber(value.createdAt, "session.createdAt");
|
|
102
110
|
assertNumber(value.updatedAt, "session.updatedAt");
|
|
103
111
|
}
|
|
112
|
+
function assertPersistedWalRecord(value, sourcePath, lineNumber) {
|
|
113
|
+
const path = `${sourcePath}:${lineNumber}`;
|
|
114
|
+
assertRecord(value, path);
|
|
115
|
+
if (value.version !== PERSISTED_SESSION_VERSION) {
|
|
116
|
+
throw new Error(`Unsupported persisted session WAL version in ${path}`);
|
|
117
|
+
}
|
|
118
|
+
assertString(value.sessionId, `${path}.sessionId`);
|
|
119
|
+
assertNumber(value.baseEntryCount, `${path}.baseEntryCount`);
|
|
120
|
+
assertSessionTreeEntries(value.entries);
|
|
121
|
+
assertNullableString(value.leafId, `${path}.leafId`);
|
|
122
|
+
assertNumber(value.revision, `${path}.revision`);
|
|
123
|
+
assertNumber(value.updatedAt, `${path}.updatedAt`);
|
|
124
|
+
assertStaticContext(value.staticContext);
|
|
125
|
+
}
|
|
104
126
|
function parsePersistedSessionFile(raw, sourcePath) {
|
|
105
127
|
let parsed;
|
|
106
128
|
try {
|
|
@@ -119,6 +141,49 @@ function parsePersistedSessionFile(raw, sourcePath) {
|
|
|
119
141
|
session: parsed.session,
|
|
120
142
|
};
|
|
121
143
|
}
|
|
144
|
+
function parseWalLine(raw, sourcePath, lineNumber) {
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = JSON.parse(raw);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw new Error(`Persisted session WAL contains invalid JSON: ${sourcePath}:${lineNumber}`, { cause: error });
|
|
151
|
+
}
|
|
152
|
+
assertPersistedWalRecord(parsed, sourcePath, lineNumber);
|
|
153
|
+
return parsed;
|
|
154
|
+
}
|
|
155
|
+
function applyWalRecord(session, record) {
|
|
156
|
+
if (record.sessionId !== session.sessionId) {
|
|
157
|
+
throw new Error(`Persisted session WAL sessionId does not match snapshot: ${record.sessionId}`);
|
|
158
|
+
}
|
|
159
|
+
if (record.baseEntryCount < session.entries.length) {
|
|
160
|
+
if (record.baseEntryCount + record.entries.length <= session.entries.length)
|
|
161
|
+
return;
|
|
162
|
+
throw new Error(`Persisted session WAL overlaps snapshot for ${record.sessionId}`);
|
|
163
|
+
}
|
|
164
|
+
if (record.baseEntryCount !== session.entries.length) {
|
|
165
|
+
throw new Error(`Persisted session WAL has a gap for ${record.sessionId}`);
|
|
166
|
+
}
|
|
167
|
+
session.entries.push(...record.entries.map((entry) => ({ ...entry })));
|
|
168
|
+
session.leafId = record.leafId;
|
|
169
|
+
session.revision = record.revision;
|
|
170
|
+
session.updatedAt = record.updatedAt;
|
|
171
|
+
session.staticContext = record.staticContext;
|
|
172
|
+
}
|
|
173
|
+
function applyPersistedWal(sessionStoreDir, session) {
|
|
174
|
+
const filePath = walPath(sessionStoreDir, session.sessionId);
|
|
175
|
+
if (!existsSync(filePath))
|
|
176
|
+
return 0;
|
|
177
|
+
const lines = readFileSync(filePath, "utf-8").split("\n");
|
|
178
|
+
let applied = 0;
|
|
179
|
+
for (const [index, line] of lines.entries()) {
|
|
180
|
+
if (!line)
|
|
181
|
+
continue;
|
|
182
|
+
applyWalRecord(session, parseWalLine(line, filePath, index + 1));
|
|
183
|
+
applied++;
|
|
184
|
+
}
|
|
185
|
+
return applied;
|
|
186
|
+
}
|
|
122
187
|
export function loadPersistedSessions(sessionStoreDir) {
|
|
123
188
|
if (!existsSync(sessionStoreDir))
|
|
124
189
|
return;
|
|
@@ -132,10 +197,15 @@ export function loadPersistedSessions(sessionStoreDir) {
|
|
|
132
197
|
if (entry.name !== expectedFileName) {
|
|
133
198
|
throw new Error(`Persisted session file name does not match sessionId: ${filePath}`);
|
|
134
199
|
}
|
|
200
|
+
const walRecords = applyPersistedWal(sessionStoreDir, persisted.session);
|
|
135
201
|
restoreSessionState(persisted.session);
|
|
202
|
+
persistedSessions.set(persistedSessionKey(sessionStoreDir, persisted.session.sessionId), {
|
|
203
|
+
entryCount: persisted.session.entries.length,
|
|
204
|
+
walRecords,
|
|
205
|
+
});
|
|
136
206
|
}
|
|
137
207
|
}
|
|
138
|
-
|
|
208
|
+
function writeSnapshot(sessionStoreDir, session) {
|
|
139
209
|
mkdirSync(sessionStoreDir, { recursive: true });
|
|
140
210
|
const filePath = sessionPath(sessionStoreDir, session.sessionId);
|
|
141
211
|
const tempPath = `${filePath}.${randomUUID()}.tmp`;
|
|
@@ -146,13 +216,44 @@ export function savePersistedSession(sessionStoreDir, session) {
|
|
|
146
216
|
try {
|
|
147
217
|
writeFileSync(tempPath, JSON.stringify(body), "utf-8");
|
|
148
218
|
replaceFileSync(tempPath, filePath);
|
|
219
|
+
rmSync(walPath(sessionStoreDir, session.sessionId), { force: true });
|
|
149
220
|
}
|
|
150
221
|
catch (error) {
|
|
151
222
|
rmSync(tempPath, { force: true });
|
|
152
223
|
throw error;
|
|
153
224
|
}
|
|
154
225
|
}
|
|
226
|
+
function appendWalRecord(sessionStoreDir, session, baseEntryCount) {
|
|
227
|
+
const record = {
|
|
228
|
+
version: PERSISTED_SESSION_VERSION,
|
|
229
|
+
sessionId: session.sessionId,
|
|
230
|
+
baseEntryCount,
|
|
231
|
+
entries: session.persistenceChange?.kind === "wal" ? session.persistenceChange.entries : [],
|
|
232
|
+
leafId: session.leafId,
|
|
233
|
+
revision: session.revision,
|
|
234
|
+
updatedAt: session.updatedAt,
|
|
235
|
+
staticContext: session.staticContext,
|
|
236
|
+
};
|
|
237
|
+
appendFileSync(walPath(sessionStoreDir, session.sessionId), `${JSON.stringify(record)}\n`, "utf-8");
|
|
238
|
+
}
|
|
239
|
+
export function savePersistedSession(sessionStoreDir, session) {
|
|
240
|
+
const key = persistedSessionKey(sessionStoreDir, session.sessionId);
|
|
241
|
+
const meta = persistedSessions.get(key);
|
|
242
|
+
if (meta && !session.persistenceChange)
|
|
243
|
+
return;
|
|
244
|
+
if (!meta || session.persistenceChange?.kind === "snapshot" || meta.walRecords >= WAL_SNAPSHOT_INTERVAL) {
|
|
245
|
+
writeSnapshot(sessionStoreDir, session);
|
|
246
|
+
persistedSessions.set(key, { entryCount: session.entries.length, walRecords: 0 });
|
|
247
|
+
markSessionPersisted(session);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
appendWalRecord(sessionStoreDir, session, meta.entryCount);
|
|
251
|
+
persistedSessions.set(key, { entryCount: session.entries.length, walRecords: meta.walRecords + 1 });
|
|
252
|
+
markSessionPersisted(session);
|
|
253
|
+
}
|
|
155
254
|
export function deletePersistedSession(sessionStoreDir, sessionId) {
|
|
156
255
|
rmSync(sessionPath(sessionStoreDir, sessionId), { force: true });
|
|
256
|
+
rmSync(walPath(sessionStoreDir, sessionId), { force: true });
|
|
257
|
+
persistedSessions.delete(persistedSessionKey(sessionStoreDir, sessionId));
|
|
157
258
|
}
|
|
158
259
|
//# sourceMappingURL=session-persistence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-persistence.js","sourceRoot":"","sources":["../src/session-persistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SessionTreeEntry } from \"@earendil-works/pi-agent-core\";\nimport {\n\texportSessionState,\n\ttype PersistedSessionState,\n\trestoreSessionState,\n\ttype SessionState,\n\ttype SessionStaticContext,\n} from \"./session-store.ts\";\n\nconst PERSISTED_SESSION_VERSION = 1;\nconst REPLACE_RETRY_DELAYS_MS = [25, 50, 100, 200, 400];\n\ninterface PersistedSessionFile {\n\tversion: 1;\n\tsession: PersistedSessionState;\n}\n\nfunction sessionFileName(sessionId: string): string {\n\treturn `${createHash(\"sha256\").update(sessionId).digest(\"hex\")}.json`;\n}\n\nfunction sessionPath(sessionStoreDir: string, sessionId: string): string {\n\treturn join(sessionStoreDir, sessionFileName(sessionId));\n}\n\nfunction isRetryableRenameError(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn process.platform === \"win32\" && code === \"EPERM\";\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction replaceFileSync(sourcePath: string, targetPath: string): void {\n\tfor (let attempt = 0; attempt <= REPLACE_RETRY_DELAYS_MS.length; attempt++) {\n\t\ttry {\n\t\t\trenameSync(sourcePath, targetPath);\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tif (!isRetryableRenameError(error) || attempt === REPLACE_RETRY_DELAYS_MS.length) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tsleepSync(REPLACE_RETRY_DELAYS_MS[attempt]);\n\t\t}\n\t}\n}\n\nfunction assertRecord(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertString(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string`);\n\t}\n}\n\nfunction assertNumber(value: unknown, path: string): asserts value is number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new Error(`${path} must be a finite number`);\n\t}\n}\n\nfunction assertNullableString(value: unknown, path: string): asserts value is string | null {\n\tif (value !== null && typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string or null`);\n\t}\n}\n\nfunction assertStaticContext(value: unknown): asserts value is SessionStaticContext | undefined {\n\tif (value === undefined) return;\n\tassertRecord(value, \"session.staticContext\");\n\tconst systemPrompt = value.systemPrompt;\n\tif (systemPrompt !== undefined && typeof systemPrompt !== \"string\") {\n\t\tthrow new Error(\"session.staticContext.systemPrompt must be a string\");\n\t}\n\tconst tools = value.tools;\n\tif (tools !== undefined) {\n\t\tif (!Array.isArray(tools)) {\n\t\t\tthrow new Error(\"session.staticContext.tools must be an array\");\n\t\t}\n\t\tfor (const [index, tool] of tools.entries()) {\n\t\t\tassertRecord(tool, `session.staticContext.tools[${index}]`);\n\t\t\tassertString(tool.name, `session.staticContext.tools[${index}].name`);\n\t\t\tassertString(tool.description, `session.staticContext.tools[${index}].description`);\n\t\t\tif (tool.parameters === undefined) {\n\t\t\t\tthrow new Error(`session.staticContext.tools[${index}].parameters is required`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction assertSessionTreeEntries(value: unknown): asserts value is SessionTreeEntry[] {\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(\"session.entries must be an array\");\n\t}\n\tfor (const [index, entry] of value.entries()) {\n\t\tassertRecord(entry, `session.entries[${index}]`);\n\t\tassertString(entry.type, `session.entries[${index}].type`);\n\t\tassertString(entry.id, `session.entries[${index}].id`);\n\t\tassertNullableString(entry.parentId, `session.entries[${index}].parentId`);\n\t\tassertString(entry.timestamp, `session.entries[${index}].timestamp`);\n\t\tif (entry.type === \"message\") {\n\t\t\tassertRecord(entry.message, `session.entries[${index}].message`);\n\t\t}\n\t}\n}\n\nfunction assertPersistedSessionState(value: unknown): asserts value is PersistedSessionState {\n\tassertRecord(value, \"session\");\n\tassertString(value.sessionId, \"session.sessionId\");\n\tassertStaticContext(value.staticContext);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, \"session.leafId\");\n\tassertNumber(value.revision, \"session.revision\");\n\tassertNumber(value.createdAt, \"session.createdAt\");\n\tassertNumber(value.updatedAt, \"session.updatedAt\");\n}\n\nfunction parsePersistedSessionFile(raw: string, sourcePath: string): PersistedSessionFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session file contains invalid JSON: ${sourcePath}`, { cause: error });\n\t}\n\tassertRecord(parsed, \"persisted session file\");\n\tif (parsed.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session version in ${sourcePath}`);\n\t}\n\tassertPersistedSessionState(parsed.session);\n\treturn {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: parsed.session,\n\t};\n}\n\nexport function loadPersistedSessions(sessionStoreDir: string): void {\n\tif (!existsSync(sessionStoreDir)) return;\n\tconst entries = readdirSync(sessionStoreDir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".json\")) continue;\n\t\tconst filePath = join(sessionStoreDir, entry.name);\n\t\tconst persisted = parsePersistedSessionFile(readFileSync(filePath, \"utf-8\"), filePath);\n\t\tconst expectedFileName = sessionFileName(persisted.session.sessionId);\n\t\tif (entry.name !== expectedFileName) {\n\t\t\tthrow new Error(`Persisted session file name does not match sessionId: ${filePath}`);\n\t\t}\n\t\trestoreSessionState(persisted.session);\n\t}\n}\n\nexport function savePersistedSession(sessionStoreDir: string, session: SessionState): void {\n\tmkdirSync(sessionStoreDir, { recursive: true });\n\tconst filePath = sessionPath(sessionStoreDir, session.sessionId);\n\tconst tempPath = `${filePath}.${randomUUID()}.tmp`;\n\tconst body: PersistedSessionFile = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: exportSessionState(session),\n\t};\n\ttry {\n\t\twriteFileSync(tempPath, JSON.stringify(body), \"utf-8\");\n\t\treplaceFileSync(tempPath, filePath);\n\t} catch (error) {\n\t\trmSync(tempPath, { force: true });\n\t\tthrow error;\n\t}\n}\n\nexport function deletePersistedSession(sessionStoreDir: string, sessionId: string): void {\n\trmSync(sessionPath(sessionStoreDir, sessionId), { force: true });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-persistence.js","sourceRoot":"","sources":["../src/session-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACN,cAAc,EACd,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,aAAa,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACN,kBAAkB,EAClB,oBAAoB,EAEpB,mBAAmB,GAGnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,yBAAyB,GAAG,CAAC,CAAC;AACpC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,uBAAuB,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAuBxD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAgC,CAAC;AAElE,SAAS,eAAe,CAAC,SAAiB,EAAU;IACnD,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;AAAA,CACtE;AAED,SAAS,WAAW,CAAC,eAAuB,EAAE,SAAiB,EAAU;IACxE,OAAO,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;AAAA,CACzD;AAED,SAAS,OAAO,CAAC,eAAuB,EAAE,SAAiB,EAAU;IACpE,OAAO,GAAG,WAAW,CAAC,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC;AAAA,CACxD;AAED,SAAS,mBAAmB,CAAC,eAAuB,EAAE,SAAiB,EAAU;IAChF,OAAO,GAAG,eAAe,KAAK,SAAS,EAAE,CAAC;AAAA,CAC1C;AAED,SAAS,sBAAsB,CAAC,KAAc,EAAW;IACxD,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;IACnD,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,CAAC;AAAA,CACxD;AAED,SAAS,SAAS,CAAC,EAAU,EAAQ;IACpC,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAAA,CACjE;AAED,SAAS,eAAe,CAAC,UAAkB,EAAE,UAAkB,EAAQ;IACtE,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5E,IAAI,CAAC;YACJ,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YACnC,OAAO;QACR,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,uBAAuB,CAAC,MAAM,EAAE,CAAC;gBAClF,MAAM,KAAK,CAAC;YACb,CAAC;YACD,SAAS,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7C,CAAC;IACF,CAAC;AAAA,CACD;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAY,EAA4C;IAC7F,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;IAC9C,CAAC;AAAA,CACD;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAY,EAA2B;IAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;IAC7C,CAAC;AAAA,CACD;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAY,EAA2B;IAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,0BAA0B,CAAC,CAAC;IACpD,CAAC;AAAA,CACD;AAED,SAAS,oBAAoB,CAAC,KAAc,EAAE,IAAY,EAAkC;IAC3F,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAC;IACrD,CAAC;AAAA,CACD;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAqD;IAC/F,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,YAAY,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;IACxC,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACxE,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACjE,CAAC;QACD,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,YAAY,CAAC,IAAI,EAAE,+BAA+B,KAAK,GAAG,CAAC,CAAC;YAC5D,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,+BAA+B,KAAK,QAAQ,CAAC,CAAC;YACtE,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,+BAA+B,KAAK,eAAe,CAAC,CAAC;YACpF,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,0BAA0B,CAAC,CAAC;YACjF,CAAC;QACF,CAAC;IACF,CAAC;AAAA,CACD;AAED,SAAS,wBAAwB,CAAC,KAAc,EAAuC;IACtF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACrD,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,YAAY,CAAC,KAAK,EAAE,mBAAmB,KAAK,GAAG,CAAC,CAAC;QACjD,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,KAAK,QAAQ,CAAC,CAAC;QAC3D,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,mBAAmB,KAAK,MAAM,CAAC,CAAC;QACvD,oBAAoB,CAAC,KAAK,CAAC,QAAQ,EAAE,mBAAmB,KAAK,YAAY,CAAC,CAAC;QAC3E,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,KAAK,aAAa,CAAC,CAAC;QACrE,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,mBAAmB,KAAK,WAAW,CAAC,CAAC;QAClE,CAAC;IACF,CAAC;AAAA,CACD;AAED,SAAS,2BAA2B,CAAC,KAAc,EAA0C;IAC5F,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC/B,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACnD,mBAAmB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACzC,wBAAwB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxC,oBAAoB,CAAC,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACrD,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACjD,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACnD,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;AAAA,CACnD;AAED,SAAS,wBAAwB,CAChC,KAAc,EACd,UAAkB,EAClB,UAAkB,EAC2B;IAC7C,MAAM,IAAI,GAAG,GAAG,UAAU,IAAI,UAAU,EAAE,CAAC;IAC3C,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1B,IAAI,KAAK,CAAC,OAAO,KAAK,yBAAyB,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,IAAI,YAAY,CAAC,CAAC;IACnD,YAAY,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,IAAI,iBAAiB,CAAC,CAAC;IAC7D,wBAAwB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxC,oBAAoB,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC;IACrD,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC;IACjD,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,IAAI,YAAY,CAAC,CAAC;IACnD,mBAAmB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;AAAA,CACzC;AAED,SAAS,yBAAyB,CAAC,GAAW,EAAE,UAAkB,EAAwB;IACzF,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,iDAAiD,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,YAAY,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,OAAO,KAAK,yBAAyB,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,4CAA4C,UAAU,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,2BAA2B,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO;QACN,OAAO,EAAE,yBAAyB;QAClC,OAAO,EAAE,MAAM,CAAC,OAAO;KACvB,CAAC;AAAA,CACF;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,UAAkB,EAAE,UAAkB,EAA6B;IACrG,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,gDAAgD,UAAU,IAAI,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACzD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,cAAc,CAAC,OAA8B,EAAE,MAAiC,EAAQ;IAChG,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,4DAA4D,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpD,IAAI,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO;QACpF,MAAM,IAAI,KAAK,CAAC,+CAA+C,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACnC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACrC,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;AAAA,CAC7C;AAED,SAAS,iBAAiB,CAAC,eAAuB,EAAE,OAA8B,EAAU;IAC3F,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,OAAO,CAAC;AAAA,CACf;AAED,MAAM,UAAU,qBAAqB,CAAC,eAAuB,EAAQ;IACpE,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;QAAE,OAAO;IACzC,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,yBAAyB,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvF,MAAM,gBAAgB,GAAG,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACtE,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,yDAAyD,QAAQ,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,UAAU,GAAG,iBAAiB,CAAC,eAAe,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACzE,mBAAmB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvC,iBAAiB,CAAC,GAAG,CAAC,mBAAmB,CAAC,eAAe,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;YACxF,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM;YAC5C,UAAU;SACV,CAAC,CAAC;IACJ,CAAC;AAAA,CACD;AAED,SAAS,aAAa,CAAC,eAAuB,EAAE,OAAqB,EAAQ;IAC5E,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,UAAU,EAAE,MAAM,CAAC;IACnD,MAAM,IAAI,GAAyB;QAClC,OAAO,EAAE,yBAAyB;QAClC,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC;KACpC,CAAC;IACF,IAAI,CAAC;QACJ,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACvD,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,MAAM,KAAK,CAAC;IACb,CAAC;AAAA,CACD;AAED,SAAS,eAAe,CAAC,eAAuB,EAAE,OAAqB,EAAE,cAAsB,EAAQ;IACtG,MAAM,MAAM,GAA8B;QACzC,OAAO,EAAE,yBAAyB;QAClC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,cAAc;QACd,OAAO,EAAE,OAAO,CAAC,iBAAiB,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAC3F,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,aAAa,EAAE,OAAO,CAAC,aAAa;KACpC,CAAC;IACF,cAAc,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAAA,CACpG;AAED,MAAM,UAAU,oBAAoB,CAAC,eAAuB,EAAE,OAAqB,EAAQ;IAC1F,MAAM,GAAG,GAAG,mBAAmB,CAAC,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,iBAAiB;QAAE,OAAO;IAC/C,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,IAAI,qBAAqB,EAAE,CAAC;QACzG,aAAa,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACxC,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAClF,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO;IACR,CAAC;IACD,eAAe,CAAC,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3D,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC,CAAC;IACpG,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAA,CAC9B;AAED,MAAM,UAAU,sBAAsB,CAAC,eAAuB,EAAE,SAAiB,EAAQ;IACxF,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,iBAAiB,CAAC,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC;AAAA,CAC1E","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport {\n\tappendFileSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { SessionTreeEntry } from \"@earendil-works/pi-agent-core\";\nimport {\n\texportSessionState,\n\tmarkSessionPersisted,\n\ttype PersistedSessionState,\n\trestoreSessionState,\n\ttype SessionState,\n\ttype SessionStaticContext,\n} from \"./session-store.ts\";\n\nconst PERSISTED_SESSION_VERSION = 1;\nconst WAL_SNAPSHOT_INTERVAL = 32;\nconst REPLACE_RETRY_DELAYS_MS = [25, 50, 100, 200, 400];\n\ninterface PersistedSessionFile {\n\tversion: 1;\n\tsession: PersistedSessionState;\n}\n\ninterface PersistedSessionWalRecord {\n\tversion: 1;\n\tsessionId: string;\n\tbaseEntryCount: number;\n\tentries: SessionTreeEntry[];\n\tleafId: string | null;\n\trevision: number;\n\tupdatedAt: number;\n\tstaticContext: SessionStaticContext | undefined;\n}\n\ninterface PersistedSessionMeta {\n\tentryCount: number;\n\twalRecords: number;\n}\n\nconst persistedSessions = new Map<string, PersistedSessionMeta>();\n\nfunction sessionFileName(sessionId: string): string {\n\treturn `${createHash(\"sha256\").update(sessionId).digest(\"hex\")}.json`;\n}\n\nfunction sessionPath(sessionStoreDir: string, sessionId: string): string {\n\treturn join(sessionStoreDir, sessionFileName(sessionId));\n}\n\nfunction walPath(sessionStoreDir: string, sessionId: string): string {\n\treturn `${sessionPath(sessionStoreDir, sessionId)}.wal`;\n}\n\nfunction persistedSessionKey(sessionStoreDir: string, sessionId: string): string {\n\treturn `${sessionStoreDir}\\0${sessionId}`;\n}\n\nfunction isRetryableRenameError(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn process.platform === \"win32\" && code === \"EPERM\";\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction replaceFileSync(sourcePath: string, targetPath: string): void {\n\tfor (let attempt = 0; attempt <= REPLACE_RETRY_DELAYS_MS.length; attempt++) {\n\t\ttry {\n\t\t\trenameSync(sourcePath, targetPath);\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tif (!isRetryableRenameError(error) || attempt === REPLACE_RETRY_DELAYS_MS.length) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tsleepSync(REPLACE_RETRY_DELAYS_MS[attempt]);\n\t\t}\n\t}\n}\n\nfunction assertRecord(value: unknown, path: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${path} must be an object`);\n\t}\n}\n\nfunction assertString(value: unknown, path: string): asserts value is string {\n\tif (typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string`);\n\t}\n}\n\nfunction assertNumber(value: unknown, path: string): asserts value is number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new Error(`${path} must be a finite number`);\n\t}\n}\n\nfunction assertNullableString(value: unknown, path: string): asserts value is string | null {\n\tif (value !== null && typeof value !== \"string\") {\n\t\tthrow new Error(`${path} must be a string or null`);\n\t}\n}\n\nfunction assertStaticContext(value: unknown): asserts value is SessionStaticContext | undefined {\n\tif (value === undefined) return;\n\tassertRecord(value, \"session.staticContext\");\n\tconst systemPrompt = value.systemPrompt;\n\tif (systemPrompt !== undefined && typeof systemPrompt !== \"string\") {\n\t\tthrow new Error(\"session.staticContext.systemPrompt must be a string\");\n\t}\n\tconst tools = value.tools;\n\tif (tools !== undefined) {\n\t\tif (!Array.isArray(tools)) {\n\t\t\tthrow new Error(\"session.staticContext.tools must be an array\");\n\t\t}\n\t\tfor (const [index, tool] of tools.entries()) {\n\t\t\tassertRecord(tool, `session.staticContext.tools[${index}]`);\n\t\t\tassertString(tool.name, `session.staticContext.tools[${index}].name`);\n\t\t\tassertString(tool.description, `session.staticContext.tools[${index}].description`);\n\t\t\tif (tool.parameters === undefined) {\n\t\t\t\tthrow new Error(`session.staticContext.tools[${index}].parameters is required`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction assertSessionTreeEntries(value: unknown): asserts value is SessionTreeEntry[] {\n\tif (!Array.isArray(value)) {\n\t\tthrow new Error(\"session.entries must be an array\");\n\t}\n\tfor (const [index, entry] of value.entries()) {\n\t\tassertRecord(entry, `session.entries[${index}]`);\n\t\tassertString(entry.type, `session.entries[${index}].type`);\n\t\tassertString(entry.id, `session.entries[${index}].id`);\n\t\tassertNullableString(entry.parentId, `session.entries[${index}].parentId`);\n\t\tassertString(entry.timestamp, `session.entries[${index}].timestamp`);\n\t\tif (entry.type === \"message\") {\n\t\t\tassertRecord(entry.message, `session.entries[${index}].message`);\n\t\t}\n\t}\n}\n\nfunction assertPersistedSessionState(value: unknown): asserts value is PersistedSessionState {\n\tassertRecord(value, \"session\");\n\tassertString(value.sessionId, \"session.sessionId\");\n\tassertStaticContext(value.staticContext);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, \"session.leafId\");\n\tassertNumber(value.revision, \"session.revision\");\n\tassertNumber(value.createdAt, \"session.createdAt\");\n\tassertNumber(value.updatedAt, \"session.updatedAt\");\n}\n\nfunction assertPersistedWalRecord(\n\tvalue: unknown,\n\tsourcePath: string,\n\tlineNumber: number,\n): asserts value is PersistedSessionWalRecord {\n\tconst path = `${sourcePath}:${lineNumber}`;\n\tassertRecord(value, path);\n\tif (value.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session WAL version in ${path}`);\n\t}\n\tassertString(value.sessionId, `${path}.sessionId`);\n\tassertNumber(value.baseEntryCount, `${path}.baseEntryCount`);\n\tassertSessionTreeEntries(value.entries);\n\tassertNullableString(value.leafId, `${path}.leafId`);\n\tassertNumber(value.revision, `${path}.revision`);\n\tassertNumber(value.updatedAt, `${path}.updatedAt`);\n\tassertStaticContext(value.staticContext);\n}\n\nfunction parsePersistedSessionFile(raw: string, sourcePath: string): PersistedSessionFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session file contains invalid JSON: ${sourcePath}`, { cause: error });\n\t}\n\tassertRecord(parsed, \"persisted session file\");\n\tif (parsed.version !== PERSISTED_SESSION_VERSION) {\n\t\tthrow new Error(`Unsupported persisted session version in ${sourcePath}`);\n\t}\n\tassertPersistedSessionState(parsed.session);\n\treturn {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: parsed.session,\n\t};\n}\n\nfunction parseWalLine(raw: string, sourcePath: string, lineNumber: number): PersistedSessionWalRecord {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch (error) {\n\t\tthrow new Error(`Persisted session WAL contains invalid JSON: ${sourcePath}:${lineNumber}`, { cause: error });\n\t}\n\tassertPersistedWalRecord(parsed, sourcePath, lineNumber);\n\treturn parsed;\n}\n\nfunction applyWalRecord(session: PersistedSessionState, record: PersistedSessionWalRecord): void {\n\tif (record.sessionId !== session.sessionId) {\n\t\tthrow new Error(`Persisted session WAL sessionId does not match snapshot: ${record.sessionId}`);\n\t}\n\tif (record.baseEntryCount < session.entries.length) {\n\t\tif (record.baseEntryCount + record.entries.length <= session.entries.length) return;\n\t\tthrow new Error(`Persisted session WAL overlaps snapshot for ${record.sessionId}`);\n\t}\n\tif (record.baseEntryCount !== session.entries.length) {\n\t\tthrow new Error(`Persisted session WAL has a gap for ${record.sessionId}`);\n\t}\n\tsession.entries.push(...record.entries.map((entry) => ({ ...entry })));\n\tsession.leafId = record.leafId;\n\tsession.revision = record.revision;\n\tsession.updatedAt = record.updatedAt;\n\tsession.staticContext = record.staticContext;\n}\n\nfunction applyPersistedWal(sessionStoreDir: string, session: PersistedSessionState): number {\n\tconst filePath = walPath(sessionStoreDir, session.sessionId);\n\tif (!existsSync(filePath)) return 0;\n\tconst lines = readFileSync(filePath, \"utf-8\").split(\"\\n\");\n\tlet applied = 0;\n\tfor (const [index, line] of lines.entries()) {\n\t\tif (!line) continue;\n\t\tapplyWalRecord(session, parseWalLine(line, filePath, index + 1));\n\t\tapplied++;\n\t}\n\treturn applied;\n}\n\nexport function loadPersistedSessions(sessionStoreDir: string): void {\n\tif (!existsSync(sessionStoreDir)) return;\n\tconst entries = readdirSync(sessionStoreDir, { withFileTypes: true });\n\tfor (const entry of entries) {\n\t\tif (!entry.isFile() || !entry.name.endsWith(\".json\")) continue;\n\t\tconst filePath = join(sessionStoreDir, entry.name);\n\t\tconst persisted = parsePersistedSessionFile(readFileSync(filePath, \"utf-8\"), filePath);\n\t\tconst expectedFileName = sessionFileName(persisted.session.sessionId);\n\t\tif (entry.name !== expectedFileName) {\n\t\t\tthrow new Error(`Persisted session file name does not match sessionId: ${filePath}`);\n\t\t}\n\t\tconst walRecords = applyPersistedWal(sessionStoreDir, persisted.session);\n\t\trestoreSessionState(persisted.session);\n\t\tpersistedSessions.set(persistedSessionKey(sessionStoreDir, persisted.session.sessionId), {\n\t\t\tentryCount: persisted.session.entries.length,\n\t\t\twalRecords,\n\t\t});\n\t}\n}\n\nfunction writeSnapshot(sessionStoreDir: string, session: SessionState): void {\n\tmkdirSync(sessionStoreDir, { recursive: true });\n\tconst filePath = sessionPath(sessionStoreDir, session.sessionId);\n\tconst tempPath = `${filePath}.${randomUUID()}.tmp`;\n\tconst body: PersistedSessionFile = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsession: exportSessionState(session),\n\t};\n\ttry {\n\t\twriteFileSync(tempPath, JSON.stringify(body), \"utf-8\");\n\t\treplaceFileSync(tempPath, filePath);\n\t\trmSync(walPath(sessionStoreDir, session.sessionId), { force: true });\n\t} catch (error) {\n\t\trmSync(tempPath, { force: true });\n\t\tthrow error;\n\t}\n}\n\nfunction appendWalRecord(sessionStoreDir: string, session: SessionState, baseEntryCount: number): void {\n\tconst record: PersistedSessionWalRecord = {\n\t\tversion: PERSISTED_SESSION_VERSION,\n\t\tsessionId: session.sessionId,\n\t\tbaseEntryCount,\n\t\tentries: session.persistenceChange?.kind === \"wal\" ? session.persistenceChange.entries : [],\n\t\tleafId: session.leafId,\n\t\trevision: session.revision,\n\t\tupdatedAt: session.updatedAt,\n\t\tstaticContext: session.staticContext,\n\t};\n\tappendFileSync(walPath(sessionStoreDir, session.sessionId), `${JSON.stringify(record)}\\n`, \"utf-8\");\n}\n\nexport function savePersistedSession(sessionStoreDir: string, session: SessionState): void {\n\tconst key = persistedSessionKey(sessionStoreDir, session.sessionId);\n\tconst meta = persistedSessions.get(key);\n\tif (meta && !session.persistenceChange) return;\n\tif (!meta || session.persistenceChange?.kind === \"snapshot\" || meta.walRecords >= WAL_SNAPSHOT_INTERVAL) {\n\t\twriteSnapshot(sessionStoreDir, session);\n\t\tpersistedSessions.set(key, { entryCount: session.entries.length, walRecords: 0 });\n\t\tmarkSessionPersisted(session);\n\t\treturn;\n\t}\n\tappendWalRecord(sessionStoreDir, session, meta.entryCount);\n\tpersistedSessions.set(key, { entryCount: session.entries.length, walRecords: meta.walRecords + 1 });\n\tmarkSessionPersisted(session);\n}\n\nexport function deletePersistedSession(sessionStoreDir: string, sessionId: string): void {\n\trmSync(sessionPath(sessionStoreDir, sessionId), { force: true });\n\trmSync(walPath(sessionStoreDir, sessionId), { force: true });\n\tpersistedSessions.delete(persistedSessionKey(sessionStoreDir, sessionId));\n}\n"]}
|
package/dist/session-store.d.ts
CHANGED
|
@@ -10,10 +10,13 @@ export interface SessionState {
|
|
|
10
10
|
staticContextHash: string;
|
|
11
11
|
entries: SessionTreeEntry[];
|
|
12
12
|
leafId: string | null;
|
|
13
|
+
treeHash: string;
|
|
14
|
+
prefixHashes: string[];
|
|
13
15
|
messages: Message[];
|
|
14
16
|
revision: number;
|
|
15
17
|
createdAt: number;
|
|
16
18
|
updatedAt: number;
|
|
19
|
+
persistenceChange: SessionPersistenceChange | undefined;
|
|
17
20
|
}
|
|
18
21
|
export interface SessionSummary {
|
|
19
22
|
sessionId: string;
|
|
@@ -35,6 +38,12 @@ export interface PersistedSessionState {
|
|
|
35
38
|
createdAt: number;
|
|
36
39
|
updatedAt: number;
|
|
37
40
|
}
|
|
41
|
+
export type SessionPersistenceChange = {
|
|
42
|
+
kind: "snapshot";
|
|
43
|
+
} | {
|
|
44
|
+
kind: "wal";
|
|
45
|
+
entries: SessionTreeEntry[];
|
|
46
|
+
};
|
|
38
47
|
export declare function getOrCreateSession(sessionId: string): SessionState;
|
|
39
48
|
export declare function getSession(sessionId: string): SessionState | undefined;
|
|
40
49
|
export declare function hashSessionEntries(entries: SessionTreeEntry[]): string;
|
|
@@ -62,4 +71,5 @@ export declare function replaceMessages(sessionId: string, messages: Message[]):
|
|
|
62
71
|
export declare function dropLastAssistantError(sessionId: string): boolean;
|
|
63
72
|
export declare function deleteSession(sessionId: string): boolean;
|
|
64
73
|
export declare function clearAllSessions(): void;
|
|
74
|
+
export declare function markSessionPersisted(session: SessionState): void;
|
|
65
75
|
//# sourceMappingURL=session-store.d.ts.map
|