@agimon-ai/doompi-core 0.0.1-alpha.107 → 0.0.1-alpha.109

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.
Files changed (55) hide show
  1. package/dist/childSession.d.mts +2 -2
  2. package/dist/sqliteSessionStorage.cjs +46 -19
  3. package/dist/sqliteSessionStorage.cjs.map +1 -1
  4. package/dist/sqliteSessionStorage.d.mts.map +1 -1
  5. package/dist/sqliteSessionStorage.mjs +47 -20
  6. package/dist/sqliteSessionStorage.mjs.map +1 -1
  7. package/dist/src/pi/piSessionRuntime.cjs +1 -4
  8. package/dist/src/pi/piSessionRuntime.cjs.map +1 -1
  9. package/dist/src/pi/piSessionRuntime.d.mts.map +1 -1
  10. package/dist/src/pi/piSessionRuntime.mjs +1 -4
  11. package/dist/src/pi/piSessionRuntime.mjs.map +1 -1
  12. package/dist/src/schemas/headless.cjs.map +1 -1
  13. package/dist/src/schemas/headless.d.mts +6 -7
  14. package/dist/src/schemas/headless.d.mts.map +1 -1
  15. package/dist/src/schemas/headless.mjs.map +1 -1
  16. package/dist/src/server/directHarnessRuntime.cjs +243 -81
  17. package/dist/src/server/directHarnessRuntime.cjs.map +1 -1
  18. package/dist/src/server/directHarnessRuntime.mjs +243 -81
  19. package/dist/src/server/directHarnessRuntime.mjs.map +1 -1
  20. package/dist/src/services/piExtensionHost/index.cjs +33 -21
  21. package/dist/src/services/piExtensionHost/index.cjs.map +1 -1
  22. package/dist/src/services/piExtensionHost/index.mjs +33 -21
  23. package/dist/src/services/piExtensionHost/index.mjs.map +1 -1
  24. package/dist/src/services/piSessionEntries/index.cjs +14 -5
  25. package/dist/src/services/piSessionEntries/index.cjs.map +1 -1
  26. package/dist/src/services/piSessionEntries/index.mjs +14 -5
  27. package/dist/src/services/piSessionEntries/index.mjs.map +1 -1
  28. package/dist/src/systems/child/adapters/headlessChildSessionService.cjs +133 -43
  29. package/dist/src/systems/child/adapters/headlessChildSessionService.cjs.map +1 -1
  30. package/dist/src/systems/child/adapters/headlessChildSessionService.d.mts +3 -2
  31. package/dist/src/systems/child/adapters/headlessChildSessionService.d.mts.map +1 -1
  32. package/dist/src/systems/child/adapters/headlessChildSessionService.mjs +133 -44
  33. package/dist/src/systems/child/adapters/headlessChildSessionService.mjs.map +1 -1
  34. package/dist/src/systems/child/types/childSession.cjs.map +1 -1
  35. package/dist/src/systems/child/types/childSession.d.mts +11 -1
  36. package/dist/src/systems/child/types/childSession.d.mts.map +1 -1
  37. package/dist/src/systems/child/types/childSession.mjs.map +1 -1
  38. package/dist/src/systems/main/adapters/headlessHost.cjs +14 -5
  39. package/dist/src/systems/main/adapters/headlessHost.cjs.map +1 -1
  40. package/dist/src/systems/main/adapters/headlessHost.d.mts.map +1 -1
  41. package/dist/src/systems/main/adapters/headlessHost.mjs +14 -5
  42. package/dist/src/systems/main/adapters/headlessHost.mjs.map +1 -1
  43. package/dist/src/systems/main/adapters/headlessSessionHost.cjs +12 -5
  44. package/dist/src/systems/main/adapters/headlessSessionHost.cjs.map +1 -1
  45. package/dist/src/systems/main/adapters/headlessSessionHost.mjs +12 -5
  46. package/dist/src/systems/main/adapters/headlessSessionHost.mjs.map +1 -1
  47. package/dist/src/types/server/directHarnessRuntime.d.mts +9 -1
  48. package/dist/src/types/server/directHarnessRuntime.d.mts.map +1 -1
  49. package/dist/terminalPiChildSessionService.cjs +24 -7
  50. package/dist/terminalPiChildSessionService.cjs.map +1 -1
  51. package/dist/terminalPiChildSessionService.d.mts +3 -2
  52. package/dist/terminalPiChildSessionService.d.mts.map +1 -1
  53. package/dist/terminalPiChildSessionService.mjs +25 -8
  54. package/dist/terminalPiChildSessionService.mjs.map +1 -1
  55. package/package.json +4 -4
@@ -1,3 +1,3 @@
1
- import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, DOOM_CHILD_SESSION_SERVICE, DoomChildSessionCapabilityCeiling, DoomChildSessionEvent, DoomChildSessionFreshSource, DoomChildSessionHandle, DoomChildSessionIntercom, DoomChildSessionRequest, DoomChildSessionRuntime, DoomChildSessionRuntimeFactory, DoomChildSessionScope, DoomChildSessionService, DoomChildSessionServiceProvider, DoomChildSessionSource, DoomChildSessionState, DoomChildSessionTerminalPiForkSource, DoomChildSessionTool, DoomChildSessionToolResult, DoomChildSessionUsage, DoomChildSessionV4ForkSource, DoomChildSessionV4RestoreSource, readDoomChildSessionService, requireDoomChildSessionService } from "./src/systems/child/types/childSession.mjs";
1
+ import { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, DOOM_CHILD_SESSION_SERVICE, DoomChildSessionCapabilityCeiling, DoomChildSessionEvent, DoomChildSessionFreshSource, DoomChildSessionHandle, DoomChildSessionIntercom, DoomChildSessionMcpCatalog, DoomChildSessionMcpTool, DoomChildSessionRequest, DoomChildSessionRuntime, DoomChildSessionRuntimeFactory, DoomChildSessionScope, DoomChildSessionService, DoomChildSessionServiceProvider, DoomChildSessionSource, DoomChildSessionState, DoomChildSessionTerminalPiForkSource, DoomChildSessionTool, DoomChildSessionToolResult, DoomChildSessionUsage, DoomChildSessionV4ForkSource, DoomChildSessionV4RestoreSource, readDoomChildSessionService, requireDoomChildSessionService } from "./src/systems/child/types/childSession.mjs";
2
2
  import { DoomChildSessionServiceDependencies, createDoomChildSessionService } from "./src/systems/child/services/childSession/index.mjs";
3
- export { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, DOOM_CHILD_SESSION_SERVICE, DoomChildSessionCapabilityCeiling, DoomChildSessionEvent, DoomChildSessionFreshSource, DoomChildSessionHandle, DoomChildSessionIntercom, DoomChildSessionRequest, DoomChildSessionRuntime, DoomChildSessionRuntimeFactory, DoomChildSessionScope, DoomChildSessionService, DoomChildSessionServiceDependencies, DoomChildSessionServiceProvider, DoomChildSessionSource, DoomChildSessionState, DoomChildSessionTerminalPiForkSource, DoomChildSessionTool, DoomChildSessionToolResult, DoomChildSessionUsage, DoomChildSessionV4ForkSource, DoomChildSessionV4RestoreSource, createDoomChildSessionService, readDoomChildSessionService, requireDoomChildSessionService };
3
+ export { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, DOOM_CHILD_SESSION_SERVICE, DoomChildSessionCapabilityCeiling, DoomChildSessionEvent, DoomChildSessionFreshSource, DoomChildSessionHandle, DoomChildSessionIntercom, DoomChildSessionMcpCatalog, DoomChildSessionMcpTool, DoomChildSessionRequest, DoomChildSessionRuntime, DoomChildSessionRuntimeFactory, DoomChildSessionScope, DoomChildSessionService, DoomChildSessionServiceDependencies, DoomChildSessionServiceProvider, DoomChildSessionSource, DoomChildSessionState, DoomChildSessionTerminalPiForkSource, DoomChildSessionTool, DoomChildSessionToolResult, DoomChildSessionUsage, DoomChildSessionV4ForkSource, DoomChildSessionV4RestoreSource, createDoomChildSessionService, readDoomChildSessionService, requireDoomChildSessionService };
@@ -60,24 +60,40 @@ function validateDurableSessionFile(file) {
60
60
  /** Completed histories use a read-only connection. Initialization cannot write or migrate. */
61
61
  async function openReadOnlyDurableStorage(file) {
62
62
  validateDurableSessionFile(file);
63
- const database = new _earendil_works_pi_durable_storage_sqlite_node.NodeSqliteDatabase(new node_sqlite.DatabaseSync(file, { readOnly: true }));
64
- return await _earendil_works_pi_durable_storage_sqlite.SqliteStorage.open({
65
- exec: (sql) => database.exec(sql),
66
- run: (sql, ...params) => database.run(sql, ...params),
67
- get: (sql, ...params) => database.get(sql, ...params),
68
- all: (sql, ...params) => database.all(sql, ...params),
69
- close: () => database.close(),
70
- transaction: (callback) => callback({
71
- exec: async (sql) => {
72
- if (!/^CREATE TABLE IF NOT EXISTS durable_schema\s/u.test(sql)) throw new Error("Read-only durable storage");
73
- },
74
- run: async (sql) => {
75
- if (sql !== "INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)") throw new Error("Read-only durable storage");
76
- },
63
+ const native = new node_sqlite.DatabaseSync(file, { readOnly: true });
64
+ const database = new _earendil_works_pi_durable_storage_sqlite_node.NodeSqliteDatabase(native);
65
+ let closed = false;
66
+ const close = async () => {
67
+ if (closed) return;
68
+ native.close();
69
+ closed = true;
70
+ };
71
+ try {
72
+ return await _earendil_works_pi_durable_storage_sqlite.SqliteStorage.open({
73
+ exec: (sql) => database.exec(sql),
74
+ run: (sql, ...params) => database.run(sql, ...params),
77
75
  get: (sql, ...params) => database.get(sql, ...params),
78
- all: (sql, ...params) => database.all(sql, ...params)
79
- })
80
- });
76
+ all: (sql, ...params) => database.all(sql, ...params),
77
+ close,
78
+ transaction: (callback) => callback({
79
+ exec: async (sql) => {
80
+ if (!/^CREATE TABLE IF NOT EXISTS durable_schema\s/u.test(sql)) throw new Error("Read-only durable storage");
81
+ },
82
+ run: async (sql) => {
83
+ if (sql !== "INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)") throw new Error("Read-only durable storage");
84
+ },
85
+ get: (sql, ...params) => database.get(sql, ...params),
86
+ all: (sql, ...params) => database.all(sql, ...params)
87
+ })
88
+ });
89
+ } catch (error) {
90
+ try {
91
+ await close();
92
+ } catch (cleanupError) {
93
+ throw new AggregateError([error, cleanupError], "Read-only storage initialization cleanup failed");
94
+ }
95
+ throw error;
96
+ }
81
97
  }
82
98
  /** Opens the one fresh-format SQLite container owned by a server session. */
83
99
  async function openSqliteSessionStorage(options, context) {
@@ -97,10 +113,14 @@ async function openSqliteSessionStorage(options, context) {
97
113
  });
98
114
  const historyLease = await options.historyOwnership.acquire(sessionFile);
99
115
  let storage;
116
+ let database;
117
+ let writerOpenAttempted = false;
100
118
  try {
101
119
  await historyLease.assertQuiescent();
102
120
  if (node_fs.default.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);
103
- storage = await (0, _earendil_works_pi_durable_storage_sqlite_node.openNodeSqliteStorage)(sessionFile);
121
+ writerOpenAttempted = true;
122
+ database = await (0, _earendil_works_pi_durable_storage_sqlite_node.openNodeSqliteDatabase)(sessionFile);
123
+ storage = await _earendil_works_pi_durable_storage_sqlite.SqliteStorage.open(database);
104
124
  const session = (0, _earendil_works_pi_durable.createSession)(storage);
105
125
  const identity = await session.snapshot(SessionIdentityDoc, context);
106
126
  if (existing && (!identity || identity.id !== id)) throw new Error("SQLite session id does not match the requested session");
@@ -121,10 +141,17 @@ async function openSqliteSessionStorage(options, context) {
121
141
  historyLease
122
142
  };
123
143
  } catch (error) {
144
+ if (writerOpenAttempted && !database) throw error;
124
145
  try {
125
146
  if (storage) await storage.close(context);
126
- } finally {
147
+ else if (database) await database.close();
148
+ } catch (cleanupError) {
149
+ throw new AggregateError([error, cleanupError], "SQLite storage initialization cleanup failed");
150
+ }
151
+ try {
127
152
  await historyLease.release();
153
+ } catch (cleanupError) {
154
+ throw new AggregateError([error, cleanupError], "SQLite storage ownership cleanup failed");
128
155
  }
129
156
  throw error;
130
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sqliteSessionStorage.cjs","names":["BACKGROUND_CONTEXT","defineDoc","DatabaseSync","NodeSqliteDatabase","SqliteStorage","path","randomUUID","fs","openNodeSqliteStorage","createSession"],"sources":["../src/services/sqliteSessionStorage/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport { createSession, defineDoc, type Storage } from '@earendil-works/pi-durable';\nimport { SqliteStorage } from '@earendil-works/pi-durable/storage/sqlite';\nimport { NodeSqliteDatabase, openNodeSqliteStorage } from '@earendil-works/pi-durable/storage/sqlite/node';\n\nimport type { DirectHarnessRuntimeOptions } from '../../types/server/directHarnessRuntime';\n\nexport const DURABLE_BACKGROUND_CONTEXT = BACKGROUND_CONTEXT;\n\nexport const DURABLE_DIRECTORY = 'durable-v1';\n/** Public string identity belongs to Doom, not the durable numeric ID namespace. */\nexport const SessionIdentityDoc = defineDoc({\n kind: 'doompi.session.identity',\n version: 1,\n scope: 'session',\n initial: () => ({ id: '', createdAt: 0, parentSessionId: '' }),\n});\nexport const SessionMetadataDoc = defineDoc({\n kind: 'doompi.session.metadata',\n version: 1,\n scope: 'session',\n initial: () => ({ name: '', workspaceRoot: '', execution: '', laneName: 'main' }),\n});\n\n/** Validate existing files without admitting a writer or applying schema upgrades. */\nexport function validateDurableSessionFile(file: string): void {\n const database = new DatabaseSync(file, { readOnly: true });\n try {\n const schema = database.prepare('SELECT version FROM durable_schema WHERE singleton = 1').get();\n if (schema?.version !== 1) throw new Error('Unsupported durable SQLite schema');\n const tables = database.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all();\n for (const name of [\n 'durable_metadata',\n 'record_ids',\n 'conversations',\n 'entries',\n 'tasks',\n 'submissions',\n 'documents',\n 'document_revisions',\n ]) {\n if (!tables.some((table) => table.name === name)) throw new Error('Invalid durable SQLite schema');\n }\n } catch (cause) {\n throw new Error('Unsupported or legacy SQLite session format', { cause });\n } finally {\n database.close();\n }\n}\n\n/** Completed histories use a read-only connection. Initialization cannot write or migrate. */\nexport async function openReadOnlyDurableStorage(file: string): Promise<Storage> {\n validateDurableSessionFile(file);\n const database = new NodeSqliteDatabase(new DatabaseSync(file, { readOnly: true }));\n const storage = await SqliteStorage.open({\n exec: (sql) => database.exec(sql),\n run: (sql, ...params) => database.run(sql, ...params),\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n close: () => database.close(),\n transaction: (callback) =>\n callback({\n exec: async (sql) => {\n if (!/^CREATE TABLE IF NOT EXISTS durable_schema\\s/u.test(sql)) throw new Error('Read-only durable storage');\n },\n run: async (sql) => {\n if (sql !== 'INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)')\n throw new Error('Read-only durable storage');\n },\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n }),\n });\n return storage;\n}\n\n/** Opens the one fresh-format SQLite container owned by a server session. */\nexport async function openSqliteSessionStorage(\n options: Pick<\n DirectHarnessRuntimeOptions,\n 'historyOwnership' | 'sessionsRoot' | 'sessionPath' | 'sessionId' | 'parentSessionId'\n >,\n context: Context,\n) {\n if (!options.historyOwnership) throw new Error('SQLite sessions require explicit HistoryOwnership');\n if (!options.sessionsRoot && !options.sessionPath) throw new Error('SQLite sessions require a server data directory');\n const id = options.sessionId ?? (options.sessionPath ? path.basename(options.sessionPath, '.sqlite') : randomUUID());\n if (!/^[a-zA-Z0-9_-]+$/u.test(id)) throw new Error('Invalid SQLite session id');\n const sessionFile = path.resolve(\n options.sessionPath ?? path.join(options.sessionsRoot!, DURABLE_DIRECTORY, `${id}.sqlite`),\n );\n if (path.basename(path.dirname(sessionFile)) !== DURABLE_DIRECTORY || path.extname(sessionFile) !== '.sqlite')\n throw new Error('Unsupported or legacy SQLite session path');\n const existing = fs.existsSync(sessionFile);\n if (!existing && options.sessionsRoot && fs.existsSync(path.join(options.sessionsRoot, `${id}.sqlite`)))\n throw new Error('Legacy SQLite sessions are unsupported by fresh durable storage');\n if (options.sessionPath && !existing) throw new Error(`SQLite session not found: ${sessionFile}`);\n if (existing) validateDurableSessionFile(sessionFile);\n fs.mkdirSync(path.dirname(sessionFile), { recursive: true, mode: 0o700 });\n const historyLease = await options.historyOwnership.acquire(sessionFile);\n let storage: Storage | undefined;\n try {\n await historyLease.assertQuiescent();\n if (fs.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);\n storage = await openNodeSqliteStorage(sessionFile);\n const session = createSession(storage);\n const identity = await session.snapshot(SessionIdentityDoc, context);\n if (existing && (!identity || identity.id !== id))\n throw new Error('SQLite session id does not match the requested session');\n if (!existing) {\n await session.commit(async (tx) => {\n const doc = await tx.doc(SessionIdentityDoc);\n doc.id = id;\n doc.createdAt = Date.now();\n doc.parentSessionId = options.parentSessionId ?? '';\n }, context);\n fs.chmodSync(sessionFile, 0o600);\n }\n const repository = { close: (closeContext: Context = context) => session.close(closeContext) };\n return { storage, session, sessionFile, repository, historyLease };\n } catch (error) {\n try {\n if (storage) await storage.close(context);\n } finally {\n await historyLease.release();\n }\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sqliteSessionStorage.cjs","names":["BACKGROUND_CONTEXT","defineDoc","DatabaseSync","NodeSqliteDatabase","SqliteStorage","path","randomUUID","fs","openNodeSqliteDatabase","createSession"],"sources":["../src/services/sqliteSessionStorage/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport { createSession, defineDoc, type Storage } from '@earendil-works/pi-durable';\nimport { SqliteStorage } from '@earendil-works/pi-durable/storage/sqlite';\nimport { NodeSqliteDatabase, openNodeSqliteDatabase } from '@earendil-works/pi-durable/storage/sqlite/node';\n\nimport type { DirectHarnessRuntimeOptions } from '../../types/server/directHarnessRuntime';\n\nexport const DURABLE_BACKGROUND_CONTEXT = BACKGROUND_CONTEXT;\n\nexport const DURABLE_DIRECTORY = 'durable-v1';\n/** Public string identity belongs to Doom, not the durable numeric ID namespace. */\nexport const SessionIdentityDoc = defineDoc({\n kind: 'doompi.session.identity',\n version: 1,\n scope: 'session',\n initial: () => ({ id: '', createdAt: 0, parentSessionId: '' }),\n});\nexport const SessionMetadataDoc = defineDoc({\n kind: 'doompi.session.metadata',\n version: 1,\n scope: 'session',\n initial: () => ({ name: '', workspaceRoot: '', execution: '', laneName: 'main' }),\n});\n\n/** Validate existing files without admitting a writer or applying schema upgrades. */\nexport function validateDurableSessionFile(file: string): void {\n const database = new DatabaseSync(file, { readOnly: true });\n try {\n const schema = database.prepare('SELECT version FROM durable_schema WHERE singleton = 1').get();\n if (schema?.version !== 1) throw new Error('Unsupported durable SQLite schema');\n const tables = database.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all();\n for (const name of [\n 'durable_metadata',\n 'record_ids',\n 'conversations',\n 'entries',\n 'tasks',\n 'submissions',\n 'documents',\n 'document_revisions',\n ]) {\n if (!tables.some((table) => table.name === name)) throw new Error('Invalid durable SQLite schema');\n }\n } catch (cause) {\n throw new Error('Unsupported or legacy SQLite session format', { cause });\n } finally {\n database.close();\n }\n}\n\n/** Completed histories use a read-only connection. Initialization cannot write or migrate. */\nexport async function openReadOnlyDurableStorage(file: string): Promise<Storage> {\n validateDurableSessionFile(file);\n const native = new DatabaseSync(file, { readOnly: true });\n const database = new NodeSqliteDatabase(native);\n let closed = false;\n const close = async () => {\n if (closed) return;\n // The writer adapter checkpoints WAL on close, which read-only connections cannot do.\n native.close();\n closed = true;\n };\n try {\n const storage = await SqliteStorage.open({\n exec: (sql) => database.exec(sql),\n run: (sql, ...params) => database.run(sql, ...params),\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n close,\n transaction: (callback) =>\n callback({\n exec: async (sql) => {\n if (!/^CREATE TABLE IF NOT EXISTS durable_schema\\s/u.test(sql))\n throw new Error('Read-only durable storage');\n },\n run: async (sql) => {\n if (sql !== 'INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)')\n throw new Error('Read-only durable storage');\n },\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n }),\n });\n return storage;\n } catch (error) {\n try {\n await close();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'Read-only storage initialization cleanup failed');\n }\n throw error;\n }\n}\n\n/** Opens the one fresh-format SQLite container owned by a server session. */\nexport async function openSqliteSessionStorage(\n options: Pick<\n DirectHarnessRuntimeOptions,\n 'historyOwnership' | 'sessionsRoot' | 'sessionPath' | 'sessionId' | 'parentSessionId'\n >,\n context: Context,\n) {\n if (!options.historyOwnership) throw new Error('SQLite sessions require explicit HistoryOwnership');\n if (!options.sessionsRoot && !options.sessionPath) throw new Error('SQLite sessions require a server data directory');\n const id = options.sessionId ?? (options.sessionPath ? path.basename(options.sessionPath, '.sqlite') : randomUUID());\n if (!/^[a-zA-Z0-9_-]+$/u.test(id)) throw new Error('Invalid SQLite session id');\n const sessionFile = path.resolve(\n options.sessionPath ?? path.join(options.sessionsRoot!, DURABLE_DIRECTORY, `${id}.sqlite`),\n );\n if (path.basename(path.dirname(sessionFile)) !== DURABLE_DIRECTORY || path.extname(sessionFile) !== '.sqlite')\n throw new Error('Unsupported or legacy SQLite session path');\n const existing = fs.existsSync(sessionFile);\n if (!existing && options.sessionsRoot && fs.existsSync(path.join(options.sessionsRoot, `${id}.sqlite`)))\n throw new Error('Legacy SQLite sessions are unsupported by fresh durable storage');\n if (options.sessionPath && !existing) throw new Error(`SQLite session not found: ${sessionFile}`);\n if (existing) validateDurableSessionFile(sessionFile);\n fs.mkdirSync(path.dirname(sessionFile), { recursive: true, mode: 0o700 });\n const historyLease = await options.historyOwnership.acquire(sessionFile);\n let storage: Storage | undefined;\n let database: NodeSqliteDatabase | undefined;\n let writerOpenAttempted = false;\n try {\n await historyLease.assertQuiescent();\n if (fs.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);\n writerOpenAttempted = true;\n database = await openNodeSqliteDatabase(sessionFile);\n storage = await SqliteStorage.open(database);\n const session = createSession(storage);\n const identity = await session.snapshot(SessionIdentityDoc, context);\n if (existing && (!identity || identity.id !== id))\n throw new Error('SQLite session id does not match the requested session');\n if (!existing) {\n await session.commit(async (tx) => {\n const doc = await tx.doc(SessionIdentityDoc);\n doc.id = id;\n doc.createdAt = Date.now();\n doc.parentSessionId = options.parentSessionId ?? '';\n }, context);\n fs.chmodSync(sessionFile, 0o600);\n }\n const repository = { close: (closeContext: Context = context) => session.close(closeContext) };\n return { storage, session, sessionFile, repository, historyLease };\n } catch (error) {\n // ponytail: An upstream open rejection has no closure receipt, so retain ownership until shutdown is confirmed.\n if (writerOpenAttempted && !database) throw error;\n try {\n if (storage) await storage.close(context);\n else if (database) await database.close();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'SQLite storage initialization cleanup failed');\n }\n try {\n await historyLease.release();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'SQLite storage ownership cleanup failed');\n }\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sqliteSessionStorage.d.mts","names":[],"sources":["../src/services/sqliteSessionStorage/index.ts"],"mappings":";;;;;qBAaa,4BAA0B;qBAE1B;;qBAEA,yDAAkB;;;;;qBAMlB,yDAAkB;;;;;;;wBAQf,2BAA2B;;wBA0BrB,2BAA2B,eAAe,QAAQ;;wBA0BlD,yBACpB,SAAS,KACP,qHAGF,SAAS,UAAO;;;;;IAoC6B,QAAA,eAAA,YAAO;;gBAAA"}
1
+ {"version":3,"file":"sqliteSessionStorage.d.mts","names":[],"sources":["../src/services/sqliteSessionStorage/index.ts"],"mappings":";;;;;qBAaa,4BAA0B;qBAE1B;;qBAEA,yDAAkB;;;;;qBAMlB,yDAAkB;;;;;;;wBAQf,2BAA2B;;wBA0BrB,2BAA2B,eAAe,QAAQ;;wBA4ClD,yBACpB,SAAS,KACP,qHAGF,SAAS,UAAO;;;;;IAwC6B,QAAA,eAAA,YAAO;;gBAAA"}
@@ -5,7 +5,7 @@ import { DatabaseSync } from "node:sqlite";
5
5
  import { createSession, defineDoc } from "@earendil-works/pi-durable";
6
6
  import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
7
7
  import { SqliteStorage } from "@earendil-works/pi-durable/storage/sqlite";
8
- import { NodeSqliteDatabase, openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
8
+ import { NodeSqliteDatabase, openNodeSqliteDatabase } from "@earendil-works/pi-durable/storage/sqlite/node";
9
9
  //#region src/services/sqliteSessionStorage/index.ts
10
10
  const DURABLE_BACKGROUND_CONTEXT = BACKGROUND_CONTEXT;
11
11
  const DURABLE_DIRECTORY = "durable-v1";
@@ -56,24 +56,40 @@ function validateDurableSessionFile(file) {
56
56
  /** Completed histories use a read-only connection. Initialization cannot write or migrate. */
57
57
  async function openReadOnlyDurableStorage(file) {
58
58
  validateDurableSessionFile(file);
59
- const database = new NodeSqliteDatabase(new DatabaseSync(file, { readOnly: true }));
60
- return await SqliteStorage.open({
61
- exec: (sql) => database.exec(sql),
62
- run: (sql, ...params) => database.run(sql, ...params),
63
- get: (sql, ...params) => database.get(sql, ...params),
64
- all: (sql, ...params) => database.all(sql, ...params),
65
- close: () => database.close(),
66
- transaction: (callback) => callback({
67
- exec: async (sql) => {
68
- if (!/^CREATE TABLE IF NOT EXISTS durable_schema\s/u.test(sql)) throw new Error("Read-only durable storage");
69
- },
70
- run: async (sql) => {
71
- if (sql !== "INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)") throw new Error("Read-only durable storage");
72
- },
59
+ const native = new DatabaseSync(file, { readOnly: true });
60
+ const database = new NodeSqliteDatabase(native);
61
+ let closed = false;
62
+ const close = async () => {
63
+ if (closed) return;
64
+ native.close();
65
+ closed = true;
66
+ };
67
+ try {
68
+ return await SqliteStorage.open({
69
+ exec: (sql) => database.exec(sql),
70
+ run: (sql, ...params) => database.run(sql, ...params),
73
71
  get: (sql, ...params) => database.get(sql, ...params),
74
- all: (sql, ...params) => database.all(sql, ...params)
75
- })
76
- });
72
+ all: (sql, ...params) => database.all(sql, ...params),
73
+ close,
74
+ transaction: (callback) => callback({
75
+ exec: async (sql) => {
76
+ if (!/^CREATE TABLE IF NOT EXISTS durable_schema\s/u.test(sql)) throw new Error("Read-only durable storage");
77
+ },
78
+ run: async (sql) => {
79
+ if (sql !== "INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)") throw new Error("Read-only durable storage");
80
+ },
81
+ get: (sql, ...params) => database.get(sql, ...params),
82
+ all: (sql, ...params) => database.all(sql, ...params)
83
+ })
84
+ });
85
+ } catch (error) {
86
+ try {
87
+ await close();
88
+ } catch (cleanupError) {
89
+ throw new AggregateError([error, cleanupError], "Read-only storage initialization cleanup failed");
90
+ }
91
+ throw error;
92
+ }
77
93
  }
78
94
  /** Opens the one fresh-format SQLite container owned by a server session. */
79
95
  async function openSqliteSessionStorage(options, context) {
@@ -93,10 +109,14 @@ async function openSqliteSessionStorage(options, context) {
93
109
  });
94
110
  const historyLease = await options.historyOwnership.acquire(sessionFile);
95
111
  let storage;
112
+ let database;
113
+ let writerOpenAttempted = false;
96
114
  try {
97
115
  await historyLease.assertQuiescent();
98
116
  if (fs.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);
99
- storage = await openNodeSqliteStorage(sessionFile);
117
+ writerOpenAttempted = true;
118
+ database = await openNodeSqliteDatabase(sessionFile);
119
+ storage = await SqliteStorage.open(database);
100
120
  const session = createSession(storage);
101
121
  const identity = await session.snapshot(SessionIdentityDoc, context);
102
122
  if (existing && (!identity || identity.id !== id)) throw new Error("SQLite session id does not match the requested session");
@@ -117,10 +137,17 @@ async function openSqliteSessionStorage(options, context) {
117
137
  historyLease
118
138
  };
119
139
  } catch (error) {
140
+ if (writerOpenAttempted && !database) throw error;
120
141
  try {
121
142
  if (storage) await storage.close(context);
122
- } finally {
143
+ else if (database) await database.close();
144
+ } catch (cleanupError) {
145
+ throw new AggregateError([error, cleanupError], "SQLite storage initialization cleanup failed");
146
+ }
147
+ try {
123
148
  await historyLease.release();
149
+ } catch (cleanupError) {
150
+ throw new AggregateError([error, cleanupError], "SQLite storage ownership cleanup failed");
124
151
  }
125
152
  throw error;
126
153
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sqliteSessionStorage.mjs","names":[],"sources":["../src/services/sqliteSessionStorage/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport { createSession, defineDoc, type Storage } from '@earendil-works/pi-durable';\nimport { SqliteStorage } from '@earendil-works/pi-durable/storage/sqlite';\nimport { NodeSqliteDatabase, openNodeSqliteStorage } from '@earendil-works/pi-durable/storage/sqlite/node';\n\nimport type { DirectHarnessRuntimeOptions } from '../../types/server/directHarnessRuntime';\n\nexport const DURABLE_BACKGROUND_CONTEXT = BACKGROUND_CONTEXT;\n\nexport const DURABLE_DIRECTORY = 'durable-v1';\n/** Public string identity belongs to Doom, not the durable numeric ID namespace. */\nexport const SessionIdentityDoc = defineDoc({\n kind: 'doompi.session.identity',\n version: 1,\n scope: 'session',\n initial: () => ({ id: '', createdAt: 0, parentSessionId: '' }),\n});\nexport const SessionMetadataDoc = defineDoc({\n kind: 'doompi.session.metadata',\n version: 1,\n scope: 'session',\n initial: () => ({ name: '', workspaceRoot: '', execution: '', laneName: 'main' }),\n});\n\n/** Validate existing files without admitting a writer or applying schema upgrades. */\nexport function validateDurableSessionFile(file: string): void {\n const database = new DatabaseSync(file, { readOnly: true });\n try {\n const schema = database.prepare('SELECT version FROM durable_schema WHERE singleton = 1').get();\n if (schema?.version !== 1) throw new Error('Unsupported durable SQLite schema');\n const tables = database.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all();\n for (const name of [\n 'durable_metadata',\n 'record_ids',\n 'conversations',\n 'entries',\n 'tasks',\n 'submissions',\n 'documents',\n 'document_revisions',\n ]) {\n if (!tables.some((table) => table.name === name)) throw new Error('Invalid durable SQLite schema');\n }\n } catch (cause) {\n throw new Error('Unsupported or legacy SQLite session format', { cause });\n } finally {\n database.close();\n }\n}\n\n/** Completed histories use a read-only connection. Initialization cannot write or migrate. */\nexport async function openReadOnlyDurableStorage(file: string): Promise<Storage> {\n validateDurableSessionFile(file);\n const database = new NodeSqliteDatabase(new DatabaseSync(file, { readOnly: true }));\n const storage = await SqliteStorage.open({\n exec: (sql) => database.exec(sql),\n run: (sql, ...params) => database.run(sql, ...params),\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n close: () => database.close(),\n transaction: (callback) =>\n callback({\n exec: async (sql) => {\n if (!/^CREATE TABLE IF NOT EXISTS durable_schema\\s/u.test(sql)) throw new Error('Read-only durable storage');\n },\n run: async (sql) => {\n if (sql !== 'INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)')\n throw new Error('Read-only durable storage');\n },\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n }),\n });\n return storage;\n}\n\n/** Opens the one fresh-format SQLite container owned by a server session. */\nexport async function openSqliteSessionStorage(\n options: Pick<\n DirectHarnessRuntimeOptions,\n 'historyOwnership' | 'sessionsRoot' | 'sessionPath' | 'sessionId' | 'parentSessionId'\n >,\n context: Context,\n) {\n if (!options.historyOwnership) throw new Error('SQLite sessions require explicit HistoryOwnership');\n if (!options.sessionsRoot && !options.sessionPath) throw new Error('SQLite sessions require a server data directory');\n const id = options.sessionId ?? (options.sessionPath ? path.basename(options.sessionPath, '.sqlite') : randomUUID());\n if (!/^[a-zA-Z0-9_-]+$/u.test(id)) throw new Error('Invalid SQLite session id');\n const sessionFile = path.resolve(\n options.sessionPath ?? path.join(options.sessionsRoot!, DURABLE_DIRECTORY, `${id}.sqlite`),\n );\n if (path.basename(path.dirname(sessionFile)) !== DURABLE_DIRECTORY || path.extname(sessionFile) !== '.sqlite')\n throw new Error('Unsupported or legacy SQLite session path');\n const existing = fs.existsSync(sessionFile);\n if (!existing && options.sessionsRoot && fs.existsSync(path.join(options.sessionsRoot, `${id}.sqlite`)))\n throw new Error('Legacy SQLite sessions are unsupported by fresh durable storage');\n if (options.sessionPath && !existing) throw new Error(`SQLite session not found: ${sessionFile}`);\n if (existing) validateDurableSessionFile(sessionFile);\n fs.mkdirSync(path.dirname(sessionFile), { recursive: true, mode: 0o700 });\n const historyLease = await options.historyOwnership.acquire(sessionFile);\n let storage: Storage | undefined;\n try {\n await historyLease.assertQuiescent();\n if (fs.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);\n storage = await openNodeSqliteStorage(sessionFile);\n const session = createSession(storage);\n const identity = await session.snapshot(SessionIdentityDoc, context);\n if (existing && (!identity || identity.id !== id))\n throw new Error('SQLite session id does not match the requested session');\n if (!existing) {\n await session.commit(async (tx) => {\n const doc = await tx.doc(SessionIdentityDoc);\n doc.id = id;\n doc.createdAt = Date.now();\n doc.parentSessionId = options.parentSessionId ?? '';\n }, context);\n fs.chmodSync(sessionFile, 0o600);\n }\n const repository = { close: (closeContext: Context = context) => session.close(closeContext) };\n return { storage, session, sessionFile, repository, historyLease };\n } catch (error) {\n try {\n if (storage) await storage.close(context);\n } finally {\n await historyLease.release();\n }\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sqliteSessionStorage.mjs","names":[],"sources":["../src/services/sqliteSessionStorage/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport { createSession, defineDoc, type Storage } from '@earendil-works/pi-durable';\nimport { SqliteStorage } from '@earendil-works/pi-durable/storage/sqlite';\nimport { NodeSqliteDatabase, openNodeSqliteDatabase } from '@earendil-works/pi-durable/storage/sqlite/node';\n\nimport type { DirectHarnessRuntimeOptions } from '../../types/server/directHarnessRuntime';\n\nexport const DURABLE_BACKGROUND_CONTEXT = BACKGROUND_CONTEXT;\n\nexport const DURABLE_DIRECTORY = 'durable-v1';\n/** Public string identity belongs to Doom, not the durable numeric ID namespace. */\nexport const SessionIdentityDoc = defineDoc({\n kind: 'doompi.session.identity',\n version: 1,\n scope: 'session',\n initial: () => ({ id: '', createdAt: 0, parentSessionId: '' }),\n});\nexport const SessionMetadataDoc = defineDoc({\n kind: 'doompi.session.metadata',\n version: 1,\n scope: 'session',\n initial: () => ({ name: '', workspaceRoot: '', execution: '', laneName: 'main' }),\n});\n\n/** Validate existing files without admitting a writer or applying schema upgrades. */\nexport function validateDurableSessionFile(file: string): void {\n const database = new DatabaseSync(file, { readOnly: true });\n try {\n const schema = database.prepare('SELECT version FROM durable_schema WHERE singleton = 1').get();\n if (schema?.version !== 1) throw new Error('Unsupported durable SQLite schema');\n const tables = database.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all();\n for (const name of [\n 'durable_metadata',\n 'record_ids',\n 'conversations',\n 'entries',\n 'tasks',\n 'submissions',\n 'documents',\n 'document_revisions',\n ]) {\n if (!tables.some((table) => table.name === name)) throw new Error('Invalid durable SQLite schema');\n }\n } catch (cause) {\n throw new Error('Unsupported or legacy SQLite session format', { cause });\n } finally {\n database.close();\n }\n}\n\n/** Completed histories use a read-only connection. Initialization cannot write or migrate. */\nexport async function openReadOnlyDurableStorage(file: string): Promise<Storage> {\n validateDurableSessionFile(file);\n const native = new DatabaseSync(file, { readOnly: true });\n const database = new NodeSqliteDatabase(native);\n let closed = false;\n const close = async () => {\n if (closed) return;\n // The writer adapter checkpoints WAL on close, which read-only connections cannot do.\n native.close();\n closed = true;\n };\n try {\n const storage = await SqliteStorage.open({\n exec: (sql) => database.exec(sql),\n run: (sql, ...params) => database.run(sql, ...params),\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n close,\n transaction: (callback) =>\n callback({\n exec: async (sql) => {\n if (!/^CREATE TABLE IF NOT EXISTS durable_schema\\s/u.test(sql))\n throw new Error('Read-only durable storage');\n },\n run: async (sql) => {\n if (sql !== 'INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)')\n throw new Error('Read-only durable storage');\n },\n get: (sql, ...params) => database.get(sql, ...params),\n all: (sql, ...params) => database.all(sql, ...params),\n }),\n });\n return storage;\n } catch (error) {\n try {\n await close();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'Read-only storage initialization cleanup failed');\n }\n throw error;\n }\n}\n\n/** Opens the one fresh-format SQLite container owned by a server session. */\nexport async function openSqliteSessionStorage(\n options: Pick<\n DirectHarnessRuntimeOptions,\n 'historyOwnership' | 'sessionsRoot' | 'sessionPath' | 'sessionId' | 'parentSessionId'\n >,\n context: Context,\n) {\n if (!options.historyOwnership) throw new Error('SQLite sessions require explicit HistoryOwnership');\n if (!options.sessionsRoot && !options.sessionPath) throw new Error('SQLite sessions require a server data directory');\n const id = options.sessionId ?? (options.sessionPath ? path.basename(options.sessionPath, '.sqlite') : randomUUID());\n if (!/^[a-zA-Z0-9_-]+$/u.test(id)) throw new Error('Invalid SQLite session id');\n const sessionFile = path.resolve(\n options.sessionPath ?? path.join(options.sessionsRoot!, DURABLE_DIRECTORY, `${id}.sqlite`),\n );\n if (path.basename(path.dirname(sessionFile)) !== DURABLE_DIRECTORY || path.extname(sessionFile) !== '.sqlite')\n throw new Error('Unsupported or legacy SQLite session path');\n const existing = fs.existsSync(sessionFile);\n if (!existing && options.sessionsRoot && fs.existsSync(path.join(options.sessionsRoot, `${id}.sqlite`)))\n throw new Error('Legacy SQLite sessions are unsupported by fresh durable storage');\n if (options.sessionPath && !existing) throw new Error(`SQLite session not found: ${sessionFile}`);\n if (existing) validateDurableSessionFile(sessionFile);\n fs.mkdirSync(path.dirname(sessionFile), { recursive: true, mode: 0o700 });\n const historyLease = await options.historyOwnership.acquire(sessionFile);\n let storage: Storage | undefined;\n let database: NodeSqliteDatabase | undefined;\n let writerOpenAttempted = false;\n try {\n await historyLease.assertQuiescent();\n if (fs.existsSync(sessionFile)) validateDurableSessionFile(sessionFile);\n writerOpenAttempted = true;\n database = await openNodeSqliteDatabase(sessionFile);\n storage = await SqliteStorage.open(database);\n const session = createSession(storage);\n const identity = await session.snapshot(SessionIdentityDoc, context);\n if (existing && (!identity || identity.id !== id))\n throw new Error('SQLite session id does not match the requested session');\n if (!existing) {\n await session.commit(async (tx) => {\n const doc = await tx.doc(SessionIdentityDoc);\n doc.id = id;\n doc.createdAt = Date.now();\n doc.parentSessionId = options.parentSessionId ?? '';\n }, context);\n fs.chmodSync(sessionFile, 0o600);\n }\n const repository = { close: (closeContext: Context = context) => session.close(closeContext) };\n return { storage, session, sessionFile, repository, historyLease };\n } catch (error) {\n // ponytail: An upstream open rejection has no closure receipt, so retain ownership until shutdown is confirmed.\n if (writerOpenAttempted && !database) throw error;\n try {\n if (storage) await storage.close(context);\n else if (database) await database.close();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'SQLite storage initialization cleanup failed');\n }\n try {\n await historyLease.release();\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'SQLite storage ownership cleanup failed');\n }\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -409,10 +409,7 @@ function createAgentSessionRuntime(options) {
409
409
  async steer(text) {
410
410
  requireLive();
411
411
  const args = messageArgs(text);
412
- (await options.runtime.submitUserPrompt(args.message, args.images)).settled.catch((error) => present({
413
- type: "error",
414
- error: String(error)
415
- }));
412
+ await options.runtime.steer(args.message, args.images);
416
413
  },
417
414
  async abort() {
418
415
  requireLive();
@@ -1 +1 @@
1
- {"version":3,"file":"piSessionRuntime.cjs","names":["createRpcTranscript","createSessionPresentation","createAcpSessionUpdateProjection","replicatedState","BACKGROUND_CONTEXT","transcriptCursor","readTranscriptPage","RemoteServiceProvider","DoomSessionManagementService","createRemoteServiceEndpoint","SessionNotFoundError","DoomSessionService"],"sources":["../../../src/pi/piSessionRuntime.ts"],"sourcesContent":["import {\n createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n type Context,\n type MutableReplicatedState,\n type RemoteServiceEndpoint,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { RoutedServerServiceHost, RoutedSessionHandle, ServerHost } from '@earendil-works/pi-server';\nimport { SessionNotFoundError } from '@earendil-works/pi-server';\n\nimport {\n DoomSessionManagementService,\n DoomSessionService,\n type SessionService,\n type SessionMessageArgs,\n type PromptArgs,\n type SessionServiceState,\n type SessionSnapshot,\n type SessionLifecycle,\n type TranscriptItem,\n type TranscriptPage,\n type TranscriptPageRequest,\n type RewindResult,\n type SessionStateInfo,\n type SessionStats,\n type SessionCommand,\n type ModelRef,\n type ThinkingLevel,\n} from '../exports/sessionProtocol';\nimport { createAcpSessionUpdateProjection } from '../services/acpSessionUpdates';\nimport { createRpcTranscript, type RpcTranscript } from '../services/rpcTranscript';\nimport { observe, type ServerTelemetry } from '../services/serverTelemetry';\nimport { createSessionPresentation } from '../services/sessionPresentation';\nimport { readTranscriptPage, transcriptCursor } from '../services/transcriptPages';\nimport type { DirectHarnessRuntime, DirectHarnessFrame } from '../types/server/directHarnessRuntime';\n\nconst SETTLED = 'agent_settled';\nconst PROMPT_LATENCY_EVENT = 'doompi_server.prompt_latency';\nconst SELECTION_COMMANDS = new Set(['mode', 'domains', 'profile', 'minor']);\n\nfunction isSelectionCommand(text: string): boolean {\n const match = /^\\/(\\S+)/.exec(text);\n return match !== null && SELECTION_COMMANDS.has(match[1]!);\n}\n\ntype PromptLatency = {\n readonly startedAt: number;\n lastStageAt: number;\n readonly reported: Set<string>;\n};\n\nasync function sessionStats(runtime: DirectHarnessRuntime, sessionId: string): Promise<SessionStats> {\n const stored = await runtime.getSessionStats();\n const { contextUsage, sessionFile } = stored;\n return {\n sessionId,\n ...(sessionFile === undefined ? {} : { sessionFile }),\n totalMessages: stored.messageCount,\n tokens: {\n input: stored.usage.input,\n output: stored.usage.output,\n cacheRead: stored.usage.cacheRead,\n cacheWrite: stored.usage.cacheWrite,\n total: stored.usage.totalTokens,\n },\n cost: stored.usage.cost.total,\n ...(contextUsage === undefined ? {} : { contextUsage }),\n };\n}\n\nexport interface AgentSessionRuntimeOptions {\n runtime: DirectHarnessRuntime;\n sessionId: string;\n sessionName: string;\n cwd: string;\n telemetry?: ServerTelemetry;\n /** Subscribes to the combined harness and headless presentation projection. */\n onPresentationFrame?: (listener: (frame: DirectHarnessFrame) => void) => () => void;\n /** Delivers one answered extension UI request to the session-scoped headless host. */\n respondToExtensionUi?: (frame: DirectHarnessFrame) => boolean;\n /** Test seam for the projection. */\n transcript?: RpcTranscript;\n readThreadTranscript?: (\n threadId: string,\n request: TranscriptPageRequest,\n context: Context,\n ) => Promise<TranscriptPage>;\n}\n\nexport interface AgentSessionRuntime extends SessionService {\n readonly state: MutableReplicatedState<SessionServiceState>;\n initialize(): Promise<void>;\n dispose(): Promise<void>;\n}\n\n/** Projects one in-process harness runtime as a Chord session service. */\nexport function createAgentSessionRuntime(options: AgentSessionRuntimeOptions): AgentSessionRuntime {\n const transcript =\n options.transcript ??\n createRpcTranscript({\n id: options.sessionId,\n cwd: options.cwd,\n name: options.sessionName,\n now: Date.now,\n retainEntries: 0,\n });\n const presentation = createSessionPresentation();\n const acpUpdates = createAcpSessionUpdateProjection();\n let updateSequence = 0;\n const inFlight = new Map<string, TranscriptItem>();\n let historyGeneration = 0;\n const summary = (snapshot: SessionSnapshot): Omit<SessionSnapshot, 'transcript'> => {\n const { transcript: _history, ...value } = snapshot;\n return value;\n };\n const state = replicatedState<SessionServiceState>({\n snapshot: { ...summary(transcript.snapshot()), fastMode: false },\n progress: null,\n updates: [],\n presentation: { revision: 0, dropped: 0, events: [], projections: [] },\n });\n void options.runtime\n .readState()\n .then((runtimeState) => {\n if (!disposed)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.snapshot.fastMode = runtimeState.fastMode === true;\n });\n })\n .catch((error) => {\n if (!disposed) present({ type: 'error', error: String(error) });\n });\n const present = (frame: Record<string, unknown>): boolean => {\n if (frame.type === 'fast_mode_changed' && typeof frame.enabled === 'boolean')\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.snapshot.fastMode = frame.enabled as boolean;\n });\n const entry = frame.entry as { seq?: number } | undefined;\n if (frame.type === 'entry_appended' && typeof entry?.seq === 'number')\n frame = {\n ...frame,\n transcriptCursor: transcriptCursor(options.sessionId, options.runtime.laneName, historyGeneration, entry.seq),\n };\n const next = presentation.record(frame);\n if (next)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.presentation = next;\n });\n return next !== undefined;\n };\n const settlers = new Set<{ resolve(): void; reject(error: Error): void }>();\n const promptFailures = new Set<(error: Error) => void>();\n let promptLatency: PromptLatency | undefined;\n let lastToolResultAt: number | undefined;\n let assistantMessageStartedAt: number | undefined;\n let disposed = false;\n const reportPromptLatency = (phase: string): void => {\n const active = promptLatency;\n if (active === undefined || active.reported.has(phase) || options.telemetry === undefined) return;\n const now = Date.now();\n active.reported.add(phase);\n observe(\n options.telemetry.recordEvent(PROMPT_LATENCY_EVENT, {\n session_id: options.sessionId,\n phase,\n duration_ms: now - active.startedAt,\n stage_duration_ms: now - active.lastStageAt,\n }),\n );\n active.lastStageAt = now;\n };\n const rejectSettlers = (error: Error): void => {\n for (const waiter of settlers) waiter.reject(error);\n settlers.clear();\n };\n\n const subscribePresentation =\n options.onPresentationFrame ??\n ((listener: (frame: DirectHarnessFrame) => void) => options.runtime.onPresentationFrame(listener));\n const unsubscribePresentation = subscribePresentation((frame) => {\n if (disposed) return;\n const message =\n typeof frame.message === 'object' && frame.message !== null ? (frame.message as { role?: unknown }) : undefined;\n if (frame.type === 'message_end' && message?.role === 'toolResult') lastToolResultAt = Date.now();\n if (frame.type === 'message_start' && message?.role === 'assistant') {\n const now = Date.now();\n assistantMessageStartedAt = now;\n if (lastToolResultAt !== undefined && options.telemetry) {\n observe(\n options.telemetry.recordEvent('doompi_server.tool_result_to_response', {\n session_id: options.sessionId,\n duration_ms: now - lastToolResultAt,\n }),\n );\n }\n lastToolResultAt = undefined;\n }\n if (frame.type === 'message_end' && message?.role === 'assistant') {\n if (assistantMessageStartedAt !== undefined && options.telemetry)\n observe(\n options.telemetry.recordEvent('doompi_server.assistant_message', {\n session_id: options.sessionId,\n duration_ms: Date.now() - assistantMessageStartedAt,\n }),\n );\n assistantMessageStartedAt = undefined;\n }\n if (frame.type === 'agent_start') reportPromptLatency('agent_started');\n else if (frame.type === 'message_start' && message?.role === 'assistant') reportPromptLatency('response_started');\n else if (frame.type === 'message_update' && message?.role === 'assistant') reportPromptLatency('first_response');\n else if (frame.type === 'message_end' && message?.role === 'assistant') reportPromptLatency('response_completed');\n const reductionStartedAt = performance.now();\n const reduction = transcript.apply(frame);\n if (frame.type === 'lifecycle_update' && frame.lifecycle !== undefined)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n const lifecycle = frame.lifecycle as SessionLifecycle;\n if ((draft.snapshot.lifecycle?.revision ?? -1) <= lifecycle.revision) draft.snapshot.lifecycle = lifecycle;\n });\n const updates = acpUpdates.apply(frame, reduction);\n const reductionDurationMs = performance.now() - reductionStartedAt;\n if (reduction.aggregate && options.telemetry) {\n observe(\n options.telemetry.recordEvent('doompi_server.transcript.aggregate', {\n session_id: options.sessionId,\n ...reduction.aggregate,\n }),\n );\n }\n if (reduction.snapshot || updates.length > 0) {\n state.change(BACKGROUND_CONTEXT, (draft) => {\n if (reduction.snapshot)\n draft.snapshot = {\n ...summary(reduction.snapshot),\n fastMode: draft.snapshot.fastMode ?? false,\n ...(draft.snapshot.lifecycle === undefined ? {} : { lifecycle: draft.snapshot.lifecycle }),\n };\n if (updates.length > 0) {\n const events = draft.updates ?? [];\n for (const update of updates) events.push({ sequence: ++updateSequence, update });\n if (events.length > 128) events.splice(0, events.length - 128);\n draft.updates = events;\n }\n });\n }\n if (reduction.progress) {\n const progress = reduction.progress;\n if (progress.type === 'item_finished') inFlight.delete(progress.item.id);\n else inFlight.set(progress.item.id, progress.item);\n }\n if (state.value.snapshot.phase === 'idle') inFlight.clear();\n if (frame.type === 'navigation_end') historyGeneration += 1;\n const changed = present(frame);\n const publishStartedAt = performance.now();\n void (reduction.snapshot || reduction.progress || updates.length > 0 || changed);\n const publishDurationMs = performance.now() - publishStartedAt;\n if (options.telemetry && (reductionDurationMs >= 50 || publishDurationMs >= 50 || frame.type === SETTLED))\n observe(\n options.telemetry.recordEvent('doompi_server.presentation_frame', {\n session_id: options.sessionId,\n 'frame.type': frame.type,\n phase: 'reduce_and_publish',\n duration_ms: reductionDurationMs + publishDurationMs,\n }),\n );\n if (frame.type === SETTLED) {\n lastToolResultAt = undefined;\n assistantMessageStartedAt = undefined;\n reportPromptLatency('settled');\n promptLatency = undefined;\n const waiting = [...settlers];\n settlers.clear();\n for (const settle of waiting) settle.resolve();\n }\n });\n\n const terminate = (error: Error): void => {\n if (disposed) return;\n disposed = true;\n for (const fail of promptFailures) fail(error);\n promptFailures.clear();\n rejectSettlers(error);\n unsubscribePresentation();\n };\n observe(\n options.runtime.exited.then(\n () => terminate(new Error('The session runtime exited')),\n (error: unknown) => terminate(error instanceof Error ? error : new Error(String(error))),\n ),\n );\n const requireLive = (): void => {\n if (disposed) throw new Error('The session runtime is disposed');\n };\n const guardContext = (context: Context): void => {\n requireLive();\n context.abortSignal?.throwIfAborted();\n };\n const awaitSettled = (): { promise: Promise<void>; resolve(): void; reject(error: Error): void } => {\n let fail!: (error: Error) => void;\n let finish!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const waiter = {\n resolve: () => {\n settlers.delete(waiter);\n resolve();\n },\n reject: (error: Error) => {\n settlers.delete(waiter);\n reject(error);\n },\n };\n fail = waiter.reject;\n finish = waiter.resolve;\n settlers.add(waiter);\n });\n observe(promise);\n return { promise, resolve: finish, reject: fail };\n };\n const messageArgs = (\n input: string | SessionMessageArgs,\n ): { message: string; images?: SessionMessageArgs['images'] } => {\n const args = typeof input === 'string' ? { text: input } : input;\n if (!args || typeof args.text !== 'string') throw new Error('Prompt message must be a string');\n if (\n args.images !== undefined &&\n (!Array.isArray(args.images) ||\n !args.images.every(\n (image) => image?.type === 'image' && typeof image.data === 'string' && typeof image.mimeType === 'string',\n ))\n )\n throw new Error('Invalid message images');\n return { message: args.text, ...(args.images === undefined ? {} : { images: args.images }) };\n };\n const hydrate = async (): Promise<void> => {\n const lifecycle = await options.runtime.readLifecycle();\n if (disposed) return;\n state.change(BACKGROUND_CONTEXT, (draft) => {\n if ((draft.snapshot.lifecycle?.revision ?? -1) <= lifecycle.revision) draft.snapshot.lifecycle = lifecycle;\n draft.presentation = presentation.resetCustomEntries();\n });\n };\n let initializing: Promise<void> | undefined;\n\n return {\n state,\n async readTranscriptPage(args, context) {\n guardContext(context);\n if (args.threadId !== undefined) {\n if (!options.readThreadTranscript) throw new Error('Child transcript reader is unavailable');\n return options.readThreadTranscript(args.threadId, args, context);\n }\n const generation = historyGeneration;\n const revision = state.value.presentation?.revision ?? 0;\n const drafts = [...inFlight.values()];\n const started = performance.now();\n let snapshot: ReturnType<DirectHarnessRuntime['readEntries']> | undefined;\n const readEntries = () => (snapshot ??= options.runtime.readEntries());\n const page = await readTranscriptPage(\n {\n sessionId: options.runtime.sessionId,\n laneName: options.runtime.laneName,\n lane: {\n getTipId: async () => (await readEntries()).leafId,\n findEntries: async (query) => {\n let entries = (await readEntries()).entries;\n if (query.type) entries = entries.filter((e) => e.type === query.type);\n if (query.customType)\n entries = entries.filter((e) => e.type === 'custom' && e.customType === query.customType);\n if (query.cursor)\n entries = entries.filter((e) =>\n query.order === 'oldestFirst' ? e.seq > query.cursor!.seq : e.seq < query.cursor!.seq,\n );\n if (query.order === 'newestFirst') entries = entries.toReversed();\n return query.limit === undefined ? entries : entries.slice(0, query.limit);\n },\n },\n },\n args,\n generation,\n context,\n );\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('doompi_server.transcript_page', {\n session_id: options.sessionId,\n phase: args.direction ?? 'latest',\n duration_ms: performance.now() - started,\n count: page.entries.length,\n }),\n );\n if (generation !== historyGeneration) throw new Error('STALE_TRANSCRIPT_CURSOR');\n return { ...page, revision, drafts };\n },\n initialize() {\n initializing ??= hydrate().catch((error: unknown) => {\n initializing = undefined;\n throw error;\n });\n return initializing;\n },\n async prompt(text: string | PromptArgs, context) {\n guardContext(context);\n const args = messageArgs(text);\n const waitFor = typeof text === 'string' ? 'settled' : (text.waitFor ?? 'settled');\n if (waitFor !== 'accepted' && waitFor !== 'settled') throw new Error('Invalid prompt acknowledgement mode');\n let projection: ReturnType<typeof awaitSettled> | undefined;\n let latency: PromptLatency | undefined;\n let submitted = false;\n let failed: Error | undefined;\n let rejectFailure!: (error: Error) => void;\n const failure = new Promise<void>((_resolve, reject) => {\n rejectFailure = reject;\n });\n const fail = (error: Error): void => {\n if (failed !== undefined) return;\n failed = error;\n projection?.reject(error);\n rejectFailure(error);\n if (latency !== undefined && promptLatency === latency) {\n reportPromptLatency('failed');\n promptLatency = undefined;\n }\n };\n const cancel = (): void => {\n if (failed !== undefined) return;\n fail(new Error('The session prompt was cancelled', { cause: context.abortSignal?.reason }));\n if (submitted && waitFor === 'settled') void options.runtime.abort().catch(() => undefined);\n };\n const guardPrompt = (): void => {\n if (failed !== undefined) throw failed;\n guardContext(context);\n };\n const submit = async () => {\n guardPrompt();\n submitted = true;\n const submission = await options.runtime.submitPrompt(args.message, args.images);\n observe(submission.settled);\n guardPrompt();\n return submission;\n };\n const span = <T>(name: string, callback: () => Promise<T>): Promise<T> => {\n const operation = options.telemetry\n ? options.telemetry.runInSpan(name, { session_id: options.sessionId }, callback)\n : callback();\n observe(operation);\n return operation;\n };\n const run = async (): Promise<void> => {\n guardPrompt();\n const lifecycle = await options.runtime.readLifecycle();\n guardPrompt();\n if (lifecycle.operation !== null || settlers.size > 0) {\n if (isSelectionCommand(args.message)) {\n const handled = await options.runtime.dispatchCommand(args.message);\n guardPrompt();\n if (handled) return;\n }\n throw new Error('A turn is already running');\n }\n if (waitFor === 'accepted' && !options.telemetry) {\n await submit();\n return;\n }\n const startedAt = Date.now();\n latency = promptLatency = { startedAt, lastStageAt: startedAt, reported: new Set() };\n const settled = (projection = awaitSettled());\n let resolveAdmission: (() => void) | undefined;\n const admitted =\n waitFor === 'accepted'\n ? new Promise<void>((resolve) => {\n resolveAdmission = resolve;\n })\n : undefined;\n const completion = span('doompi_server.prompt_to_settled', async () => {\n const submission = await span('doompi_server.prompt_admission', submit);\n guardPrompt();\n if (submission.handledCommand) settled.resolve();\n reportPromptLatency('accepted');\n resolveAdmission?.();\n await Promise.all([\n span('doompi_server.prompt_engine_settlement', () => submission.settled),\n span('doompi_server.prompt_projection_settlement', () => settled.promise),\n ]);\n }).catch((error: unknown) => {\n const cause = error instanceof Error ? error : new Error(String(error));\n fail(cause);\n throw cause;\n });\n if (admitted) await Promise.race([admitted, completion]);\n else await completion;\n };\n promptFailures.add(fail);\n context.abortSignal?.addEventListener('abort', cancel, { once: true });\n try {\n await Promise.race([run(), failure]);\n } catch (error) {\n const cause = error instanceof Error ? error : new Error(String(error));\n fail(cause);\n throw cause;\n } finally {\n promptFailures.delete(fail);\n context.abortSignal?.removeEventListener('abort', cancel);\n }\n },\n async steer(text: string | SessionMessageArgs) {\n requireLive();\n const args = messageArgs(text);\n const submission = await options.runtime.submitUserPrompt(args.message, args.images);\n void submission.settled.catch((error: unknown) => present({ type: 'error', error: String(error) }));\n },\n async abort() {\n requireLive();\n await options.runtime.abort((await options.runtime.readLifecycle()).operation?.id);\n },\n async abortOperation(args) {\n requireLive();\n if (!args || typeof args.operationId !== 'string' || !args.operationId)\n throw new Error('Invalid operation identity');\n await options.runtime.abort(args.operationId);\n },\n async setModel(model, context) {\n guardContext(context);\n if (!model || typeof model.provider !== 'string' || typeof model.id !== 'string')\n throw new Error('Invalid model');\n await options.runtime.setModel(model);\n },\n async setFastMode(enabled, context) {\n guardContext(context);\n if (typeof enabled !== 'boolean') throw new Error('Invalid fast mode');\n await options.runtime.setFastMode(enabled);\n state.change(context, (draft) => {\n draft.snapshot.fastMode = enabled;\n });\n },\n async setThinking(thinkingLevel, context) {\n guardContext(context);\n if (!['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'].includes(thinkingLevel))\n throw new Error('Invalid thinking level');\n await options.runtime.setThinkingLevel(thinkingLevel);\n },\n async followUp(args, context) {\n guardContext(context);\n const message = messageArgs(args);\n await options.runtime.followUp(message.message, message.images);\n },\n async enqueueAutomatic(args, context) {\n guardContext(context);\n const message = messageArgs(args);\n return options.runtime.enqueueAutomatic(message.message, message.images);\n },\n async removeQueued(args, context) {\n guardContext(context);\n if (!args || typeof args.id !== 'string' || !args.id) throw new Error('Invalid queue identity');\n return options.runtime.removeQueued(args.id);\n },\n async promoteQueued(args, context) {\n guardContext(context);\n if (\n !args ||\n typeof args.id !== 'string' ||\n !args.id ||\n (args.operationId !== undefined && (typeof args.operationId !== 'string' || !args.operationId))\n )\n throw new Error('Invalid queue promotion');\n return options.runtime.promoteQueued(args.id, args.operationId);\n },\n async resumeQueue(context) {\n guardContext(context);\n await options.runtime.resumeQueue();\n },\n async clearQueue(context) {\n guardContext(context);\n return options.runtime.clearQueue();\n },\n async rewind(args, context) {\n guardContext(context);\n if (!args || typeof args.itemId !== 'string' || !args.itemId) throw new Error('Invalid rewind identity');\n const { entries } = await options.runtime.readEntries();\n const entry = entries.toReversed().find((candidate) => {\n if (candidate.type !== 'message' || typeof candidate.id !== 'string') return false;\n const message = candidate.message;\n if (!message || typeof message !== 'object' || Array.isArray(message)) return false;\n const record = message as unknown as Record<string, unknown>;\n return (\n candidate.id === args.itemId ||\n record.id === args.itemId ||\n (record.role === 'user' && typeof record.timestamp === 'number' && args.itemId === `user-${record.timestamp}`)\n );\n });\n if (!entry) throw new Error('The selected message is not in the active session tree.');\n const result = await options.runtime.navigateTree(entry.id, {\n ...(args.summarize === undefined ? {} : { summarize: args.summarize }),\n ...(args.customInstructions === undefined ? {} : { customInstructions: args.customInstructions }),\n ...(args.replaceInstructions === undefined ? {} : { replaceInstructions: args.replaceInstructions }),\n ...(args.label === undefined ? {} : { label: args.label }),\n });\n if (!result.cancelled) await hydrate();\n return result as RewindResult;\n },\n async extensionUiResponse(response, context) {\n guardContext(context);\n if (\n !response ||\n typeof response.id !== 'string' ||\n !response.id ||\n !(\n ('value' in response && typeof response.value === 'string') ||\n ('confirmed' in response && typeof response.confirmed === 'boolean') ||\n ('cancelled' in response && response.cancelled === true)\n )\n )\n throw new Error('Invalid extension UI response');\n if (!options.respondToExtensionUi?.({ ...response, type: 'extension_ui_response' }))\n throw new Error(`No pending extension UI request: ${response.id}`);\n present({ type: 'extension_ui_answered', id: response.id });\n state.change(context, () => undefined);\n },\n async getState(context) {\n guardContext(context);\n const runtimeState = await options.runtime.readState();\n return { ...runtimeState, fastMode: runtimeState.fastMode === true } as unknown as SessionStateInfo;\n },\n async getSessionStats(context) {\n guardContext(context);\n return sessionStats(options.runtime, options.sessionId);\n },\n async getCommands(context) {\n guardContext(context);\n return options.runtime.listCommands() as SessionCommand[];\n },\n async getAvailableModels(context) {\n guardContext(context);\n return (await options.runtime.availableModels()).map((model) => ({\n provider: model.provider,\n id: model.id,\n })) as ModelRef[];\n },\n async getAvailableThinkingLevels(context) {\n guardContext(context);\n return (await options.runtime.availableThinkingLevels()) as ThinkingLevel[];\n },\n async compact(args, context) {\n guardContext(context);\n await options.runtime.compact(args.customInstructions);\n return null;\n },\n async setName(name, context) {\n guardContext(context);\n if (typeof name !== 'string' || name.length > 256) throw new Error('Invalid session name');\n await options.runtime.setName(name);\n },\n async dispose() {\n terminate(new Error('The session runtime is disposed'));\n },\n };\n}\n\nexport interface AgentServerServiceOptions extends AgentSessionRuntimeOptions {\n createdAt: number;\n}\n\nexport interface DoomSessionMetadata {\n id: string;\n createdAt: number;\n storageVersion: number;\n cwd: string;\n sessionName: string;\n}\n\nfunction endpointAttachment(endpoint: RemoteServiceEndpoint): {\n invokeService: RemoteServiceEndpoint['invoke'];\n release(): void;\n} {\n return {\n invokeService: (call, publish, context) => endpoint.invoke(call, publish, context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction managementHost(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: DoomSessionManagementService, mode: 'singleton' }]);\n provider.provide(DoomSessionManagementService, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n return endpointAttachment(createRemoteServiceEndpoint(provider));\n },\n };\n}\n\n/** Creates the 0.85 routed host for one supervised DoomPi session. */\nexport function createAgentServerService(options: AgentServerServiceOptions): ServerHost<DoomSessionMetadata> {\n const metadata: DoomSessionMetadata = {\n id: options.sessionId,\n createdAt: options.createdAt,\n storageVersion: 1,\n cwd: options.cwd,\n sessionName: options.sessionName,\n };\n const runtime = createAgentSessionRuntime(options);\n let closed = false;\n\n return {\n serverServices: managementHost(),\n async resolveSession(sessionId) {\n if (sessionId !== metadata.id) throw new SessionNotFoundError(`No session ${sessionId}`);\n return metadata;\n },\n async openSession() {\n if (closed) throw new SessionNotFoundError('The session service is closed');\n await runtime.initialize();\n const provider = new RemoteServiceProvider([{ service: DoomSessionService, mode: 'singleton' }]);\n provider.provide(DoomSessionService, runtime);\n const handle: RoutedSessionHandle = {\n attachClient: () => endpointAttachment(createRemoteServiceEndpoint(provider)),\n async close() {\n if (closed) return;\n closed = true;\n provider.dispose();\n await runtime.dispose();\n },\n };\n return handle;\n },\n };\n}\n\nexport type { SessionSnapshot };\n"],"mappings":"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"}
1
+ {"version":3,"file":"piSessionRuntime.cjs","names":["createRpcTranscript","createSessionPresentation","createAcpSessionUpdateProjection","replicatedState","BACKGROUND_CONTEXT","transcriptCursor","readTranscriptPage","RemoteServiceProvider","DoomSessionManagementService","createRemoteServiceEndpoint","SessionNotFoundError","DoomSessionService"],"sources":["../../../src/pi/piSessionRuntime.ts"],"sourcesContent":["import {\n createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n type Context,\n type MutableReplicatedState,\n type RemoteServiceEndpoint,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { RoutedServerServiceHost, RoutedSessionHandle, ServerHost } from '@earendil-works/pi-server';\nimport { SessionNotFoundError } from '@earendil-works/pi-server';\n\nimport {\n DoomSessionManagementService,\n DoomSessionService,\n type SessionService,\n type SessionMessageArgs,\n type PromptArgs,\n type SessionServiceState,\n type SessionSnapshot,\n type SessionLifecycle,\n type TranscriptItem,\n type TranscriptPage,\n type TranscriptPageRequest,\n type RewindResult,\n type SessionStateInfo,\n type SessionStats,\n type SessionCommand,\n type ModelRef,\n type ThinkingLevel,\n} from '../exports/sessionProtocol';\nimport { createAcpSessionUpdateProjection } from '../services/acpSessionUpdates';\nimport { createRpcTranscript, type RpcTranscript } from '../services/rpcTranscript';\nimport { observe, type ServerTelemetry } from '../services/serverTelemetry';\nimport { createSessionPresentation } from '../services/sessionPresentation';\nimport { readTranscriptPage, transcriptCursor } from '../services/transcriptPages';\nimport type { DirectHarnessRuntime, DirectHarnessFrame } from '../types/server/directHarnessRuntime';\n\nconst SETTLED = 'agent_settled';\nconst PROMPT_LATENCY_EVENT = 'doompi_server.prompt_latency';\nconst SELECTION_COMMANDS = new Set(['mode', 'domains', 'profile', 'minor']);\n\nfunction isSelectionCommand(text: string): boolean {\n const match = /^\\/(\\S+)/.exec(text);\n return match !== null && SELECTION_COMMANDS.has(match[1]!);\n}\n\ntype PromptLatency = {\n readonly startedAt: number;\n lastStageAt: number;\n readonly reported: Set<string>;\n};\n\nasync function sessionStats(runtime: DirectHarnessRuntime, sessionId: string): Promise<SessionStats> {\n const stored = await runtime.getSessionStats();\n const { contextUsage, sessionFile } = stored;\n return {\n sessionId,\n ...(sessionFile === undefined ? {} : { sessionFile }),\n totalMessages: stored.messageCount,\n tokens: {\n input: stored.usage.input,\n output: stored.usage.output,\n cacheRead: stored.usage.cacheRead,\n cacheWrite: stored.usage.cacheWrite,\n total: stored.usage.totalTokens,\n },\n cost: stored.usage.cost.total,\n ...(contextUsage === undefined ? {} : { contextUsage }),\n };\n}\n\nexport interface AgentSessionRuntimeOptions {\n runtime: DirectHarnessRuntime;\n sessionId: string;\n sessionName: string;\n cwd: string;\n telemetry?: ServerTelemetry;\n /** Subscribes to the combined harness and headless presentation projection. */\n onPresentationFrame?: (listener: (frame: DirectHarnessFrame) => void) => () => void;\n /** Delivers one answered extension UI request to the session-scoped headless host. */\n respondToExtensionUi?: (frame: DirectHarnessFrame) => boolean;\n /** Test seam for the projection. */\n transcript?: RpcTranscript;\n readThreadTranscript?: (\n threadId: string,\n request: TranscriptPageRequest,\n context: Context,\n ) => Promise<TranscriptPage>;\n}\n\nexport interface AgentSessionRuntime extends SessionService {\n readonly state: MutableReplicatedState<SessionServiceState>;\n initialize(): Promise<void>;\n dispose(): Promise<void>;\n}\n\n/** Projects one in-process harness runtime as a Chord session service. */\nexport function createAgentSessionRuntime(options: AgentSessionRuntimeOptions): AgentSessionRuntime {\n const transcript =\n options.transcript ??\n createRpcTranscript({\n id: options.sessionId,\n cwd: options.cwd,\n name: options.sessionName,\n now: Date.now,\n retainEntries: 0,\n });\n const presentation = createSessionPresentation();\n const acpUpdates = createAcpSessionUpdateProjection();\n let updateSequence = 0;\n const inFlight = new Map<string, TranscriptItem>();\n let historyGeneration = 0;\n const summary = (snapshot: SessionSnapshot): Omit<SessionSnapshot, 'transcript'> => {\n const { transcript: _history, ...value } = snapshot;\n return value;\n };\n const state = replicatedState<SessionServiceState>({\n snapshot: { ...summary(transcript.snapshot()), fastMode: false },\n progress: null,\n updates: [],\n presentation: { revision: 0, dropped: 0, events: [], projections: [] },\n });\n void options.runtime\n .readState()\n .then((runtimeState) => {\n if (!disposed)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.snapshot.fastMode = runtimeState.fastMode === true;\n });\n })\n .catch((error) => {\n if (!disposed) present({ type: 'error', error: String(error) });\n });\n const present = (frame: Record<string, unknown>): boolean => {\n if (frame.type === 'fast_mode_changed' && typeof frame.enabled === 'boolean')\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.snapshot.fastMode = frame.enabled as boolean;\n });\n const entry = frame.entry as { seq?: number } | undefined;\n if (frame.type === 'entry_appended' && typeof entry?.seq === 'number')\n frame = {\n ...frame,\n transcriptCursor: transcriptCursor(options.sessionId, options.runtime.laneName, historyGeneration, entry.seq),\n };\n const next = presentation.record(frame);\n if (next)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n draft.presentation = next;\n });\n return next !== undefined;\n };\n const settlers = new Set<{ resolve(): void; reject(error: Error): void }>();\n const promptFailures = new Set<(error: Error) => void>();\n let promptLatency: PromptLatency | undefined;\n let lastToolResultAt: number | undefined;\n let assistantMessageStartedAt: number | undefined;\n let disposed = false;\n const reportPromptLatency = (phase: string): void => {\n const active = promptLatency;\n if (active === undefined || active.reported.has(phase) || options.telemetry === undefined) return;\n const now = Date.now();\n active.reported.add(phase);\n observe(\n options.telemetry.recordEvent(PROMPT_LATENCY_EVENT, {\n session_id: options.sessionId,\n phase,\n duration_ms: now - active.startedAt,\n stage_duration_ms: now - active.lastStageAt,\n }),\n );\n active.lastStageAt = now;\n };\n const rejectSettlers = (error: Error): void => {\n for (const waiter of settlers) waiter.reject(error);\n settlers.clear();\n };\n\n const subscribePresentation =\n options.onPresentationFrame ??\n ((listener: (frame: DirectHarnessFrame) => void) => options.runtime.onPresentationFrame(listener));\n const unsubscribePresentation = subscribePresentation((frame) => {\n if (disposed) return;\n const message =\n typeof frame.message === 'object' && frame.message !== null ? (frame.message as { role?: unknown }) : undefined;\n if (frame.type === 'message_end' && message?.role === 'toolResult') lastToolResultAt = Date.now();\n if (frame.type === 'message_start' && message?.role === 'assistant') {\n const now = Date.now();\n assistantMessageStartedAt = now;\n if (lastToolResultAt !== undefined && options.telemetry) {\n observe(\n options.telemetry.recordEvent('doompi_server.tool_result_to_response', {\n session_id: options.sessionId,\n duration_ms: now - lastToolResultAt,\n }),\n );\n }\n lastToolResultAt = undefined;\n }\n if (frame.type === 'message_end' && message?.role === 'assistant') {\n if (assistantMessageStartedAt !== undefined && options.telemetry)\n observe(\n options.telemetry.recordEvent('doompi_server.assistant_message', {\n session_id: options.sessionId,\n duration_ms: Date.now() - assistantMessageStartedAt,\n }),\n );\n assistantMessageStartedAt = undefined;\n }\n if (frame.type === 'agent_start') reportPromptLatency('agent_started');\n else if (frame.type === 'message_start' && message?.role === 'assistant') reportPromptLatency('response_started');\n else if (frame.type === 'message_update' && message?.role === 'assistant') reportPromptLatency('first_response');\n else if (frame.type === 'message_end' && message?.role === 'assistant') reportPromptLatency('response_completed');\n const reductionStartedAt = performance.now();\n const reduction = transcript.apply(frame);\n if (frame.type === 'lifecycle_update' && frame.lifecycle !== undefined)\n state.change(BACKGROUND_CONTEXT, (draft) => {\n const lifecycle = frame.lifecycle as SessionLifecycle;\n if ((draft.snapshot.lifecycle?.revision ?? -1) <= lifecycle.revision) draft.snapshot.lifecycle = lifecycle;\n });\n const updates = acpUpdates.apply(frame, reduction);\n const reductionDurationMs = performance.now() - reductionStartedAt;\n if (reduction.aggregate && options.telemetry) {\n observe(\n options.telemetry.recordEvent('doompi_server.transcript.aggregate', {\n session_id: options.sessionId,\n ...reduction.aggregate,\n }),\n );\n }\n if (reduction.snapshot || updates.length > 0) {\n state.change(BACKGROUND_CONTEXT, (draft) => {\n if (reduction.snapshot)\n draft.snapshot = {\n ...summary(reduction.snapshot),\n fastMode: draft.snapshot.fastMode ?? false,\n ...(draft.snapshot.lifecycle === undefined ? {} : { lifecycle: draft.snapshot.lifecycle }),\n };\n if (updates.length > 0) {\n const events = draft.updates ?? [];\n for (const update of updates) events.push({ sequence: ++updateSequence, update });\n if (events.length > 128) events.splice(0, events.length - 128);\n draft.updates = events;\n }\n });\n }\n if (reduction.progress) {\n const progress = reduction.progress;\n if (progress.type === 'item_finished') inFlight.delete(progress.item.id);\n else inFlight.set(progress.item.id, progress.item);\n }\n if (state.value.snapshot.phase === 'idle') inFlight.clear();\n if (frame.type === 'navigation_end') historyGeneration += 1;\n const changed = present(frame);\n const publishStartedAt = performance.now();\n void (reduction.snapshot || reduction.progress || updates.length > 0 || changed);\n const publishDurationMs = performance.now() - publishStartedAt;\n if (options.telemetry && (reductionDurationMs >= 50 || publishDurationMs >= 50 || frame.type === SETTLED))\n observe(\n options.telemetry.recordEvent('doompi_server.presentation_frame', {\n session_id: options.sessionId,\n 'frame.type': frame.type,\n phase: 'reduce_and_publish',\n duration_ms: reductionDurationMs + publishDurationMs,\n }),\n );\n if (frame.type === SETTLED) {\n lastToolResultAt = undefined;\n assistantMessageStartedAt = undefined;\n reportPromptLatency('settled');\n promptLatency = undefined;\n const waiting = [...settlers];\n settlers.clear();\n for (const settle of waiting) settle.resolve();\n }\n });\n\n const terminate = (error: Error): void => {\n if (disposed) return;\n disposed = true;\n for (const fail of promptFailures) fail(error);\n promptFailures.clear();\n rejectSettlers(error);\n unsubscribePresentation();\n };\n observe(\n options.runtime.exited.then(\n () => terminate(new Error('The session runtime exited')),\n (error: unknown) => terminate(error instanceof Error ? error : new Error(String(error))),\n ),\n );\n const requireLive = (): void => {\n if (disposed) throw new Error('The session runtime is disposed');\n };\n const guardContext = (context: Context): void => {\n requireLive();\n context.abortSignal?.throwIfAborted();\n };\n const awaitSettled = (): { promise: Promise<void>; resolve(): void; reject(error: Error): void } => {\n let fail!: (error: Error) => void;\n let finish!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const waiter = {\n resolve: () => {\n settlers.delete(waiter);\n resolve();\n },\n reject: (error: Error) => {\n settlers.delete(waiter);\n reject(error);\n },\n };\n fail = waiter.reject;\n finish = waiter.resolve;\n settlers.add(waiter);\n });\n observe(promise);\n return { promise, resolve: finish, reject: fail };\n };\n const messageArgs = (\n input: string | SessionMessageArgs,\n ): { message: string; images?: SessionMessageArgs['images'] } => {\n const args = typeof input === 'string' ? { text: input } : input;\n if (!args || typeof args.text !== 'string') throw new Error('Prompt message must be a string');\n if (\n args.images !== undefined &&\n (!Array.isArray(args.images) ||\n !args.images.every(\n (image) => image?.type === 'image' && typeof image.data === 'string' && typeof image.mimeType === 'string',\n ))\n )\n throw new Error('Invalid message images');\n return { message: args.text, ...(args.images === undefined ? {} : { images: args.images }) };\n };\n const hydrate = async (): Promise<void> => {\n const lifecycle = await options.runtime.readLifecycle();\n if (disposed) return;\n state.change(BACKGROUND_CONTEXT, (draft) => {\n if ((draft.snapshot.lifecycle?.revision ?? -1) <= lifecycle.revision) draft.snapshot.lifecycle = lifecycle;\n draft.presentation = presentation.resetCustomEntries();\n });\n };\n let initializing: Promise<void> | undefined;\n\n return {\n state,\n async readTranscriptPage(args, context) {\n guardContext(context);\n if (args.threadId !== undefined) {\n if (!options.readThreadTranscript) throw new Error('Child transcript reader is unavailable');\n return options.readThreadTranscript(args.threadId, args, context);\n }\n const generation = historyGeneration;\n const revision = state.value.presentation?.revision ?? 0;\n const drafts = [...inFlight.values()];\n const started = performance.now();\n let snapshot: ReturnType<DirectHarnessRuntime['readEntries']> | undefined;\n const readEntries = () => (snapshot ??= options.runtime.readEntries());\n const page = await readTranscriptPage(\n {\n sessionId: options.runtime.sessionId,\n laneName: options.runtime.laneName,\n lane: {\n getTipId: async () => (await readEntries()).leafId,\n findEntries: async (query) => {\n let entries = (await readEntries()).entries;\n if (query.type) entries = entries.filter((e) => e.type === query.type);\n if (query.customType)\n entries = entries.filter((e) => e.type === 'custom' && e.customType === query.customType);\n if (query.cursor)\n entries = entries.filter((e) =>\n query.order === 'oldestFirst' ? e.seq > query.cursor!.seq : e.seq < query.cursor!.seq,\n );\n if (query.order === 'newestFirst') entries = entries.toReversed();\n return query.limit === undefined ? entries : entries.slice(0, query.limit);\n },\n },\n },\n args,\n generation,\n context,\n );\n if (options.telemetry)\n observe(\n options.telemetry.recordEvent('doompi_server.transcript_page', {\n session_id: options.sessionId,\n phase: args.direction ?? 'latest',\n duration_ms: performance.now() - started,\n count: page.entries.length,\n }),\n );\n if (generation !== historyGeneration) throw new Error('STALE_TRANSCRIPT_CURSOR');\n return { ...page, revision, drafts };\n },\n initialize() {\n initializing ??= hydrate().catch((error: unknown) => {\n initializing = undefined;\n throw error;\n });\n return initializing;\n },\n async prompt(text: string | PromptArgs, context) {\n guardContext(context);\n const args = messageArgs(text);\n const waitFor = typeof text === 'string' ? 'settled' : (text.waitFor ?? 'settled');\n if (waitFor !== 'accepted' && waitFor !== 'settled') throw new Error('Invalid prompt acknowledgement mode');\n let projection: ReturnType<typeof awaitSettled> | undefined;\n let latency: PromptLatency | undefined;\n let submitted = false;\n let failed: Error | undefined;\n let rejectFailure!: (error: Error) => void;\n const failure = new Promise<void>((_resolve, reject) => {\n rejectFailure = reject;\n });\n const fail = (error: Error): void => {\n if (failed !== undefined) return;\n failed = error;\n projection?.reject(error);\n rejectFailure(error);\n if (latency !== undefined && promptLatency === latency) {\n reportPromptLatency('failed');\n promptLatency = undefined;\n }\n };\n const cancel = (): void => {\n if (failed !== undefined) return;\n fail(new Error('The session prompt was cancelled', { cause: context.abortSignal?.reason }));\n if (submitted && waitFor === 'settled') void options.runtime.abort().catch(() => undefined);\n };\n const guardPrompt = (): void => {\n if (failed !== undefined) throw failed;\n guardContext(context);\n };\n const submit = async () => {\n guardPrompt();\n submitted = true;\n const submission = await options.runtime.submitPrompt(args.message, args.images);\n observe(submission.settled);\n guardPrompt();\n return submission;\n };\n const span = <T>(name: string, callback: () => Promise<T>): Promise<T> => {\n const operation = options.telemetry\n ? options.telemetry.runInSpan(name, { session_id: options.sessionId }, callback)\n : callback();\n observe(operation);\n return operation;\n };\n const run = async (): Promise<void> => {\n guardPrompt();\n const lifecycle = await options.runtime.readLifecycle();\n guardPrompt();\n if (lifecycle.operation !== null || settlers.size > 0) {\n if (isSelectionCommand(args.message)) {\n const handled = await options.runtime.dispatchCommand(args.message);\n guardPrompt();\n if (handled) return;\n }\n throw new Error('A turn is already running');\n }\n if (waitFor === 'accepted' && !options.telemetry) {\n await submit();\n return;\n }\n const startedAt = Date.now();\n latency = promptLatency = { startedAt, lastStageAt: startedAt, reported: new Set() };\n const settled = (projection = awaitSettled());\n let resolveAdmission: (() => void) | undefined;\n const admitted =\n waitFor === 'accepted'\n ? new Promise<void>((resolve) => {\n resolveAdmission = resolve;\n })\n : undefined;\n const completion = span('doompi_server.prompt_to_settled', async () => {\n const submission = await span('doompi_server.prompt_admission', submit);\n guardPrompt();\n if (submission.handledCommand) settled.resolve();\n reportPromptLatency('accepted');\n resolveAdmission?.();\n await Promise.all([\n span('doompi_server.prompt_engine_settlement', () => submission.settled),\n span('doompi_server.prompt_projection_settlement', () => settled.promise),\n ]);\n }).catch((error: unknown) => {\n const cause = error instanceof Error ? error : new Error(String(error));\n fail(cause);\n throw cause;\n });\n if (admitted) await Promise.race([admitted, completion]);\n else await completion;\n };\n promptFailures.add(fail);\n context.abortSignal?.addEventListener('abort', cancel, { once: true });\n try {\n await Promise.race([run(), failure]);\n } catch (error) {\n const cause = error instanceof Error ? error : new Error(String(error));\n fail(cause);\n throw cause;\n } finally {\n promptFailures.delete(fail);\n context.abortSignal?.removeEventListener('abort', cancel);\n }\n },\n async steer(text: string | SessionMessageArgs) {\n requireLive();\n const args = messageArgs(text);\n await options.runtime.steer(args.message, args.images);\n },\n async abort() {\n requireLive();\n await options.runtime.abort((await options.runtime.readLifecycle()).operation?.id);\n },\n async abortOperation(args) {\n requireLive();\n if (!args || typeof args.operationId !== 'string' || !args.operationId)\n throw new Error('Invalid operation identity');\n await options.runtime.abort(args.operationId);\n },\n async setModel(model, context) {\n guardContext(context);\n if (!model || typeof model.provider !== 'string' || typeof model.id !== 'string')\n throw new Error('Invalid model');\n await options.runtime.setModel(model);\n },\n async setFastMode(enabled, context) {\n guardContext(context);\n if (typeof enabled !== 'boolean') throw new Error('Invalid fast mode');\n await options.runtime.setFastMode(enabled);\n state.change(context, (draft) => {\n draft.snapshot.fastMode = enabled;\n });\n },\n async setThinking(thinkingLevel, context) {\n guardContext(context);\n if (!['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'].includes(thinkingLevel))\n throw new Error('Invalid thinking level');\n await options.runtime.setThinkingLevel(thinkingLevel);\n },\n async followUp(args, context) {\n guardContext(context);\n const message = messageArgs(args);\n await options.runtime.followUp(message.message, message.images);\n },\n async enqueueAutomatic(args, context) {\n guardContext(context);\n const message = messageArgs(args);\n return options.runtime.enqueueAutomatic(message.message, message.images);\n },\n async removeQueued(args, context) {\n guardContext(context);\n if (!args || typeof args.id !== 'string' || !args.id) throw new Error('Invalid queue identity');\n return options.runtime.removeQueued(args.id);\n },\n async promoteQueued(args, context) {\n guardContext(context);\n if (\n !args ||\n typeof args.id !== 'string' ||\n !args.id ||\n (args.operationId !== undefined && (typeof args.operationId !== 'string' || !args.operationId))\n )\n throw new Error('Invalid queue promotion');\n return options.runtime.promoteQueued(args.id, args.operationId);\n },\n async resumeQueue(context) {\n guardContext(context);\n await options.runtime.resumeQueue();\n },\n async clearQueue(context) {\n guardContext(context);\n return options.runtime.clearQueue();\n },\n async rewind(args, context) {\n guardContext(context);\n if (!args || typeof args.itemId !== 'string' || !args.itemId) throw new Error('Invalid rewind identity');\n const { entries } = await options.runtime.readEntries();\n const entry = entries.toReversed().find((candidate) => {\n if (candidate.type !== 'message' || typeof candidate.id !== 'string') return false;\n const message = candidate.message;\n if (!message || typeof message !== 'object' || Array.isArray(message)) return false;\n const record = message as unknown as Record<string, unknown>;\n return (\n candidate.id === args.itemId ||\n record.id === args.itemId ||\n (record.role === 'user' && typeof record.timestamp === 'number' && args.itemId === `user-${record.timestamp}`)\n );\n });\n if (!entry) throw new Error('The selected message is not in the active session tree.');\n const result = await options.runtime.navigateTree(entry.id, {\n ...(args.summarize === undefined ? {} : { summarize: args.summarize }),\n ...(args.customInstructions === undefined ? {} : { customInstructions: args.customInstructions }),\n ...(args.replaceInstructions === undefined ? {} : { replaceInstructions: args.replaceInstructions }),\n ...(args.label === undefined ? {} : { label: args.label }),\n });\n if (!result.cancelled) await hydrate();\n return result as RewindResult;\n },\n async extensionUiResponse(response, context) {\n guardContext(context);\n if (\n !response ||\n typeof response.id !== 'string' ||\n !response.id ||\n !(\n ('value' in response && typeof response.value === 'string') ||\n ('confirmed' in response && typeof response.confirmed === 'boolean') ||\n ('cancelled' in response && response.cancelled === true)\n )\n )\n throw new Error('Invalid extension UI response');\n if (!options.respondToExtensionUi?.({ ...response, type: 'extension_ui_response' }))\n throw new Error(`No pending extension UI request: ${response.id}`);\n present({ type: 'extension_ui_answered', id: response.id });\n state.change(context, () => undefined);\n },\n async getState(context) {\n guardContext(context);\n const runtimeState = await options.runtime.readState();\n return { ...runtimeState, fastMode: runtimeState.fastMode === true } as unknown as SessionStateInfo;\n },\n async getSessionStats(context) {\n guardContext(context);\n return sessionStats(options.runtime, options.sessionId);\n },\n async getCommands(context) {\n guardContext(context);\n return options.runtime.listCommands() as SessionCommand[];\n },\n async getAvailableModels(context) {\n guardContext(context);\n return (await options.runtime.availableModels()).map((model) => ({\n provider: model.provider,\n id: model.id,\n })) as ModelRef[];\n },\n async getAvailableThinkingLevels(context) {\n guardContext(context);\n return (await options.runtime.availableThinkingLevels()) as ThinkingLevel[];\n },\n async compact(args, context) {\n guardContext(context);\n await options.runtime.compact(args.customInstructions);\n return null;\n },\n async setName(name, context) {\n guardContext(context);\n if (typeof name !== 'string' || name.length > 256) throw new Error('Invalid session name');\n await options.runtime.setName(name);\n },\n async dispose() {\n terminate(new Error('The session runtime is disposed'));\n },\n };\n}\n\nexport interface AgentServerServiceOptions extends AgentSessionRuntimeOptions {\n createdAt: number;\n}\n\nexport interface DoomSessionMetadata {\n id: string;\n createdAt: number;\n storageVersion: number;\n cwd: string;\n sessionName: string;\n}\n\nfunction endpointAttachment(endpoint: RemoteServiceEndpoint): {\n invokeService: RemoteServiceEndpoint['invoke'];\n release(): void;\n} {\n return {\n invokeService: (call, publish, context) => endpoint.invoke(call, publish, context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction managementHost(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: DoomSessionManagementService, mode: 'singleton' }]);\n provider.provide(DoomSessionManagementService, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n return endpointAttachment(createRemoteServiceEndpoint(provider));\n },\n };\n}\n\n/** Creates the 0.85 routed host for one supervised DoomPi session. */\nexport function createAgentServerService(options: AgentServerServiceOptions): ServerHost<DoomSessionMetadata> {\n const metadata: DoomSessionMetadata = {\n id: options.sessionId,\n createdAt: options.createdAt,\n storageVersion: 1,\n cwd: options.cwd,\n sessionName: options.sessionName,\n };\n const runtime = createAgentSessionRuntime(options);\n let closed = false;\n\n return {\n serverServices: managementHost(),\n async resolveSession(sessionId) {\n if (sessionId !== metadata.id) throw new SessionNotFoundError(`No session ${sessionId}`);\n return metadata;\n },\n async openSession() {\n if (closed) throw new SessionNotFoundError('The session service is closed');\n await runtime.initialize();\n const provider = new RemoteServiceProvider([{ service: DoomSessionService, mode: 'singleton' }]);\n provider.provide(DoomSessionService, runtime);\n const handle: RoutedSessionHandle = {\n attachClient: () => endpointAttachment(createRemoteServiceEndpoint(provider)),\n async close() {\n if (closed) return;\n closed = true;\n provider.dispose();\n await runtime.dispose();\n },\n };\n return handle;\n },\n };\n}\n\nexport type { SessionSnapshot };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"piSessionRuntime.d.mts","names":[],"sources":["../../../src/pi/piSessionRuntime.ts"],"mappings":";;;;;;;;iBAwEiB;EACf,SAAS;EACT;EACA;EACA;EACA,YAAY;;EAEZ,uBAAuB,WAAW,OAAO;;EAEzC,wBAAwB,OAAO;;EAE/B,aAAa;EACb,wBACE,kBACA,SAAS,uBACT,SAAS,YACN,QAAQ;;iBAGE,4BAA4B;WAClC,OAAO,uBAAuB;EACvC,cAAc;EACd,WAAW;;;wBAIG,0BAA0B,SAAS,6BAA6B;iBAgjB/D,kCAAkC;EACjD;;iBAGe;EACf;EACA;EACA;EACA;EACA;;;wBA2Bc,yBAAyB,SAAS,4BAA4B,WAAW"}
1
+ {"version":3,"file":"piSessionRuntime.d.mts","names":[],"sources":["../../../src/pi/piSessionRuntime.ts"],"mappings":";;;;;;;;iBAwEiB;EACf,SAAS;EACT;EACA;EACA;EACA,YAAY;;EAEZ,uBAAuB,WAAW,OAAO;;EAEzC,wBAAwB,OAAO;;EAE/B,aAAa;EACb,wBACE,kBACA,SAAS,uBACT,SAAS,YACN,QAAQ;;iBAGE,4BAA4B;WAClC,OAAO,uBAAuB;EACvC,cAAc;EACd,WAAW;;;wBAIG,0BAA0B,SAAS,6BAA6B;iBA+iB/D,kCAAkC;EACjD;;iBAGe;EACf;EACA;EACA;EACA;EACA;;;wBA2Bc,yBAAyB,SAAS,4BAA4B,WAAW"}
@@ -409,10 +409,7 @@ function createAgentSessionRuntime(options) {
409
409
  async steer(text) {
410
410
  requireLive();
411
411
  const args = messageArgs(text);
412
- (await options.runtime.submitUserPrompt(args.message, args.images)).settled.catch((error) => present({
413
- type: "error",
414
- error: String(error)
415
- }));
412
+ await options.runtime.steer(args.message, args.images);
416
413
  },
417
414
  async abort() {
418
415
  requireLive();