@geminixiang/mikan 1.0.0-beta.37 → 1.0.0-beta.39

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 (201) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/adapter.js +1 -1
  4. package/dist/adapter.js.map +1 -1
  5. package/dist/adapters/discord/bot.d.ts +3 -6
  6. package/dist/adapters/discord/bot.d.ts.map +1 -1
  7. package/dist/adapters/discord/bot.js +16 -39
  8. package/dist/adapters/discord/bot.js.map +1 -1
  9. package/dist/adapters/github/bot.d.ts +2 -0
  10. package/dist/adapters/github/bot.d.ts.map +1 -1
  11. package/dist/adapters/github/bot.js +15 -11
  12. package/dist/adapters/github/bot.js.map +1 -1
  13. package/dist/adapters/github/github-ops.d.ts +1 -1
  14. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  15. package/dist/adapters/github/github-ops.js +2 -1
  16. package/dist/adapters/github/github-ops.js.map +1 -1
  17. package/dist/adapters/github/repo.d.ts +2 -1
  18. package/dist/adapters/github/repo.d.ts.map +1 -1
  19. package/dist/adapters/github/repo.js +2 -3
  20. package/dist/adapters/github/repo.js.map +1 -1
  21. package/dist/adapters/github/types.d.ts +1 -1
  22. package/dist/adapters/github/types.d.ts.map +1 -1
  23. package/dist/adapters/github/types.js.map +1 -1
  24. package/dist/adapters/intake.js +1 -1
  25. package/dist/adapters/intake.js.map +1 -1
  26. package/dist/adapters/shared.d.ts +17 -5
  27. package/dist/adapters/shared.d.ts.map +1 -1
  28. package/dist/adapters/shared.js +44 -8
  29. package/dist/adapters/shared.js.map +1 -1
  30. package/dist/adapters/slack/blocks.d.ts +14 -0
  31. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  32. package/dist/adapters/slack/blocks.js +34 -0
  33. package/dist/adapters/slack/blocks.js.map +1 -1
  34. package/dist/adapters/slack/bot.d.ts +19 -6
  35. package/dist/adapters/slack/bot.d.ts.map +1 -1
  36. package/dist/adapters/slack/bot.js +88 -21
  37. package/dist/adapters/slack/bot.js.map +1 -1
  38. package/dist/adapters/slack/types.d.ts +1 -1
  39. package/dist/adapters/slack/types.js.map +1 -1
  40. package/dist/adapters/telegram/bot.d.ts +5 -6
  41. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  42. package/dist/adapters/telegram/bot.js +29 -51
  43. package/dist/adapters/telegram/bot.js.map +1 -1
  44. package/dist/adapters/types.d.ts +19 -1
  45. package/dist/adapters/types.d.ts.map +1 -1
  46. package/dist/adapters/types.js.map +1 -1
  47. package/dist/agent.d.ts +0 -1
  48. package/dist/agent.d.ts.map +1 -1
  49. package/dist/agent.js +79 -101
  50. package/dist/agent.js.map +1 -1
  51. package/dist/cli/ext-dev.d.ts.map +1 -1
  52. package/dist/cli/ext-dev.js +8 -8
  53. package/dist/cli/ext-dev.js.map +1 -1
  54. package/dist/cli/ext.js +3 -3
  55. package/dist/cli/ext.js.map +1 -1
  56. package/dist/cli/office.js +2 -2
  57. package/dist/cli/office.js.map +1 -1
  58. package/dist/commands/auto-reply.d.ts.map +1 -1
  59. package/dist/commands/auto-reply.js +1 -2
  60. package/dist/commands/auto-reply.js.map +1 -1
  61. package/dist/commands/login.js +1 -1
  62. package/dist/commands/login.js.map +1 -1
  63. package/dist/commands/manifest.d.ts.map +1 -1
  64. package/dist/commands/manifest.js +3 -1
  65. package/dist/commands/manifest.js.map +1 -1
  66. package/dist/commands/model.d.ts.map +1 -1
  67. package/dist/commands/model.js +3 -7
  68. package/dist/commands/model.js.map +1 -1
  69. package/dist/commands/sandbox.d.ts.map +1 -1
  70. package/dist/commands/sandbox.js +7 -7
  71. package/dist/commands/sandbox.js.map +1 -1
  72. package/dist/commands/session-view.d.ts.map +1 -1
  73. package/dist/commands/session-view.js +1 -2
  74. package/dist/commands/session-view.js.map +1 -1
  75. package/dist/commands/types.d.ts +2 -1
  76. package/dist/commands/types.d.ts.map +1 -1
  77. package/dist/commands/types.js.map +1 -1
  78. package/dist/config.d.ts +10 -18
  79. package/dist/config.d.ts.map +1 -1
  80. package/dist/config.js +16 -15
  81. package/dist/config.js.map +1 -1
  82. package/dist/execution-resolver.d.ts +4 -6
  83. package/dist/execution-resolver.d.ts.map +1 -1
  84. package/dist/execution-resolver.js +10 -19
  85. package/dist/execution-resolver.js.map +1 -1
  86. package/dist/harness/extensions/loader.js +1 -1
  87. package/dist/harness/extensions/loader.js.map +1 -1
  88. package/dist/harness/skills.d.ts +8 -0
  89. package/dist/harness/skills.d.ts.map +1 -1
  90. package/dist/harness/skills.js +46 -4
  91. package/dist/harness/skills.js.map +1 -1
  92. package/dist/harness/types.d.ts +2 -0
  93. package/dist/harness/types.d.ts.map +1 -1
  94. package/dist/harness/types.js.map +1 -1
  95. package/dist/index.d.ts +2 -0
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +1 -0
  98. package/dist/index.js.map +1 -1
  99. package/dist/main.js +16 -16
  100. package/dist/main.js.map +1 -1
  101. package/dist/{office-address.d.ts → office/address.d.ts} +13 -14
  102. package/dist/office/address.d.ts.map +1 -0
  103. package/dist/{office-address.js → office/address.js} +13 -18
  104. package/dist/office/address.js.map +1 -0
  105. package/dist/office/index.d.ts +11 -0
  106. package/dist/office/index.d.ts.map +1 -0
  107. package/dist/office/index.js +11 -0
  108. package/dist/office/index.js.map +1 -0
  109. package/dist/office/layout.d.ts +20 -0
  110. package/dist/office/layout.d.ts.map +1 -0
  111. package/dist/office/layout.js +88 -0
  112. package/dist/office/layout.js.map +1 -0
  113. package/dist/{office-migration.d.ts → office/migration.d.ts} +3 -3
  114. package/dist/office/migration.d.ts.map +1 -0
  115. package/dist/{office-migration.js → office/migration.js} +8 -12
  116. package/dist/office/migration.js.map +1 -0
  117. package/dist/{office-registry.d.ts → office/registry.d.ts} +18 -24
  118. package/dist/office/registry.d.ts.map +1 -0
  119. package/dist/{office-registry.js → office/registry.js} +22 -83
  120. package/dist/office/registry.js.map +1 -0
  121. package/dist/office/types.d.ts +71 -0
  122. package/dist/office/types.d.ts.map +1 -0
  123. package/dist/office/types.js +2 -0
  124. package/dist/office/types.js.map +1 -0
  125. package/dist/packages/admin.js +5 -5
  126. package/dist/packages/admin.js.map +1 -1
  127. package/dist/packages/inspect.d.ts.map +1 -1
  128. package/dist/packages/inspect.js +3 -8
  129. package/dist/packages/inspect.js.map +1 -1
  130. package/dist/packages/materialize.js +1 -1
  131. package/dist/packages/materialize.js.map +1 -1
  132. package/dist/packages/resolve.js +5 -8
  133. package/dist/packages/resolve.js.map +1 -1
  134. package/dist/packages/types.d.ts +2 -5
  135. package/dist/packages/types.d.ts.map +1 -1
  136. package/dist/packages/types.js.map +1 -1
  137. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  138. package/dist/runtime/conversation-runtime.js +13 -15
  139. package/dist/runtime/conversation-runtime.js.map +1 -1
  140. package/dist/runtime/session-lifecycle.js +1 -1
  141. package/dist/runtime/session-lifecycle.js.map +1 -1
  142. package/dist/runtime/types.d.ts +3 -2
  143. package/dist/runtime/types.d.ts.map +1 -1
  144. package/dist/runtime/types.js.map +1 -1
  145. package/dist/sandbox/identity.js +1 -1
  146. package/dist/sandbox/identity.js.map +1 -1
  147. package/dist/settings-mutation.d.ts +3 -2
  148. package/dist/settings-mutation.d.ts.map +1 -1
  149. package/dist/settings-mutation.js +6 -7
  150. package/dist/settings-mutation.js.map +1 -1
  151. package/dist/tools/generate-image.d.ts +8 -2
  152. package/dist/tools/generate-image.d.ts.map +1 -1
  153. package/dist/tools/generate-image.js +5 -3
  154. package/dist/tools/generate-image.js.map +1 -1
  155. package/dist/tools/index.d.ts +5 -0
  156. package/dist/tools/index.d.ts.map +1 -1
  157. package/dist/tools/index.js +3 -5
  158. package/dist/tools/index.js.map +1 -1
  159. package/dist/trigger.d.ts +1 -1
  160. package/dist/trigger.d.ts.map +1 -1
  161. package/dist/trigger.js +5 -10
  162. package/dist/trigger.js.map +1 -1
  163. package/dist/types.d.ts +3 -22
  164. package/dist/types.d.ts.map +1 -1
  165. package/dist/types.js.map +1 -1
  166. package/dist/vault/index.js +1 -1
  167. package/dist/vault/index.js.map +1 -1
  168. package/dist/vault/injection.d.ts +3 -1
  169. package/dist/vault/injection.d.ts.map +1 -1
  170. package/dist/vault/injection.js +2 -2
  171. package/dist/vault/injection.js.map +1 -1
  172. package/dist/web/admin/portal.d.ts.map +1 -1
  173. package/dist/web/admin/portal.js +67 -80
  174. package/dist/web/admin/portal.js.map +1 -1
  175. package/dist/web/admin/types.d.ts +2 -1
  176. package/dist/web/admin/types.d.ts.map +1 -1
  177. package/dist/web/admin/types.js.map +1 -1
  178. package/dist/web/server.d.ts +1 -1
  179. package/dist/web/server.d.ts.map +1 -1
  180. package/dist/web/server.js +3 -3
  181. package/dist/web/server.js.map +1 -1
  182. package/dist/web/session-view/portal.js +1 -1
  183. package/dist/web/session-view/portal.js.map +1 -1
  184. package/dist/workspace-projection/index.d.ts +2 -4
  185. package/dist/workspace-projection/index.d.ts.map +1 -1
  186. package/dist/workspace-projection/index.js +21 -56
  187. package/dist/workspace-projection/index.js.map +1 -1
  188. package/dist/workspace-projection/types.d.ts +0 -2
  189. package/dist/workspace-projection/types.d.ts.map +1 -1
  190. package/dist/workspace-projection/types.js.map +1 -1
  191. package/package.json +41 -16
  192. package/dist/office-address.d.ts.map +0 -1
  193. package/dist/office-address.js.map +0 -1
  194. package/dist/office-migration.d.ts.map +0 -1
  195. package/dist/office-migration.js.map +0 -1
  196. package/dist/office-registry.d.ts.map +0 -1
  197. package/dist/office-registry.js.map +0 -1
  198. package/dist/store.d.ts +0 -51
  199. package/dist/store.d.ts.map +0 -1
  200. package/dist/store.js +0 -185
  201. package/dist/store.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-runtime.js","sourceRoot":"","sources":["../../src/runtime/conversation-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n ConversationKind,\n OfficeAddress,\n PlatformName,\n RunningSession,\n} from \"../adapter.js\";\nimport { conversationOfficeDir, officeDirName, officeKey } from \"../office-address.js\";\nimport { createRunner } from \"../agent.js\";\nimport type { PiAgentWrapper } from \"../agent.js\";\nimport { MikanModels } from \"../harness/index.js\";\nimport type { ExtensionBlockAction } from \"../harness/index.js\";\nimport { defaultCommandHandlers, dispatchCommand } from \"../commands/registry.js\";\nimport type { CommandHandler, CommandServices } from \"../commands/types.js\";\nimport { isPrivateConversation } from \"../commands/utils.js\";\nimport * as log from \"../log.js\";\nimport {\n addLifecycleBreadcrumb,\n applyRunScope,\n createRunAttributionAttributes,\n registerTraceAttribution,\n reportUserFacingError,\n} from \"../observability/sentry.js\";\nimport {\n ChatHistorySync,\n hasMaterializedChatSession,\n waitForThreadSessionBootstrap,\n} from \"../sessions/chat-history-sync.js\";\nimport { shouldRotateTopLevelSession } from \"../sessions/rotation.js\";\nimport { resolveChannelSessionFile } from \"../sessions/store.js\";\nimport {\n assertSessionKeyBelongsToConversation,\n deriveSessionKey,\n} from \"../sessions/session-key.js\";\nimport { formatNothingRunning, formatStopped, formatStopping } from \"../platform-messages.js\";\nimport * as Sentry from \"@sentry/node\";\nimport { getUnresolvedSandboxPathContext } from \"../sandbox/index.js\";\nimport { disabledVaultManager } from \"../vault/disabled.js\";\nimport type { ConversationRuntimeState } from \"./types.js\";\nimport { SessionLifecycle } from \"./session-lifecycle.js\";\n\ntype ConversationState = ConversationRuntimeState;\n\nexport type {\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n} from \"./types.js\";\nimport type {\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n SessionStateOptions,\n} from \"./types.js\";\n\n/**\n * Placeholder token store for embedders that run without the web portal.\n * Command handlers guard on `portalBaseUrl` before minting tokens, so this\n * only fires when a portal URL is configured without its backing store.\n */\nfunction portalNotConfiguredTokenStore(portal: string): { create: () => never } {\n return {\n create: () => {\n throw new Error(`${portal} portal not configured`);\n },\n };\n}\n\nfunction runtimeCwdForSandbox(\n sandbox: ConversationRuntimeOptions[\"sandbox\"],\n hostWorkspaceRoot: string,\n address: OfficeAddress,\n): string {\n const runtimeWorkspaceRoot = getUnresolvedSandboxPathContext(\n sandbox,\n hostWorkspaceRoot,\n ).runtimeWorkspaceRoot;\n return `${runtimeWorkspaceRoot.replace(/\\/+$/, \"\")}/${officeDirName(address)}`;\n}\n\nexport function createConversationRuntime(\n options: ConversationRuntimeOptions,\n): ConversationRuntime {\n return new ConversationRuntimeImpl(options);\n}\n\nclass ConversationRuntimeImpl implements ConversationRuntime {\n private readonly sessions = new SessionLifecycle();\n private readonly inFlightRuns = new Set<Promise<void>>();\n private readonly sessionDreamSettlements = new Set<Promise<void>>();\n private readonly chatSessionManager = new ChatHistorySync();\n private readonly commandServices: CommandServices;\n private readonly commandHandlers: readonly CommandHandler[];\n private readonly resolvedModels: MikanModels;\n private globalRunnerGeneration = 0;\n private readonly conversationRunnerGenerations = new Map<string, number>();\n private isShuttingDown = false;\n\n constructor(private readonly options: ConversationRuntimeOptions) {\n this.resolvedModels = options.models ?? MikanModels.create();\n this.commandServices = {\n ...options,\n resourceController: options.resourceController ?? options.provisioner,\n vaultManager: options.vaultManager ?? disabledVaultManager,\n linkTokenStore: options.linkTokenStore ?? portalNotConfiguredTokenStore(\"Login\"),\n sessionViewTokenStore:\n options.sessionViewTokenStore ?? portalNotConfiguredTokenStore(\"Session viewer\"),\n adminTokenStore: options.adminTokenStore ?? portalNotConfiguredTokenStore(\"Admin\"),\n runtime: this,\n };\n this.commandHandlers = options.commandHandlers ?? defaultCommandHandlers(this.resolvedModels);\n }\n\n isRunning(address: OfficeAddress, sessionKey: string): boolean {\n return this.sessions.isRunning(address, sessionKey);\n }\n\n getRunningSessions(): RunningSession[] {\n const sessions: RunningSession[] = [];\n for (const state of this.sessions.runningStates()) {\n if (state.startedAt) {\n const currentStep = state.runner.getCurrentStep();\n sessions.push({\n address: state.address,\n sessionKey: state.sessionKey,\n startedAt: state.startedAt,\n lastActivityAt: state.lastActivityAt,\n currentTool: currentStep?.label || currentStep?.toolName,\n });\n }\n }\n return sessions;\n }\n\n async handleStop(address: OfficeAddress, sessionKey: string, bot: MessagingBot): Promise<void> {\n assertSessionKeyBelongsToConversation(sessionKey, address.conversationId);\n const state = this.sessions.get(address, sessionKey);\n if (state?.running) {\n state.stopRequested = true;\n state.runner.abort();\n const ts = await bot.postMessage(address.conversationId, formatStopping(bot));\n state.stopMessageTs = ts;\n } else {\n await bot.postMessage(address.conversationId, formatNothingRunning(bot));\n }\n }\n\n forceStop(address: OfficeAddress, sessionKey: string): void {\n const state = this.sessions.get(address, sessionKey);\n if (state?.running) {\n log.logInfo(`[Force Stop] Force stopping session: ${sessionKey}`);\n state.stopRequested = true;\n state.runner.abort();\n }\n }\n\n async handleNewCommand(\n sessionKey: string,\n conversationId: string,\n bot: MessagingBot,\n message: ConversationContext[\"message\"],\n responder: ConversationContext[\"responder\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<void> {\n // The message's address is the authority; the raw id is still passed for\n // filesystem layout, so a disagreement must fail loudly, not pick one.\n const address = message.address;\n if (conversationId !== address.conversationId) {\n throw new Error(\n `Conversation id ${JSON.stringify(conversationId)} does not match office ` +\n JSON.stringify(address.conversationId),\n );\n }\n assertSessionKeyBelongsToConversation(sessionKey, address.conversationId);\n const activeState = this.sessions.get(address, sessionKey);\n if (\n activeState?.running ||\n (activeState?.runSettlement && this.sessionDreamSettlements.has(activeState.runSettlement))\n ) {\n const activeSettlement = activeState.runSettlement;\n if (activeSettlement && this.sessionDreamSettlements.has(activeSettlement)) {\n await activeSettlement;\n return;\n }\n activeState.stopRequested = true;\n activeState.runner.abort();\n await activeSettlement;\n }\n\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n conversationKind: message.conversationKind,\n });\n if (\n state.running ||\n (state.runSettlement && this.sessionDreamSettlements.has(state.runSettlement))\n ) {\n const activeSettlement = state.runSettlement;\n if (activeSettlement && this.sessionDreamSettlements.has(activeSettlement)) {\n await activeSettlement;\n return;\n }\n state.stopRequested = true;\n state.runner.abort();\n await activeSettlement;\n return this.handleNewCommand(sessionKey, conversationId, bot, message, responder, platform);\n }\n const dreamSettlement = this.startSessionDream(state, async () => {\n let working = false;\n try {\n await responder.setWorking(true);\n working = true;\n const result = await this.dreamSessionMemory(state, message, platform);\n if (!result.success) {\n const detail = result.errorMessage ? ` ${result.errorMessage}` : \"\";\n await responder.respondDiagnostic(\n `Could not preserve memory, so the current conversation was not reset.${detail}`,\n { style: \"error\" },\n );\n return;\n }\n\n await responder.setWorking(false);\n working = false;\n await this.resetSession(state, bot);\n } finally {\n if (working) await responder.setWorking(false);\n }\n });\n try {\n await dreamSettlement;\n } finally {\n this.finishSessionDream(state, dreamSettlement);\n }\n }\n\n private startSessionDream(\n state: ConversationState,\n dream: () => Promise<void>,\n markRunning = true,\n ): Promise<void> {\n if (markRunning) {\n state.running = true;\n state.stopRequested = false;\n state.startedAt = Date.now();\n state.lastActivityAt = Date.now();\n }\n\n const settlement = Promise.resolve().then(dream);\n state.runSettlement = settlement;\n this.sessionDreamSettlements.add(settlement);\n this.inFlightRuns.add(settlement);\n return settlement;\n }\n\n private finishSessionDream(state: ConversationState, settlement: Promise<void>): void {\n this.sessionDreamSettlements.delete(settlement);\n this.inFlightRuns.delete(settlement);\n if (state.runSettlement !== settlement) return;\n\n state.runSettlement = undefined;\n state.running = false;\n state.startedAt = 0;\n state.lastAccessedAt = Date.now();\n this.sessions.onSettlement(state.address);\n this.sessions.evictIdle();\n }\n\n private async dreamSessionMemory(\n state: ConversationState,\n message: ConversationContext[\"message\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<{ success: boolean; errorMessage?: string }> {\n try {\n const result = await state.runner.dreamSessionMemory(message, platform);\n // Only a clean stop means the dream finished its work. Everything else —\n // budget abort, length cutoff, error, blocked — leaves memory unwritten,\n // and treating it as success resets the session and loses it silently.\n // Listed as a whitelist so a new stop reason fails safe.\n if (result.stopReason !== \"stop\") {\n return {\n success: false,\n errorMessage: result.errorMessage ?? `Session Dream stopped early (${result.stopReason})`,\n };\n }\n return { success: true };\n } catch (err) {\n return { success: false, errorMessage: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async rotateSharedSessionAfterDream(\n address: OfficeAddress,\n sessionKey: string,\n message: ConversationContext[\"message\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<void> {\n const conversationId = address.conversationId;\n if (message.conversationKind !== \"shared\" || sessionKey !== conversationId) return;\n\n const conversationDir = conversationOfficeDir(this.options.workingDir, address);\n const currentSession = resolveChannelSessionFile(conversationDir);\n if (!currentSession || !shouldRotateTopLevelSession(currentSession, new Date())) return;\n\n await this.sessions.runConversationMaintenance(address, async () => {\n const session = resolveChannelSessionFile(conversationDir);\n if (!session || !shouldRotateTopLevelSession(session, new Date())) return;\n\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n conversationKind: message.conversationKind,\n currentMessageId: message.id,\n });\n const dreamSettlement = this.startSessionDream(\n state,\n async () => {\n const result = await this.dreamSessionMemory(state, message, platform);\n if (!result.success) {\n const detail = result.errorMessage ? `: ${result.errorMessage}` : \"\";\n log.logWarning(`[${conversationId}] Automatic Session Dream failed${detail}`);\n return;\n }\n\n const runtimeCwd = runtimeCwdForSandbox(\n this.options.sandbox,\n this.options.workingDir,\n address,\n );\n this.chatSessionManager.resetSession({ conversationDir, sessionKey, cwd: runtimeCwd });\n this.sessions.discard(address, sessionKey);\n log.logInfo(\n `[${conversationId}] Session Dream completed; rotated session: ${sessionKey}`,\n );\n },\n false,\n );\n try {\n await dreamSettlement;\n } finally {\n this.finishSessionDream(state, dreamSettlement);\n }\n });\n }\n\n private async resetSession(state: ConversationState, bot: MessagingBot): Promise<void> {\n const { address, sessionKey } = state;\n const conversationId = address.conversationId;\n const conversationDir = conversationOfficeDir(this.options.workingDir, address);\n const runtimeCwd = runtimeCwdForSandbox(this.options.sandbox, this.options.workingDir, address);\n this.chatSessionManager.resetSession({ conversationDir, sessionKey, cwd: runtimeCwd });\n\n this.sessions.discard(address, sessionKey);\n\n log.logInfo(`[${conversationId}] Session reset: ${sessionKey}`);\n await bot.postMessage(conversationId, \"Conversation reset. Send a new message to start fresh.\");\n }\n\n async handleEvent(\n event: ConversationEvent,\n bot: MessagingBot,\n context: ConversationContext,\n ): Promise<void> {\n const sessionKey = deriveSessionKey(event);\n await this.sessions.enqueue(event.address, sessionKey, () =>\n this.runSession({ event, bot, context }),\n );\n }\n\n /**\n * Dispatch an extension-owned interactive block action: materialize the\n * conversation's harness instance (activating its extensions) and run the\n * matching onAction handler — deterministic, no agent run. Serialized on\n * the session queue so rapid interactions (votes) never interleave.\n */\n async handleExtensionAction(params: {\n address: OfficeAddress;\n sessionKey: string;\n conversationKind: ConversationKind;\n slug: string;\n action: ExtensionBlockAction;\n }): Promise<boolean> {\n if (this.isShuttingDown) return false;\n const { address, sessionKey, conversationKind, slug, action } = params;\n const conversationId = address.conversationId;\n let consumed = false;\n await this.sessions.enqueue(address, sessionKey, async () => {\n try {\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n currentMessageId: action.messageTs ?? sessionKey,\n conversationKind,\n });\n consumed = await state.runner.tryExtensionAction(slug, action);\n if (consumed) state.lastAccessedAt = Date.now();\n } catch (err) {\n log.logWarning(\n `[${conversationId}] Extension action dispatch failed (${slug}:${action.actionId})`,\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n return consumed;\n }\n\n async runSession({ event, bot, context }: RunSessionOptions): Promise<void> {\n const conversationId = event.conversationId;\n if (this.isShuttingDown) {\n log.logInfo(\n `[${conversationId}] Rejected event during shutdown: ${event.text.substring(0, 50)}`,\n );\n return;\n }\n\n const sessionKey = deriveSessionKey(event);\n const privateConversation = isPrivateConversation(event);\n const handledCommand = await dispatchCommand(this.commandHandlers, {\n bot,\n responder: context.responder,\n platform: context.platform.name as PlatformName,\n address: event.address,\n platformUserId: event.user,\n platformUserName: context.message.userName,\n conversationId,\n vaultConversationId: event.vaultConversationId,\n sessionKey,\n commandText: event.text,\n privateConversation,\n services: this.commandServices,\n });\n if (handledCommand) return;\n\n const address = event.address;\n const activeSettlement = this.sessions.get(address, sessionKey)?.runSettlement;\n if (activeSettlement) await activeSettlement;\n\n if (sessionKey === conversationId) {\n await this.rotateSharedSessionAfterDream(\n address,\n sessionKey,\n context.message,\n context.platform,\n );\n }\n\n const releaseConversationWork = await this.sessions.acquireConversationWork(address);\n try {\n const conversationDir = conversationOfficeDir(this.options.workingDir, address);\n const waitedForParent = await waitForThreadSessionBootstrap({\n parentSessionKey: conversationId,\n sessionKey,\n hasThreadSession: () => hasMaterializedChatSession({ conversationDir, sessionKey }),\n isParentRunning: () => this.sessions.get(address, conversationId)?.running === true,\n });\n if (waitedForParent) {\n log.logInfo(\n `[${conversationId}] Delayed thread bootstrap until parent session sealed: ${sessionKey}`,\n );\n }\n\n let state: ConversationState;\n try {\n state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n currentMessageId: event.ts,\n conversationKind: event.conversationKind,\n });\n state.runner.syncChatHistory(event.ts);\n\n // Extension-contributed commands: deterministic dispatch, no agent run.\n // Built-in commands already had their chance above, so extensions can\n // never shadow them; unmatched slash text falls through to the agent.\n if (event.text.trim().startsWith(\"/\")) {\n const handled = await state.runner.tryExtensionCommand(\n context.message,\n context.responder,\n );\n if (handled) {\n state.lastAccessedAt = Date.now();\n return;\n }\n }\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"mikan\",\n surface: \"session_setup\",\n operation: \"get_or_create_state\",\n severity: \"error\",\n platform: context.platform.name,\n context: {\n conversationId,\n sessionKey,\n messageId: context.message.id,\n threadTs: context.message.threadTs,\n attachmentCount: context.message.attachments?.length ?? 0,\n },\n });\n throw err;\n }\n\n state.running = true;\n state.stopRequested = false;\n state.startedAt = Date.now();\n state.lastActivityAt = Date.now();\n\n log.logInfo(`[${conversationId}] Starting run: ${event.text.substring(0, 50)}`);\n\n const runPromise = (async () => {\n try {\n const result = await this.runWithInstrumentation(\n context,\n { conversationId, sessionKey, startedAt: state.startedAt },\n async () => {\n await context.responder.setTyping(true);\n await context.responder.setWorking(true);\n try {\n return await state.runner.run(context.message, context.responder, context.platform);\n } finally {\n await context.responder.setWorking(false);\n }\n },\n );\n\n if (result?.stopReason === \"aborted\" && state.stopRequested) {\n if (state.stopMessageTs) {\n await bot.updateMessage(conversationId, state.stopMessageTs, formatStopped(bot));\n state.stopMessageTs = undefined;\n } else {\n await bot.postMessage(conversationId, formatStopped(bot));\n }\n }\n } finally {\n state.running = false;\n state.lastAccessedAt = Date.now();\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size - 1);\n }\n })();\n\n this.inFlightRuns.add(runPromise);\n state.runSettlement = runPromise;\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size);\n try {\n await runPromise;\n } finally {\n this.inFlightRuns.delete(runPromise);\n if (state.runSettlement === runPromise) state.runSettlement = undefined;\n this.sessions.onSettlement(address);\n this.sessions.evictIdle();\n }\n } finally {\n releaseConversationWork();\n }\n }\n\n private async runWithInstrumentation(\n context: ConversationContext,\n meta: {\n conversationId: string;\n sessionKey: string;\n startedAt: number;\n },\n body: () => Promise<{ stopReason: string; errorMessage?: string }>,\n ): Promise<{ stopReason: string; errorMessage?: string } | undefined> {\n const { conversationId, sessionKey, startedAt } = meta;\n const { message, platform } = context;\n\n const attribution = createRunAttributionAttributes({\n conversationId,\n sessionKey,\n messageId: message.id,\n platform: platform.name,\n userId: message.userId,\n userName: message.userName,\n threadTs: message.threadTs,\n });\n\n Sentry.metrics.count(\"agent.run.started\", 1, {\n attributes: attribution,\n });\n\n return Sentry.startSpan(\n { name: \"agent.run\", op: \"agent\", attributes: attribution },\n async (span) =>\n Sentry.withScope(async (scope) => {\n registerTraceAttribution(span, attribution);\n applyRunScope(scope, {\n conversationId,\n sessionKey,\n messageId: message.id,\n platform: platform.name,\n userId: message.userId,\n userName: message.userName,\n threadTs: message.threadTs,\n });\n addLifecycleBreadcrumb(\"agent.run.started\", {\n channel_id: conversationId,\n platform: platform.name,\n has_attachments: (message.attachments?.length ?? 0) > 0,\n });\n\n try {\n const result = await body();\n const durationMs = Date.now() - startedAt;\n const completionAttrs = {\n ...attribution,\n stop_reason: result.stopReason,\n };\n Sentry.metrics.distribution(\"agent.run.duration\", durationMs, {\n unit: \"millisecond\",\n attributes: completionAttrs,\n });\n Sentry.metrics.count(\"agent.run.completed\", 1, { attributes: completionAttrs });\n addLifecycleBreadcrumb(\"agent.run.completed\", {\n channel_id: conversationId,\n platform: platform.name,\n stop_reason: result.stopReason,\n duration_ms: durationMs,\n });\n return result;\n } catch (err) {\n scope.setContext(\"agent_run_error\", {\n conversationId,\n sessionKey,\n platform: platform.name,\n messageId: message.id,\n threadTs: message.threadTs,\n });\n reportUserFacingError(err, {\n domain: \"mikan\",\n surface: \"agent_run\",\n operation: \"run\",\n severity: \"error\",\n platform: platform.name,\n context: {\n conversationId,\n sessionKey,\n messageId: message.id,\n threadTs: message.threadTs,\n attachmentCount: message.attachments?.length ?? 0,\n },\n });\n Sentry.metrics.count(\"agent.run.errors\", 1, {\n attributes: attribution,\n });\n log.logWarning(\n `[${conversationId}] Run error`,\n err instanceof Error ? err.message : String(err),\n );\n return undefined;\n }\n }),\n );\n }\n\n switchConversationModel(address: OfficeAddress, _provider: string, _model: string): boolean {\n this.bumpConversationRunnerGeneration(address);\n return this.clearOffice(address, \"Model switched\");\n }\n\n refreshConversationEnvironment(address: OfficeAddress): boolean {\n this.bumpConversationRunnerGeneration(address);\n return this.clearOffice(address, \"Environment refreshed\");\n }\n\n refreshAllConversations(): { busy: OfficeAddress[] } {\n this.globalRunnerGeneration++;\n const busy: OfficeAddress[] = [];\n for (const address of this.sessions.offices()) {\n if (!this.clearOffice(address, \"Global settings changed\")) {\n this.sessions.deferConversationClear(address);\n busy.push(address);\n }\n }\n return { busy };\n }\n\n private clearOffice(address: OfficeAddress, reason: string): boolean {\n const cleared = this.sessions.clearConversation(address);\n if (cleared) {\n log.logInfo(`[${address.conversationId}] ${reason}; cleared cached session runners`);\n }\n return cleared;\n }\n\n private bumpConversationRunnerGeneration(address: OfficeAddress): void {\n const key = officeKey(address);\n this.conversationRunnerGenerations.set(\n key,\n (this.conversationRunnerGenerations.get(key) ?? 0) + 1,\n );\n }\n\n private runnerGeneration(address: OfficeAddress): string {\n return `${this.globalRunnerGeneration}:${this.conversationRunnerGenerations.get(officeKey(address)) ?? 0}`;\n }\n\n private async createCurrentRunner(\n options: SessionStateOptions,\n conversationDir: string,\n sessionScope: Awaited<ReturnType<ChatHistorySync[\"resolveSessionScope\"]>>,\n ): Promise<PiAgentWrapper> {\n while (true) {\n const generation = this.runnerGeneration(options.address);\n const runner = await createRunner({\n sandboxConfig: this.options.sandbox,\n sessionKey: options.sessionKey,\n address: options.address,\n conversationId: options.conversationId,\n conversationDir,\n workspaceDir: this.options.workingDir,\n sessionScope,\n vaultManager: this.options.vaultManager,\n provisioner: this.options.provisioner,\n resourceController: this.options.resourceController,\n sessionView: this.options.sessionViewTokenStore\n ? {\n tokenStore: this.options.sessionViewTokenStore,\n portalBaseUrl: this.options.portalBaseUrl,\n }\n : undefined,\n platformNotifier: this.options.platformNotifier,\n platformReactor: this.options.platformReactor,\n platformUploader: this.options.platformUploader,\n platformBlockKit: this.options.platformBlockKit,\n platformToolPackFactories: this.options.platformToolPackFactories,\n models: this.resolvedModels,\n });\n if (generation === this.runnerGeneration(options.address)) return runner;\n await runner.dispose();\n }\n }\n\n private async getOrCreateState(\n options: SessionStateOptions & { currentMessageId?: string },\n ): Promise<ConversationState> {\n const { address, sessionKey, currentMessageId } = options;\n const existing = this.sessions.get(address, sessionKey);\n if (existing?.running) return existing;\n\n const conversationDir = conversationOfficeDir(this.options.workingDir, address);\n const runtimeCwd = runtimeCwdForSandbox(this.options.sandbox, this.options.workingDir, address);\n const sessionScope = await this.chatSessionManager.resolveSessionScope({\n conversationDir,\n sessionKey,\n cwd: runtimeCwd,\n currentMessageId,\n rotateTopLevelSession: false,\n });\n\n if (existing && existing.sessionFile === sessionScope.contextFile) {\n existing.lastAccessedAt = Date.now();\n return existing;\n }\n\n // A stale state (rotated session file) is being replaced: release the old\n // runner's extension resources before the new one takes the slot.\n if (existing) this.sessions.discard(address, sessionKey);\n\n const state: ConversationState = {\n address,\n sessionKey,\n running: false,\n runner: await this.createCurrentRunner(options, conversationDir, sessionScope),\n stopRequested: false,\n lastAccessedAt: Date.now(),\n sessionFile: sessionScope.contextFile,\n startedAt: 0,\n };\n this.sessions.set(state);\n return state;\n }\n\n async shutdown(timeoutMs = 30_000): Promise<void> {\n if (this.isShuttingDown) return;\n this.isShuttingDown = true;\n log.logInfo(\"Shutting down gracefully...\");\n\n const timeout = Date.now() + timeoutMs;\n while (this.inFlightRuns.size > 0 && Date.now() < timeout) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n if (this.inFlightRuns.size > 0) {\n log.logWarning(`Forcing exit with ${this.inFlightRuns.size} runs still in progress`);\n reportUserFacingError(new Error(\"Shutdown forced with in-flight agent runs\"), {\n domain: \"mikan\",\n surface: \"shutdown\",\n operation: \"force_exit_with_inflight_runs\",\n severity: \"warning\",\n context: { inFlightRuns: this.inFlightRuns.size, timeoutMs },\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"conversation-runtime.js","sourceRoot":"","sources":["../../src/runtime/conversation-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n ConversationKind,\n OfficeAddress,\n PlatformName,\n RunningSession,\n} from \"../adapter.js\";\nimport { officeKey, type Workspace } from \"../office/index.js\";\nimport { createRunner } from \"../agent.js\";\nimport type { PiAgentWrapper } from \"../agent.js\";\nimport { MikanModels } from \"../harness/index.js\";\nimport type { ExtensionBlockAction } from \"../harness/index.js\";\nimport { defaultCommandHandlers, dispatchCommand } from \"../commands/registry.js\";\nimport type { CommandHandler, CommandServices } from \"../commands/types.js\";\nimport { isPrivateConversation } from \"../commands/utils.js\";\nimport * as log from \"../log.js\";\nimport {\n addLifecycleBreadcrumb,\n applyRunScope,\n createRunAttributionAttributes,\n registerTraceAttribution,\n reportUserFacingError,\n} from \"../observability/sentry.js\";\nimport {\n ChatHistorySync,\n hasMaterializedChatSession,\n waitForThreadSessionBootstrap,\n} from \"../sessions/chat-history-sync.js\";\nimport { shouldRotateTopLevelSession } from \"../sessions/rotation.js\";\nimport { resolveChannelSessionFile } from \"../sessions/store.js\";\nimport {\n assertSessionKeyBelongsToConversation,\n deriveSessionKey,\n} from \"../sessions/session-key.js\";\nimport { formatNothingRunning, formatStopped, formatStopping } from \"../platform-messages.js\";\nimport * as Sentry from \"@sentry/node\";\nimport { getUnresolvedSandboxPathContext } from \"../sandbox/index.js\";\nimport { disabledVaultManager } from \"../vault/disabled.js\";\nimport type { ConversationRuntimeState } from \"./types.js\";\nimport { SessionLifecycle } from \"./session-lifecycle.js\";\n\ntype ConversationState = ConversationRuntimeState;\n\nexport type {\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n} from \"./types.js\";\nimport type {\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n SessionStateOptions,\n} from \"./types.js\";\n\n/**\n * Placeholder token store for embedders that run without the web portal.\n * Command handlers guard on `portalBaseUrl` before minting tokens, so this\n * only fires when a portal URL is configured without its backing store.\n */\nfunction portalNotConfiguredTokenStore(portal: string): { create: () => never } {\n return {\n create: () => {\n throw new Error(`${portal} portal not configured`);\n },\n };\n}\n\nfunction runtimeCwdForSandbox(\n sandbox: ConversationRuntimeOptions[\"sandbox\"],\n workspace: Workspace,\n address: OfficeAddress,\n): string {\n const runtimeWorkspaceRoot = getUnresolvedSandboxPathContext(\n sandbox,\n workspace.root,\n ).runtimeWorkspaceRoot;\n // The office key names the same segment on the host and in the runtime.\n return `${runtimeWorkspaceRoot.replace(/\\/+$/, \"\")}/${workspace.office(address).key}`;\n}\n\nexport function createConversationRuntime(\n options: ConversationRuntimeOptions,\n): ConversationRuntime {\n return new ConversationRuntimeImpl(options);\n}\n\nclass ConversationRuntimeImpl implements ConversationRuntime {\n private readonly sessions = new SessionLifecycle();\n private readonly inFlightRuns = new Set<Promise<void>>();\n private readonly sessionDreamSettlements = new Set<Promise<void>>();\n private readonly chatSessionManager = new ChatHistorySync();\n private readonly commandServices: CommandServices;\n private readonly commandHandlers: readonly CommandHandler[];\n private readonly resolvedModels: MikanModels;\n private globalRunnerGeneration = 0;\n private readonly conversationRunnerGenerations = new Map<string, number>();\n private isShuttingDown = false;\n\n constructor(private readonly options: ConversationRuntimeOptions) {\n this.resolvedModels = options.models ?? MikanModels.create();\n this.commandServices = {\n ...options,\n resourceController: options.resourceController ?? options.provisioner,\n vaultManager: options.vaultManager ?? disabledVaultManager,\n linkTokenStore: options.linkTokenStore ?? portalNotConfiguredTokenStore(\"Login\"),\n sessionViewTokenStore:\n options.sessionViewTokenStore ?? portalNotConfiguredTokenStore(\"Session viewer\"),\n adminTokenStore: options.adminTokenStore ?? portalNotConfiguredTokenStore(\"Admin\"),\n runtime: this,\n };\n this.commandHandlers = options.commandHandlers ?? defaultCommandHandlers(this.resolvedModels);\n }\n\n isRunning(address: OfficeAddress, sessionKey: string): boolean {\n return this.sessions.isRunning(address, sessionKey);\n }\n\n getRunningSessions(): RunningSession[] {\n const sessions: RunningSession[] = [];\n for (const state of this.sessions.runningStates()) {\n if (state.startedAt) {\n const currentStep = state.runner.getCurrentStep();\n sessions.push({\n address: state.address,\n sessionKey: state.sessionKey,\n startedAt: state.startedAt,\n lastActivityAt: state.lastActivityAt,\n currentTool: currentStep?.label || currentStep?.toolName,\n });\n }\n }\n return sessions;\n }\n\n async handleStop(address: OfficeAddress, sessionKey: string, bot: MessagingBot): Promise<void> {\n assertSessionKeyBelongsToConversation(sessionKey, address.conversationId);\n const state = this.sessions.get(address, sessionKey);\n if (state?.running) {\n state.stopRequested = true;\n state.runner.abort();\n const ts = await bot.postMessage(address.conversationId, formatStopping(bot));\n state.stopMessageTs = ts;\n } else {\n await bot.postMessage(address.conversationId, formatNothingRunning(bot));\n }\n }\n\n forceStop(address: OfficeAddress, sessionKey: string): void {\n const state = this.sessions.get(address, sessionKey);\n if (state?.running) {\n log.logInfo(`[Force Stop] Force stopping session: ${sessionKey}`);\n state.stopRequested = true;\n state.runner.abort();\n }\n }\n\n async handleNewCommand(\n sessionKey: string,\n conversationId: string,\n bot: MessagingBot,\n message: ConversationContext[\"message\"],\n responder: ConversationContext[\"responder\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<void> {\n // The message's address is the authority; the raw id is still passed for\n // filesystem layout, so a disagreement must fail loudly, not pick one.\n const address = message.address;\n if (conversationId !== address.conversationId) {\n throw new Error(\n `Conversation id ${JSON.stringify(conversationId)} does not match office ` +\n JSON.stringify(address.conversationId),\n );\n }\n assertSessionKeyBelongsToConversation(sessionKey, address.conversationId);\n const activeState = this.sessions.get(address, sessionKey);\n if (\n activeState?.running ||\n (activeState?.runSettlement && this.sessionDreamSettlements.has(activeState.runSettlement))\n ) {\n const activeSettlement = activeState.runSettlement;\n if (activeSettlement && this.sessionDreamSettlements.has(activeSettlement)) {\n await activeSettlement;\n return;\n }\n activeState.stopRequested = true;\n activeState.runner.abort();\n await activeSettlement;\n }\n\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n conversationKind: message.conversationKind,\n });\n if (\n state.running ||\n (state.runSettlement && this.sessionDreamSettlements.has(state.runSettlement))\n ) {\n const activeSettlement = state.runSettlement;\n if (activeSettlement && this.sessionDreamSettlements.has(activeSettlement)) {\n await activeSettlement;\n return;\n }\n state.stopRequested = true;\n state.runner.abort();\n await activeSettlement;\n return this.handleNewCommand(sessionKey, conversationId, bot, message, responder, platform);\n }\n const dreamSettlement = this.startSessionDream(state, async () => {\n let working = false;\n try {\n await responder.setWorking(true);\n working = true;\n const result = await this.dreamSessionMemory(state, message, platform);\n if (!result.success) {\n const detail = result.errorMessage ? ` ${result.errorMessage}` : \"\";\n await responder.respondDiagnostic(\n `Could not preserve memory, so the current conversation was not reset.${detail}`,\n { style: \"error\" },\n );\n return;\n }\n\n await responder.setWorking(false);\n working = false;\n await this.resetSession(state, bot);\n } finally {\n if (working) await responder.setWorking(false);\n }\n });\n try {\n await dreamSettlement;\n } finally {\n this.finishSessionDream(state, dreamSettlement);\n }\n }\n\n private startSessionDream(\n state: ConversationState,\n dream: () => Promise<void>,\n markRunning = true,\n ): Promise<void> {\n if (markRunning) {\n state.running = true;\n state.stopRequested = false;\n state.startedAt = Date.now();\n state.lastActivityAt = Date.now();\n }\n\n const settlement = Promise.resolve().then(dream);\n state.runSettlement = settlement;\n this.sessionDreamSettlements.add(settlement);\n this.inFlightRuns.add(settlement);\n return settlement;\n }\n\n private finishSessionDream(state: ConversationState, settlement: Promise<void>): void {\n this.sessionDreamSettlements.delete(settlement);\n this.inFlightRuns.delete(settlement);\n if (state.runSettlement !== settlement) return;\n\n state.runSettlement = undefined;\n state.running = false;\n state.startedAt = 0;\n state.lastAccessedAt = Date.now();\n this.sessions.onSettlement(state.address);\n this.sessions.evictIdle();\n }\n\n private async dreamSessionMemory(\n state: ConversationState,\n message: ConversationContext[\"message\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<{ success: boolean; errorMessage?: string }> {\n try {\n const result = await state.runner.dreamSessionMemory(message, platform);\n // Only a clean stop means the dream finished its work. Everything else —\n // budget abort, length cutoff, error, blocked — leaves memory unwritten,\n // and treating it as success resets the session and loses it silently.\n // Listed as a whitelist so a new stop reason fails safe.\n if (result.stopReason !== \"stop\") {\n return {\n success: false,\n errorMessage: result.errorMessage ?? `Session Dream stopped early (${result.stopReason})`,\n };\n }\n return { success: true };\n } catch (err) {\n return { success: false, errorMessage: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async rotateSharedSessionAfterDream(\n address: OfficeAddress,\n sessionKey: string,\n message: ConversationContext[\"message\"],\n platform: ConversationContext[\"platform\"],\n ): Promise<void> {\n const conversationId = address.conversationId;\n if (message.conversationKind !== \"shared\" || sessionKey !== conversationId) return;\n\n const conversationDir = this.options.workspace.office(address).dir;\n const currentSession = resolveChannelSessionFile(conversationDir);\n if (!currentSession || !shouldRotateTopLevelSession(currentSession, new Date())) return;\n\n await this.sessions.runConversationMaintenance(address, async () => {\n const session = resolveChannelSessionFile(conversationDir);\n if (!session || !shouldRotateTopLevelSession(session, new Date())) return;\n\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n conversationKind: message.conversationKind,\n currentMessageId: message.id,\n });\n const dreamSettlement = this.startSessionDream(\n state,\n async () => {\n const result = await this.dreamSessionMemory(state, message, platform);\n if (!result.success) {\n const detail = result.errorMessage ? `: ${result.errorMessage}` : \"\";\n log.logWarning(`[${conversationId}] Automatic Session Dream failed${detail}`);\n return;\n }\n\n const runtimeCwd = runtimeCwdForSandbox(\n this.options.sandbox,\n this.options.workspace,\n address,\n );\n this.chatSessionManager.resetSession({ conversationDir, sessionKey, cwd: runtimeCwd });\n this.sessions.discard(address, sessionKey);\n log.logInfo(\n `[${conversationId}] Session Dream completed; rotated session: ${sessionKey}`,\n );\n },\n false,\n );\n try {\n await dreamSettlement;\n } finally {\n this.finishSessionDream(state, dreamSettlement);\n }\n });\n }\n\n private async resetSession(state: ConversationState, bot: MessagingBot): Promise<void> {\n const { address, sessionKey } = state;\n const conversationId = address.conversationId;\n const conversationDir = this.options.workspace.office(address).dir;\n const runtimeCwd = runtimeCwdForSandbox(this.options.sandbox, this.options.workspace, address);\n this.chatSessionManager.resetSession({ conversationDir, sessionKey, cwd: runtimeCwd });\n\n this.sessions.discard(address, sessionKey);\n\n log.logInfo(`[${conversationId}] Session reset: ${sessionKey}`);\n await bot.postMessage(conversationId, \"Conversation reset. Send a new message to start fresh.\");\n }\n\n async handleEvent(\n event: ConversationEvent,\n bot: MessagingBot,\n context: ConversationContext,\n ): Promise<void> {\n const sessionKey = deriveSessionKey(event);\n await this.sessions.enqueue(event.address, sessionKey, () =>\n this.runSession({ event, bot, context }),\n );\n }\n\n /**\n * Dispatch an extension-owned interactive block action: materialize the\n * conversation's harness instance (activating its extensions) and run the\n * matching onAction handler — deterministic, no agent run. Serialized on\n * the session queue so rapid interactions (votes) never interleave.\n */\n async handleExtensionAction(params: {\n address: OfficeAddress;\n sessionKey: string;\n conversationKind: ConversationKind;\n slug: string;\n action: ExtensionBlockAction;\n }): Promise<boolean> {\n if (this.isShuttingDown) return false;\n const { address, sessionKey, conversationKind, slug, action } = params;\n const conversationId = address.conversationId;\n let consumed = false;\n await this.sessions.enqueue(address, sessionKey, async () => {\n try {\n const state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n currentMessageId: action.messageTs ?? sessionKey,\n conversationKind,\n });\n consumed = await state.runner.tryExtensionAction(slug, action);\n if (consumed) state.lastAccessedAt = Date.now();\n } catch (err) {\n log.logWarning(\n `[${conversationId}] Extension action dispatch failed (${slug}:${action.actionId})`,\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n return consumed;\n }\n\n async runSession({ event, bot, context }: RunSessionOptions): Promise<void> {\n const conversationId = event.conversationId;\n if (this.isShuttingDown) {\n log.logInfo(\n `[${conversationId}] Rejected event during shutdown: ${event.text.substring(0, 50)}`,\n );\n return;\n }\n\n const sessionKey = deriveSessionKey(event);\n const privateConversation = isPrivateConversation(event);\n const handledCommand = await dispatchCommand(this.commandHandlers, {\n bot,\n responder: context.responder,\n platform: context.platform.name as PlatformName,\n address: event.address,\n platformUserId: event.user,\n platformUserName: context.message.userName,\n conversationId,\n vaultConversationId: event.vaultConversationId,\n sessionKey,\n commandText: event.text,\n privateConversation,\n services: this.commandServices,\n });\n if (handledCommand) return;\n\n const address = event.address;\n const activeSettlement = this.sessions.get(address, sessionKey)?.runSettlement;\n if (activeSettlement) await activeSettlement;\n\n if (sessionKey === conversationId) {\n await this.rotateSharedSessionAfterDream(\n address,\n sessionKey,\n context.message,\n context.platform,\n );\n }\n\n const releaseConversationWork = await this.sessions.acquireConversationWork(address);\n try {\n const conversationDir = this.options.workspace.office(address).dir;\n const waitedForParent = await waitForThreadSessionBootstrap({\n parentSessionKey: conversationId,\n sessionKey,\n hasThreadSession: () => hasMaterializedChatSession({ conversationDir, sessionKey }),\n isParentRunning: () => this.sessions.get(address, conversationId)?.running === true,\n });\n if (waitedForParent) {\n log.logInfo(\n `[${conversationId}] Delayed thread bootstrap until parent session sealed: ${sessionKey}`,\n );\n }\n\n let state: ConversationState;\n try {\n state = await this.getOrCreateState({\n address,\n conversationId,\n sessionKey,\n currentMessageId: event.ts,\n conversationKind: event.conversationKind,\n });\n state.runner.syncChatHistory(event.ts);\n\n // Extension-contributed commands: deterministic dispatch, no agent run.\n // Built-in commands already had their chance above, so extensions can\n // never shadow them; unmatched slash text falls through to the agent.\n if (event.text.trim().startsWith(\"/\")) {\n const handled = await state.runner.tryExtensionCommand(\n context.message,\n context.responder,\n );\n if (handled) {\n state.lastAccessedAt = Date.now();\n return;\n }\n }\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"mikan\",\n surface: \"session_setup\",\n operation: \"get_or_create_state\",\n severity: \"error\",\n platform: context.platform.name,\n context: {\n conversationId,\n sessionKey,\n messageId: context.message.id,\n threadTs: context.message.threadTs,\n attachmentCount: context.message.attachments?.length ?? 0,\n },\n });\n throw err;\n }\n\n state.running = true;\n state.stopRequested = false;\n state.startedAt = Date.now();\n state.lastActivityAt = Date.now();\n\n log.logInfo(`[${conversationId}] Starting run: ${event.text.substring(0, 50)}`);\n\n const runPromise = (async () => {\n try {\n const result = await this.runWithInstrumentation(\n context,\n { conversationId, sessionKey, startedAt: state.startedAt },\n async () => {\n await context.responder.setTyping(true);\n await context.responder.setWorking(true);\n try {\n return await state.runner.run(context.message, context.responder, context.platform);\n } finally {\n await context.responder.setWorking(false);\n }\n },\n );\n\n if (result?.stopReason === \"aborted\" && state.stopRequested) {\n if (state.stopMessageTs) {\n await bot.updateMessage(conversationId, state.stopMessageTs, formatStopped(bot));\n state.stopMessageTs = undefined;\n } else {\n await bot.postMessage(conversationId, formatStopped(bot));\n }\n }\n } finally {\n state.running = false;\n state.lastAccessedAt = Date.now();\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size - 1);\n }\n })();\n\n this.inFlightRuns.add(runPromise);\n state.runSettlement = runPromise;\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size);\n try {\n await runPromise;\n } finally {\n this.inFlightRuns.delete(runPromise);\n if (state.runSettlement === runPromise) state.runSettlement = undefined;\n this.sessions.onSettlement(address);\n this.sessions.evictIdle();\n }\n } finally {\n releaseConversationWork();\n }\n }\n\n private async runWithInstrumentation(\n context: ConversationContext,\n meta: {\n conversationId: string;\n sessionKey: string;\n startedAt: number;\n },\n body: () => Promise<{ stopReason: string; errorMessage?: string }>,\n ): Promise<{ stopReason: string; errorMessage?: string } | undefined> {\n const { conversationId, sessionKey, startedAt } = meta;\n const { message, platform } = context;\n\n const attribution = createRunAttributionAttributes({\n conversationId,\n sessionKey,\n messageId: message.id,\n platform: platform.name,\n userId: message.userId,\n userName: message.userName,\n threadTs: message.threadTs,\n });\n\n Sentry.metrics.count(\"agent.run.started\", 1, {\n attributes: attribution,\n });\n\n return Sentry.startSpan(\n { name: \"agent.run\", op: \"agent\", attributes: attribution },\n async (span) =>\n Sentry.withScope(async (scope) => {\n registerTraceAttribution(span, attribution);\n applyRunScope(scope, {\n conversationId,\n sessionKey,\n messageId: message.id,\n platform: platform.name,\n userId: message.userId,\n userName: message.userName,\n threadTs: message.threadTs,\n });\n addLifecycleBreadcrumb(\"agent.run.started\", {\n channel_id: conversationId,\n platform: platform.name,\n has_attachments: (message.attachments?.length ?? 0) > 0,\n });\n\n try {\n const result = await body();\n const durationMs = Date.now() - startedAt;\n const completionAttrs = {\n ...attribution,\n stop_reason: result.stopReason,\n };\n Sentry.metrics.distribution(\"agent.run.duration\", durationMs, {\n unit: \"millisecond\",\n attributes: completionAttrs,\n });\n Sentry.metrics.count(\"agent.run.completed\", 1, { attributes: completionAttrs });\n addLifecycleBreadcrumb(\"agent.run.completed\", {\n channel_id: conversationId,\n platform: platform.name,\n stop_reason: result.stopReason,\n duration_ms: durationMs,\n });\n return result;\n } catch (err) {\n scope.setContext(\"agent_run_error\", {\n conversationId,\n sessionKey,\n platform: platform.name,\n messageId: message.id,\n threadTs: message.threadTs,\n });\n reportUserFacingError(err, {\n domain: \"mikan\",\n surface: \"agent_run\",\n operation: \"run\",\n severity: \"error\",\n platform: platform.name,\n context: {\n conversationId,\n sessionKey,\n messageId: message.id,\n threadTs: message.threadTs,\n attachmentCount: message.attachments?.length ?? 0,\n },\n });\n Sentry.metrics.count(\"agent.run.errors\", 1, {\n attributes: attribution,\n });\n log.logWarning(\n `[${conversationId}] Run error`,\n err instanceof Error ? err.message : String(err),\n );\n return undefined;\n }\n }),\n );\n }\n\n switchConversationModel(address: OfficeAddress, _provider: string, _model: string): boolean {\n this.bumpConversationRunnerGeneration(address);\n return this.clearOffice(address, \"Model switched\");\n }\n\n refreshConversationEnvironment(address: OfficeAddress): boolean {\n this.bumpConversationRunnerGeneration(address);\n return this.clearOffice(address, \"Environment refreshed\");\n }\n\n refreshAllConversations(): { busy: OfficeAddress[] } {\n this.globalRunnerGeneration++;\n const busy: OfficeAddress[] = [];\n for (const address of this.sessions.offices()) {\n if (!this.clearOffice(address, \"Global settings changed\")) {\n this.sessions.deferConversationClear(address);\n busy.push(address);\n }\n }\n return { busy };\n }\n\n private clearOffice(address: OfficeAddress, reason: string): boolean {\n const cleared = this.sessions.clearConversation(address);\n if (cleared) {\n log.logInfo(`[${address.conversationId}] ${reason}; cleared cached session runners`);\n }\n return cleared;\n }\n\n private bumpConversationRunnerGeneration(address: OfficeAddress): void {\n const key = officeKey(address);\n this.conversationRunnerGenerations.set(\n key,\n (this.conversationRunnerGenerations.get(key) ?? 0) + 1,\n );\n }\n\n private runnerGeneration(address: OfficeAddress): string {\n return `${this.globalRunnerGeneration}:${this.conversationRunnerGenerations.get(officeKey(address)) ?? 0}`;\n }\n\n private async createCurrentRunner(\n options: SessionStateOptions,\n conversationDir: string,\n sessionScope: Awaited<ReturnType<ChatHistorySync[\"resolveSessionScope\"]>>,\n ): Promise<PiAgentWrapper> {\n while (true) {\n const generation = this.runnerGeneration(options.address);\n const runner = await createRunner({\n sandboxConfig: this.options.sandbox,\n sessionKey: options.sessionKey,\n office: this.options.workspace.office(options.address),\n sessionScope,\n vaultManager: this.options.vaultManager,\n provisioner: this.options.provisioner,\n resourceController: this.options.resourceController,\n sessionView: this.options.sessionViewTokenStore\n ? {\n tokenStore: this.options.sessionViewTokenStore,\n portalBaseUrl: this.options.portalBaseUrl,\n }\n : undefined,\n platformNotifier: this.options.platformNotifier,\n platformReactor: this.options.platformReactor,\n platformUploader: this.options.platformUploader,\n platformBlockKit: this.options.platformBlockKit,\n platformToolPackFactories: this.options.platformToolPackFactories,\n models: this.resolvedModels,\n });\n if (generation === this.runnerGeneration(options.address)) return runner;\n await runner.dispose();\n }\n }\n\n private async getOrCreateState(\n options: SessionStateOptions & { currentMessageId?: string },\n ): Promise<ConversationState> {\n const { address, sessionKey, currentMessageId } = options;\n const existing = this.sessions.get(address, sessionKey);\n if (existing?.running) return existing;\n\n const conversationDir = this.options.workspace.office(address).dir;\n const runtimeCwd = runtimeCwdForSandbox(this.options.sandbox, this.options.workspace, address);\n const sessionScope = await this.chatSessionManager.resolveSessionScope({\n conversationDir,\n sessionKey,\n cwd: runtimeCwd,\n currentMessageId,\n rotateTopLevelSession: false,\n });\n\n if (existing && existing.sessionFile === sessionScope.contextFile) {\n existing.lastAccessedAt = Date.now();\n return existing;\n }\n\n // A stale state (rotated session file) is being replaced: release the old\n // runner's extension resources before the new one takes the slot.\n if (existing) this.sessions.discard(address, sessionKey);\n\n const state: ConversationState = {\n address,\n sessionKey,\n running: false,\n runner: await this.createCurrentRunner(options, conversationDir, sessionScope),\n stopRequested: false,\n lastAccessedAt: Date.now(),\n sessionFile: sessionScope.contextFile,\n startedAt: 0,\n };\n this.sessions.set(state);\n return state;\n }\n\n async shutdown(timeoutMs = 30_000): Promise<void> {\n if (this.isShuttingDown) return;\n this.isShuttingDown = true;\n log.logInfo(\"Shutting down gracefully...\");\n\n const timeout = Date.now() + timeoutMs;\n while (this.inFlightRuns.size > 0 && Date.now() < timeout) {\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n if (this.inFlightRuns.size > 0) {\n log.logWarning(`Forcing exit with ${this.inFlightRuns.size} runs still in progress`);\n reportUserFacingError(new Error(\"Shutdown forced with in-flight agent runs\"), {\n domain: \"mikan\",\n surface: \"shutdown\",\n operation: \"force_exit_with_inflight_runs\",\n severity: \"warning\",\n context: { inFlightRuns: this.inFlightRuns.size, timeoutMs },\n });\n }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import * as log from "../log.js";
2
- import { officeKey } from "../office-address.js";
2
+ import { officeKey } from "../office/index.js";
3
3
  const DEFAULT_MAX_SESSIONS = 500;
4
4
  const DEFAULT_IDLE_TIMEOUT_MS = 3_600_000;
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"session-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/session-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OfficeAddress } from \"../adapter.js\";\nimport * as log from \"../log.js\";\nimport { officeKey } from \"../office-address.js\";\nimport type { ConversationRuntimeState, SessionLifecycleOptions } from \"./types.js\";\n\nconst DEFAULT_MAX_SESSIONS = 500;\nconst DEFAULT_IDLE_TIMEOUT_MS = 3_600_000;\n\ninterface ConversationBarrier {\n activeWork: number;\n pendingMaintenance: number;\n maintenanceTail: Promise<void>;\n activeWaiters: Array<() => void>;\n workWaiters: Array<() => void>;\n}\n\n/**\n * Runtime state is addressed by office, not by session key alone.\n *\n * A session key is a platform value: a Discord channel and a Telegram chat can\n * legitimately produce the same string, and every platform shares this one\n * lifecycle. The internal map key therefore prefixes the office key, which\n * carries the platform plus a digest of the raw conversation id. Callers only\n * ever pass `(address, sessionKey)`; the composite never leaves this module,\n * so nothing downstream can parse it or invent one.\n */\nfunction runtimeSessionId(address: OfficeAddress, sessionKey: string): string {\n return `${officeKey(address)}|${sessionKey}`;\n}\n\nexport class SessionLifecycle {\n private readonly states = new Map<string, ConversationRuntimeState>();\n private readonly queues = new Map<string, Promise<void>>();\n private readonly conversationBarriers = new Map<string, ConversationBarrier>();\n private readonly pendingConversationClears = new Set<string>();\n private readonly maxSessions: number;\n private readonly idleTimeoutMs: number;\n private readonly now: () => number;\n\n constructor(options: SessionLifecycleOptions = {}) {\n this.maxSessions = options.maxSessions ?? DEFAULT_MAX_SESSIONS;\n this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.now = options.now ?? Date.now;\n }\n\n get(address: OfficeAddress, sessionKey: string): ConversationRuntimeState | undefined {\n return this.states.get(runtimeSessionId(address, sessionKey));\n }\n\n /** The state carries its own identity, so it cannot be filed under another. */\n set(state: ConversationRuntimeState): void {\n this.states.set(runtimeSessionId(state.address, state.sessionKey), state);\n }\n\n async enqueue(\n address: OfficeAddress,\n sessionKey: string,\n run: () => Promise<void>,\n ): Promise<void> {\n const id = runtimeSessionId(address, sessionKey);\n const previous = this.queues.get(id) ?? Promise.resolve();\n const next = previous.catch(() => {}).then(run);\n this.queues.set(id, next);\n try {\n await next;\n } finally {\n if (this.queues.get(id) === next) this.queues.delete(id);\n }\n }\n\n async acquireConversationWork(address: OfficeAddress): Promise<() => void> {\n const barrier = this.getConversationBarrier(address);\n while (barrier.pendingMaintenance > 0) {\n await new Promise<void>((resolve) => barrier.workWaiters.push(resolve));\n }\n\n barrier.activeWork++;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n barrier.activeWork--;\n if (barrier.activeWork === 0) {\n const waiters = barrier.activeWaiters.splice(0);\n for (const resolve of waiters) resolve();\n }\n };\n }\n\n async runConversationMaintenance<T>(\n address: OfficeAddress,\n maintenance: () => Promise<T>,\n ): Promise<T> {\n const barrier = this.getConversationBarrier(address);\n barrier.pendingMaintenance++;\n\n const previousMaintenance = barrier.maintenanceTail;\n let finishMaintenance!: () => void;\n const maintenanceTurn = new Promise<void>((resolve) => (finishMaintenance = resolve));\n barrier.maintenanceTail = previousMaintenance.then(() => maintenanceTurn);\n\n await previousMaintenance;\n if (barrier.activeWork > 0) {\n await new Promise<void>((resolve) => barrier.activeWaiters.push(resolve));\n }\n\n try {\n return await maintenance();\n } finally {\n finishMaintenance();\n barrier.pendingMaintenance--;\n if (barrier.pendingMaintenance === 0) {\n const waiters = barrier.workWaiters.splice(0);\n for (const resolve of waiters) resolve();\n }\n }\n }\n\n private getConversationBarrier(address: OfficeAddress): ConversationBarrier {\n const key = officeKey(address);\n const existing = this.conversationBarriers.get(key);\n if (existing) return existing;\n\n const barrier: ConversationBarrier = {\n activeWork: 0,\n pendingMaintenance: 0,\n maintenanceTail: Promise.resolve(),\n activeWaiters: [],\n workWaiters: [],\n };\n this.conversationBarriers.set(key, barrier);\n return barrier;\n }\n\n isRunning(address: OfficeAddress, sessionKey: string): boolean {\n return this.get(address, sessionKey)?.running === true;\n }\n\n runningStates(): ConversationRuntimeState[] {\n return Array.from(this.states.values()).filter((state) => state.running);\n }\n\n /** Every office holding runtime state, deduplicated by office key. */\n offices(): OfficeAddress[] {\n const offices = new Map<string, OfficeAddress>();\n for (const state of this.states.values()) offices.set(officeKey(state.address), state.address);\n return Array.from(offices.values());\n }\n\n /**\n * Resolve the offices behind a raw conversation id. Settings, the filesystem,\n * and Admin scope still address offices by raw id (ADR 0005), so this is the\n * bridge until they carry an `OfficeAddress`. Two platforms sharing a raw id\n * yield both offices, matching the raw-id scope those callers expect today.\n */\n officesForConversationId(conversationId: string): OfficeAddress[] {\n return this.offices().filter((address) => address.conversationId === conversationId);\n }\n\n clearConversation(address: OfficeAddress): boolean {\n if (this.hasActiveRun(address)) return false;\n this.pendingConversationClears.delete(officeKey(address));\n this.discardConversation(address);\n return true;\n }\n\n deferConversationClear(address: OfficeAddress): void {\n this.pendingConversationClears.add(officeKey(address));\n }\n\n onSettlement(address: OfficeAddress): void {\n const key = officeKey(address);\n if (!this.pendingConversationClears.has(key)) return;\n if (this.hasActiveRun(address)) return;\n\n this.pendingConversationClears.delete(key);\n this.discardConversation(address);\n }\n\n private hasActiveRun(address: OfficeAddress): boolean {\n const key = officeKey(address);\n for (const state of this.states.values()) {\n if (\n officeKey(state.address) === key &&\n (state.running || state.runSettlement !== undefined)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private discardConversation(address: OfficeAddress): void {\n const key = officeKey(address);\n for (const state of Array.from(this.states.values())) {\n if (officeKey(state.address) === key) this.discard(state.address, state.sessionKey);\n }\n }\n\n discard(address: OfficeAddress, sessionKey: string): void {\n const id = runtimeSessionId(address, sessionKey);\n const state = this.states.get(id);\n if (!state) return;\n this.states.delete(id);\n state.runner.dispose().catch((err: unknown) => {\n log.logWarning(\n `Runner dispose failed: ${sessionKey}`,\n err instanceof Error ? err.message : String(err),\n );\n });\n }\n\n evictIdle(): void {\n const now = this.now();\n for (const state of Array.from(this.states.values())) {\n if (\n !state.running &&\n state.runSettlement === undefined &&\n now - state.lastAccessedAt > this.idleTimeoutMs\n ) {\n this.discard(state.address, state.sessionKey);\n }\n }\n if (this.states.size <= this.maxSessions) return;\n\n const idle = Array.from(this.states.values())\n .filter((state) => !state.running && state.runSettlement === undefined)\n .toSorted((left, right) => left.lastAccessedAt - right.lastAccessedAt);\n const toEvict = this.states.size - this.maxSessions;\n for (const state of idle.slice(0, toEvict)) this.discard(state.address, state.sessionKey);\n }\n}\n"]}
1
+ {"version":3,"file":"session-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/session-lifecycle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,uBAAuB,GAAG,SAAS,CAAC;AAU1C;;;;;;;;;GASG;AACH,SAAS,gBAAgB,CAAC,OAAsB,EAAE,UAAkB;IAClE,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,UAAU,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,OAAO,gBAAgB;IAS3B,YAAY,OAAO,GAA4B,EAAE;QARhC,WAAM,GAAG,IAAI,GAAG,EAAoC,CAAC;QACrD,WAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;QAC1C,yBAAoB,GAAG,IAAI,GAAG,EAA+B,CAAC;QAC9D,8BAAyB,GAAG,IAAI,GAAG,EAAU,CAAC;QAM7D,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,oBAAoB,CAAC;QAC/D,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;QACtE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACrC,CAAC;IAED,GAAG,CAAC,OAAsB,EAAE,UAAkB;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,+EAA+E;IAC/E,GAAG,CAAC,KAA+B;QACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAsB,EACtB,UAAkB,EAClB,GAAwB;QAExB,MAAM,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,OAAsB;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC,kBAAkB,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,OAAO,CAAC,UAAU,EAAE,CAAC;QACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,OAAO,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAChD,KAAK,MAAM,OAAO,IAAI,OAAO;oBAAE,OAAO,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,OAAsB,EACtB,WAA6B;QAE7B,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QACrD,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAE7B,MAAM,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;QACpD,IAAI,iBAA8B,CAAC;QACnC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC;QACtF,OAAO,CAAC,eAAe,GAAG,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QAE1E,MAAM,mBAAmB,CAAC;QAC1B,IAAI,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,WAAW,EAAE,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,iBAAiB,EAAE,CAAC;YACpB,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,OAAO,CAAC,kBAAkB,KAAK,CAAC,EAAE,CAAC;gBACrC,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBAC9C,KAAK,MAAM,OAAO,IAAI,OAAO;oBAAE,OAAO,EAAE,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAsB;QACnD,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAE9B,MAAM,OAAO,GAAwB;YACnC,UAAU,EAAE,CAAC;YACb,kBAAkB,EAAE,CAAC;YACrB,eAAe,EAAE,OAAO,CAAC,OAAO,EAAE;YAClC,aAAa,EAAE,EAAE;YACjB,WAAW,EAAE,EAAE;SAChB,CAAC;QACF,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,CAAC,OAAsB,EAAE,UAAkB;QAClD,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,CAAC;IAED,aAAa;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3E,CAAC;IAED,sEAAsE;IACtE,OAAO;QACL,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;QACjD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/F,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,cAAsB;QAC7C,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,KAAK,cAAc,CAAC,CAAC;IACvF,CAAC;IAED,iBAAiB,CAAC,OAAsB;QACtC,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7C,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sBAAsB,CAAC,OAAsB;QAC3C,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,YAAY,CAAC,OAAsB;QACjC,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QACrD,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,OAAO;QAEvC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAEO,YAAY,CAAC,OAAsB;QACzC,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,IACE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG;gBAChC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,EACpD,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,mBAAmB,CAAC,OAAsB;QAChD,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;YACrD,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG;gBAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAAsB,EAAE,UAAkB;QAChD,MAAM,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YAC5C,GAAG,CAAC,UAAU,CACZ,0BAA0B,UAAU,EAAE,EACtC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS;QACP,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;YACrD,IACE,CAAC,KAAK,CAAC,OAAO;gBACd,KAAK,CAAC,aAAa,KAAK,SAAS;gBACjC,GAAG,GAAG,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,EAC/C,CAAC;gBACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAEjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;aAC1C,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC;aACtE,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5F,CAAC;CACF","sourcesContent":["import type { OfficeAddress } from \"../adapter.js\";\nimport * as log from \"../log.js\";\nimport { officeKey } from \"../office/index.js\";\nimport type { ConversationRuntimeState, SessionLifecycleOptions } from \"./types.js\";\n\nconst DEFAULT_MAX_SESSIONS = 500;\nconst DEFAULT_IDLE_TIMEOUT_MS = 3_600_000;\n\ninterface ConversationBarrier {\n activeWork: number;\n pendingMaintenance: number;\n maintenanceTail: Promise<void>;\n activeWaiters: Array<() => void>;\n workWaiters: Array<() => void>;\n}\n\n/**\n * Runtime state is addressed by office, not by session key alone.\n *\n * A session key is a platform value: a Discord channel and a Telegram chat can\n * legitimately produce the same string, and every platform shares this one\n * lifecycle. The internal map key therefore prefixes the office key, which\n * carries the platform plus a digest of the raw conversation id. Callers only\n * ever pass `(address, sessionKey)`; the composite never leaves this module,\n * so nothing downstream can parse it or invent one.\n */\nfunction runtimeSessionId(address: OfficeAddress, sessionKey: string): string {\n return `${officeKey(address)}|${sessionKey}`;\n}\n\nexport class SessionLifecycle {\n private readonly states = new Map<string, ConversationRuntimeState>();\n private readonly queues = new Map<string, Promise<void>>();\n private readonly conversationBarriers = new Map<string, ConversationBarrier>();\n private readonly pendingConversationClears = new Set<string>();\n private readonly maxSessions: number;\n private readonly idleTimeoutMs: number;\n private readonly now: () => number;\n\n constructor(options: SessionLifecycleOptions = {}) {\n this.maxSessions = options.maxSessions ?? DEFAULT_MAX_SESSIONS;\n this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.now = options.now ?? Date.now;\n }\n\n get(address: OfficeAddress, sessionKey: string): ConversationRuntimeState | undefined {\n return this.states.get(runtimeSessionId(address, sessionKey));\n }\n\n /** The state carries its own identity, so it cannot be filed under another. */\n set(state: ConversationRuntimeState): void {\n this.states.set(runtimeSessionId(state.address, state.sessionKey), state);\n }\n\n async enqueue(\n address: OfficeAddress,\n sessionKey: string,\n run: () => Promise<void>,\n ): Promise<void> {\n const id = runtimeSessionId(address, sessionKey);\n const previous = this.queues.get(id) ?? Promise.resolve();\n const next = previous.catch(() => {}).then(run);\n this.queues.set(id, next);\n try {\n await next;\n } finally {\n if (this.queues.get(id) === next) this.queues.delete(id);\n }\n }\n\n async acquireConversationWork(address: OfficeAddress): Promise<() => void> {\n const barrier = this.getConversationBarrier(address);\n while (barrier.pendingMaintenance > 0) {\n await new Promise<void>((resolve) => barrier.workWaiters.push(resolve));\n }\n\n barrier.activeWork++;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n barrier.activeWork--;\n if (barrier.activeWork === 0) {\n const waiters = barrier.activeWaiters.splice(0);\n for (const resolve of waiters) resolve();\n }\n };\n }\n\n async runConversationMaintenance<T>(\n address: OfficeAddress,\n maintenance: () => Promise<T>,\n ): Promise<T> {\n const barrier = this.getConversationBarrier(address);\n barrier.pendingMaintenance++;\n\n const previousMaintenance = barrier.maintenanceTail;\n let finishMaintenance!: () => void;\n const maintenanceTurn = new Promise<void>((resolve) => (finishMaintenance = resolve));\n barrier.maintenanceTail = previousMaintenance.then(() => maintenanceTurn);\n\n await previousMaintenance;\n if (barrier.activeWork > 0) {\n await new Promise<void>((resolve) => barrier.activeWaiters.push(resolve));\n }\n\n try {\n return await maintenance();\n } finally {\n finishMaintenance();\n barrier.pendingMaintenance--;\n if (barrier.pendingMaintenance === 0) {\n const waiters = barrier.workWaiters.splice(0);\n for (const resolve of waiters) resolve();\n }\n }\n }\n\n private getConversationBarrier(address: OfficeAddress): ConversationBarrier {\n const key = officeKey(address);\n const existing = this.conversationBarriers.get(key);\n if (existing) return existing;\n\n const barrier: ConversationBarrier = {\n activeWork: 0,\n pendingMaintenance: 0,\n maintenanceTail: Promise.resolve(),\n activeWaiters: [],\n workWaiters: [],\n };\n this.conversationBarriers.set(key, barrier);\n return barrier;\n }\n\n isRunning(address: OfficeAddress, sessionKey: string): boolean {\n return this.get(address, sessionKey)?.running === true;\n }\n\n runningStates(): ConversationRuntimeState[] {\n return Array.from(this.states.values()).filter((state) => state.running);\n }\n\n /** Every office holding runtime state, deduplicated by office key. */\n offices(): OfficeAddress[] {\n const offices = new Map<string, OfficeAddress>();\n for (const state of this.states.values()) offices.set(officeKey(state.address), state.address);\n return Array.from(offices.values());\n }\n\n /**\n * Resolve the offices behind a raw conversation id. Settings, the filesystem,\n * and Admin scope still address offices by raw id (ADR 0005), so this is the\n * bridge until they carry an `OfficeAddress`. Two platforms sharing a raw id\n * yield both offices, matching the raw-id scope those callers expect today.\n */\n officesForConversationId(conversationId: string): OfficeAddress[] {\n return this.offices().filter((address) => address.conversationId === conversationId);\n }\n\n clearConversation(address: OfficeAddress): boolean {\n if (this.hasActiveRun(address)) return false;\n this.pendingConversationClears.delete(officeKey(address));\n this.discardConversation(address);\n return true;\n }\n\n deferConversationClear(address: OfficeAddress): void {\n this.pendingConversationClears.add(officeKey(address));\n }\n\n onSettlement(address: OfficeAddress): void {\n const key = officeKey(address);\n if (!this.pendingConversationClears.has(key)) return;\n if (this.hasActiveRun(address)) return;\n\n this.pendingConversationClears.delete(key);\n this.discardConversation(address);\n }\n\n private hasActiveRun(address: OfficeAddress): boolean {\n const key = officeKey(address);\n for (const state of this.states.values()) {\n if (\n officeKey(state.address) === key &&\n (state.running || state.runSettlement !== undefined)\n ) {\n return true;\n }\n }\n return false;\n }\n\n private discardConversation(address: OfficeAddress): void {\n const key = officeKey(address);\n for (const state of Array.from(this.states.values())) {\n if (officeKey(state.address) === key) this.discard(state.address, state.sessionKey);\n }\n }\n\n discard(address: OfficeAddress, sessionKey: string): void {\n const id = runtimeSessionId(address, sessionKey);\n const state = this.states.get(id);\n if (!state) return;\n this.states.delete(id);\n state.runner.dispose().catch((err: unknown) => {\n log.logWarning(\n `Runner dispose failed: ${sessionKey}`,\n err instanceof Error ? err.message : String(err),\n );\n });\n }\n\n evictIdle(): void {\n const now = this.now();\n for (const state of Array.from(this.states.values())) {\n if (\n !state.running &&\n state.runSettlement === undefined &&\n now - state.lastAccessedAt > this.idleTimeoutMs\n ) {\n this.discard(state.address, state.sessionKey);\n }\n }\n if (this.states.size <= this.maxSessions) return;\n\n const idle = Array.from(this.states.values())\n .filter((state) => !state.running && state.runSettlement === undefined)\n .toSorted((left, right) => left.lastAccessedAt - right.lastAccessedAt);\n const toEvict = this.states.size - this.maxSessions;\n for (const state of idle.slice(0, toEvict)) this.discard(state.address, state.sessionKey);\n }\n}\n"]}
@@ -36,8 +36,9 @@ export interface SessionStateOptions {
36
36
  /** Canonical office identity; the runtime keys all state by this. */
37
37
  address: OfficeAddress;
38
38
  /**
39
- * The office's raw platform id. Filesystem layout, settings, and Admin scope
40
- * still address offices this way; see ADR 0005.
39
+ * The office's raw platform id — the session-key grammar's conversation
40
+ * value (a bare conversation session key equals it). Never a storage key;
41
+ * layout and settings are addressed through the Office value.
41
42
  */
42
43
  conversationId: string;
43
44
  sessionKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { PiAgentWrapper } from \"../agent.js\";\nimport type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ConversationKind,\n OfficeAddress,\n PlatformBlockKit,\n PlatformNotifier,\n PlatformReactor,\n PlatformUploader,\n} from \"../adapter.js\";\nimport type {\n AdminTokenStoreLike,\n CommandHandler,\n CommandServices,\n LinkTokenStoreLike,\n SessionViewTokenStoreLike,\n} from \"../commands/types.js\";\nimport type { MikanModels } from \"../harness/index.js\";\nimport type { PlatformToolPackFactory } from \"../tools/types.js\";\nimport type { VaultManager } from \"../vault/index.js\";\n\nexport interface SessionLifecycleOptions {\n maxSessions?: number;\n idleTimeoutMs?: number;\n now?: () => number;\n}\n\nexport interface ConversationRuntimeState {\n /** The office that owns this runtime state. */\n address: OfficeAddress;\n /** This office's platform session reference (raw session-key grammar). */\n sessionKey: string;\n running: boolean;\n /** Exact settlement of the current run, including post-run response handling. */\n runSettlement?: Promise<void>;\n runner: PiAgentWrapper;\n stopRequested: boolean;\n stopMessageTs?: string;\n lastAccessedAt: number;\n sessionFile: string;\n /** Epoch ms when the current run started; 0 when idle. */\n startedAt: number;\n lastActivityAt?: number;\n}\n\nexport interface RunSessionOptions {\n event: ConversationEvent;\n bot: MessagingBot;\n context: ConversationContext;\n}\n\n/** Conversation/session identity used to resolve per-session runner state. */\nexport interface SessionStateOptions {\n /** Canonical office identity; the runtime keys all state by this. */\n address: OfficeAddress;\n /**\n * The office's raw platform id. Filesystem layout, settings, and Admin scope\n * still address offices this way; see ADR 0005.\n */\n conversationId: string;\n sessionKey: string;\n conversationKind?: ConversationKind;\n}\n\nexport interface ConversationRuntimeOptions extends Omit<\n CommandServices,\n \"runtime\" | \"vaultManager\" | \"linkTokenStore\" | \"sessionViewTokenStore\" | \"adminTokenStore\"\n> {\n /**\n * Credential vault for sandboxed conversations. Optional for embedders;\n * when omitted the runtime uses an inert, disabled vault.\n */\n vaultManager?: VaultManager;\n /** Login-portal token store; omit when no web portal is hosted. */\n linkTokenStore?: LinkTokenStoreLike;\n /** Session-viewer token store; omit when no web portal is hosted. */\n sessionViewTokenStore?: SessionViewTokenStoreLike;\n /** Admin-portal token store; omit when no web portal is hosted. */\n adminTokenStore?: AdminTokenStoreLike;\n /** Override the default command handlers (e.g., to add /help, /status). */\n commandHandlers?: readonly CommandHandler[];\n /** Model registry override; defaults to the process-wide models.json load. */\n models?: MikanModels;\n /** Proactive platform messaging for extensions (`api.notify`). */\n platformNotifier?: PlatformNotifier;\n /** Proactive emoji reactions for extensions (`api.react`). */\n platformReactor?: PlatformReactor;\n /** Proactive file uploads for extensions (`api.uploadFile`). */\n platformUploader?: PlatformUploader;\n /** Interactive Block Kit posting/updating for extensions (`api.blockkit`). */\n platformBlockKit?: PlatformBlockKit;\n /**\n * Optional platform capability packs (extra tools + per-run bind), as\n * factories — each runner instantiates its own pack because bind state is\n * per-runner. Assembled at process start (e.g. GitHub PR/CI pack); core\n * stays platform-neutral.\n */\n platformToolPackFactories?: readonly PlatformToolPackFactory[];\n}\n\nexport interface ConversationRuntime extends MessagingEventHandler {\n runSession(options: RunSessionOptions): Promise<void>;\n switchConversationModel(address: OfficeAddress, provider: string, model: string): boolean;\n refreshConversationEnvironment(address: OfficeAddress): boolean;\n /** Clear idle runners; defer busy conversation invalidation until settlement. */\n refreshAllConversations(): { busy: OfficeAddress[] };\n shutdown(timeoutMs?: number): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { PiAgentWrapper } from \"../agent.js\";\nimport type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ConversationKind,\n OfficeAddress,\n PlatformBlockKit,\n PlatformNotifier,\n PlatformReactor,\n PlatformUploader,\n} from \"../adapter.js\";\nimport type {\n AdminTokenStoreLike,\n CommandHandler,\n CommandServices,\n LinkTokenStoreLike,\n SessionViewTokenStoreLike,\n} from \"../commands/types.js\";\nimport type { MikanModels } from \"../harness/index.js\";\nimport type { PlatformToolPackFactory } from \"../tools/types.js\";\nimport type { VaultManager } from \"../vault/index.js\";\n\nexport interface SessionLifecycleOptions {\n maxSessions?: number;\n idleTimeoutMs?: number;\n now?: () => number;\n}\n\nexport interface ConversationRuntimeState {\n /** The office that owns this runtime state. */\n address: OfficeAddress;\n /** This office's platform session reference (raw session-key grammar). */\n sessionKey: string;\n running: boolean;\n /** Exact settlement of the current run, including post-run response handling. */\n runSettlement?: Promise<void>;\n runner: PiAgentWrapper;\n stopRequested: boolean;\n stopMessageTs?: string;\n lastAccessedAt: number;\n sessionFile: string;\n /** Epoch ms when the current run started; 0 when idle. */\n startedAt: number;\n lastActivityAt?: number;\n}\n\nexport interface RunSessionOptions {\n event: ConversationEvent;\n bot: MessagingBot;\n context: ConversationContext;\n}\n\n/** Conversation/session identity used to resolve per-session runner state. */\nexport interface SessionStateOptions {\n /** Canonical office identity; the runtime keys all state by this. */\n address: OfficeAddress;\n /**\n * The office's raw platform id — the session-key grammar's conversation\n * value (a bare conversation session key equals it). Never a storage key;\n * layout and settings are addressed through the Office value.\n */\n conversationId: string;\n sessionKey: string;\n conversationKind?: ConversationKind;\n}\n\nexport interface ConversationRuntimeOptions extends Omit<\n CommandServices,\n \"runtime\" | \"vaultManager\" | \"linkTokenStore\" | \"sessionViewTokenStore\" | \"adminTokenStore\"\n> {\n /**\n * Credential vault for sandboxed conversations. Optional for embedders;\n * when omitted the runtime uses an inert, disabled vault.\n */\n vaultManager?: VaultManager;\n /** Login-portal token store; omit when no web portal is hosted. */\n linkTokenStore?: LinkTokenStoreLike;\n /** Session-viewer token store; omit when no web portal is hosted. */\n sessionViewTokenStore?: SessionViewTokenStoreLike;\n /** Admin-portal token store; omit when no web portal is hosted. */\n adminTokenStore?: AdminTokenStoreLike;\n /** Override the default command handlers (e.g., to add /help, /status). */\n commandHandlers?: readonly CommandHandler[];\n /** Model registry override; defaults to the process-wide models.json load. */\n models?: MikanModels;\n /** Proactive platform messaging for extensions (`api.notify`). */\n platformNotifier?: PlatformNotifier;\n /** Proactive emoji reactions for extensions (`api.react`). */\n platformReactor?: PlatformReactor;\n /** Proactive file uploads for extensions (`api.uploadFile`). */\n platformUploader?: PlatformUploader;\n /** Interactive Block Kit posting/updating for extensions (`api.blockkit`). */\n platformBlockKit?: PlatformBlockKit;\n /**\n * Optional platform capability packs (extra tools + per-run bind), as\n * factories — each runner instantiates its own pack because bind state is\n * per-runner. Assembled at process start (e.g. GitHub PR/CI pack); core\n * stays platform-neutral.\n */\n platformToolPackFactories?: readonly PlatformToolPackFactory[];\n}\n\nexport interface ConversationRuntime extends MessagingEventHandler {\n runSession(options: RunSessionOptions): Promise<void>;\n switchConversationModel(address: OfficeAddress, provider: string, model: string): boolean;\n refreshConversationEnvironment(address: OfficeAddress): boolean;\n /** Clear idle runners; defer busy conversation invalidation until settlement. */\n refreshAllConversations(): { busy: OfficeAddress[] };\n shutdown(timeoutMs?: number): Promise<void>;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { officeKey } from "../office-address.js";
2
+ import { officeKey } from "../office/index.js";
3
3
  const IDENTITY_HASH_LENGTH = 12;
4
4
  /**
5
5
  * Vault key for a run. Conversation-scoped sandboxes (image, gondolin,
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAahC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CACxC,UAAyB,EACzB,KAAsB;IAEtB,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3F,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,UAAyB,EACzB,KAAsB;IAEtB,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IACpD,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,aAAa,UAAU,CAAC,SAAS,EAAE,CAAC;IAChF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAAC,iBAAyB;IACvE,OAAO,WAAW,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAyB,EACzB,GAA+C;IAE/C,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3F,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvE,OAAO,WAAW,CAAC,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,MAAM,SAAS,GAAG,KAAK;SACpB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,SAAS,IAAI,SAAS,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,WAAmB;IAC1E,OAAO,GAAG,MAAM,IAAI,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,WAAW,CAAC,IAA2C,EAAE,KAAa;IAC7E,MAAM,QAAQ,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC;SAC9B,MAAM,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC;SAC3B,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAClC,OAAO,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC/B,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { officeKey } from \"../office-address.js\";\nimport type { OfficeAddress } from \"../types.js\";\nimport type { SandboxConfig } from \"./types.js\";\n\nconst IDENTITY_HASH_LENGTH = 12;\n\n/** Identity a run authenticates as when resolving credentials. */\nexport interface CredentialScope {\n userId: string;\n /**\n * Office whose credentials the run may use — the vault-routing address\n * (`vaultConversationId` substituted where a command targets another\n * conversation's vault on the same platform).\n */\n address: OfficeAddress;\n}\n\n/**\n * Vault key for a run. Conversation-scoped sandboxes (image, gondolin,\n * firecracker, cloudflare) key credentials by office key: platform-scoped and\n * collision-resistant, so two platforms sharing a raw conversation id can\n * never resolve each other's credentials — and one identity string names the\n * office across the workspace, the registry, and the vault.\n *\n * Host mode keys by user (the host has no execution isolation to scope to)\n * and container mode by the deployment-chosen container; both are\n * platform-neutral on purpose and unchanged by ADR 0005.\n */\nexport function credentialAuthorizationKey(\n baseConfig: SandboxConfig,\n scope: CredentialScope,\n): string {\n if (baseConfig.type === \"host\") return identityKey(\"user\", scope.userId);\n if (baseConfig.type === \"container\") return identityKey(\"container\", baseConfig.container);\n return officeKey(scope.address);\n}\n\nexport function legacyExactCredentialAuthorizationKey(\n baseConfig: SandboxConfig,\n scope: CredentialScope,\n): string | undefined {\n if (baseConfig.type === \"host\") return scope.userId;\n if (baseConfig.type === \"container\") return `container-${baseConfig.container}`;\n return undefined;\n}\n\n/**\n * The raw-id conversation vault key written before the office migration; the\n * boot-time vault migration renames these directories to office keys.\n */\nexport function legacyConversationCredentialKey(rawConversationId: string): string {\n return identityKey(\"conversation\", rawConversationId);\n}\n\n/**\n * Sandbox resource identity (container name, gondolin instance, cloudflare\n * sandbox scope). Still raw-conversation-keyed: renaming it churns every\n * provisioned container on upgrade, so it migrates with the resource-naming\n * commit tracked by ADR 0005 — a cross-platform id collision here costs a\n * container recreate (mount signatures differ), never credential access.\n */\nexport function runtimeResourceKey(\n baseConfig: SandboxConfig,\n ids: { userId: string; conversationId: string },\n): string {\n if (baseConfig.type === \"container\") return identityKey(\"container\", baseConfig.container);\n if (baseConfig.type === \"host\") return identityKey(\"user\", ids.userId);\n return identityKey(\"conversation\", ids.conversationId);\n}\n\nexport function sanitizeIdentitySegment(value: string): string {\n const sanitized = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return sanitized || \"unknown\";\n}\n\nexport function scopeCloudflareSandboxId(baseId: string, resourceKey: string): string {\n return `${baseId}-${resourceKey}`;\n}\n\nfunction identityKey(kind: \"user\" | \"conversation\" | \"container\", value: string): string {\n const readable = sanitizeIdentitySegment(value).slice(0, 40).replace(/-+$/g, \"\") || \"unknown\";\n const hash = createHash(\"sha256\")\n .update(`${kind}\\0${value}`)\n .digest(\"hex\")\n .slice(0, IDENTITY_HASH_LENGTH);\n return `${readable}-${hash}`;\n}\n"]}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAI/C,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAahC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CACxC,UAAyB,EACzB,KAAsB;IAEtB,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3F,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,qCAAqC,CACnD,UAAyB,EACzB,KAAsB;IAEtB,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IACpD,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,aAAa,UAAU,CAAC,SAAS,EAAE,CAAC;IAChF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAAC,iBAAyB;IACvE,OAAO,WAAW,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAyB,EACzB,GAA+C;IAE/C,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3F,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvE,OAAO,WAAW,CAAC,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,MAAM,SAAS,GAAG,KAAK;SACpB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,SAAS,IAAI,SAAS,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,WAAmB;IAC1E,OAAO,GAAG,MAAM,IAAI,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,WAAW,CAAC,IAA2C,EAAE,KAAa;IAC7E,MAAM,QAAQ,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;IAC9F,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC;SAC9B,MAAM,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC;SAC3B,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAClC,OAAO,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC/B,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { officeKey } from \"../office/index.js\";\nimport type { OfficeAddress } from \"../types.js\";\nimport type { SandboxConfig } from \"./types.js\";\n\nconst IDENTITY_HASH_LENGTH = 12;\n\n/** Identity a run authenticates as when resolving credentials. */\nexport interface CredentialScope {\n userId: string;\n /**\n * Office whose credentials the run may use — the vault-routing address\n * (`vaultConversationId` substituted where a command targets another\n * conversation's vault on the same platform).\n */\n address: OfficeAddress;\n}\n\n/**\n * Vault key for a run. Conversation-scoped sandboxes (image, gondolin,\n * firecracker, cloudflare) key credentials by office key: platform-scoped and\n * collision-resistant, so two platforms sharing a raw conversation id can\n * never resolve each other's credentials — and one identity string names the\n * office across the workspace, the registry, and the vault.\n *\n * Host mode keys by user (the host has no execution isolation to scope to)\n * and container mode by the deployment-chosen container; both are\n * platform-neutral on purpose and unchanged by ADR 0005.\n */\nexport function credentialAuthorizationKey(\n baseConfig: SandboxConfig,\n scope: CredentialScope,\n): string {\n if (baseConfig.type === \"host\") return identityKey(\"user\", scope.userId);\n if (baseConfig.type === \"container\") return identityKey(\"container\", baseConfig.container);\n return officeKey(scope.address);\n}\n\nexport function legacyExactCredentialAuthorizationKey(\n baseConfig: SandboxConfig,\n scope: CredentialScope,\n): string | undefined {\n if (baseConfig.type === \"host\") return scope.userId;\n if (baseConfig.type === \"container\") return `container-${baseConfig.container}`;\n return undefined;\n}\n\n/**\n * The raw-id conversation vault key written before the office migration; the\n * boot-time vault migration renames these directories to office keys.\n */\nexport function legacyConversationCredentialKey(rawConversationId: string): string {\n return identityKey(\"conversation\", rawConversationId);\n}\n\n/**\n * Sandbox resource identity (container name, gondolin instance, cloudflare\n * sandbox scope). Still raw-conversation-keyed: renaming it churns every\n * provisioned container on upgrade, so it migrates with the resource-naming\n * commit tracked by ADR 0005 — a cross-platform id collision here costs a\n * container recreate (mount signatures differ), never credential access.\n */\nexport function runtimeResourceKey(\n baseConfig: SandboxConfig,\n ids: { userId: string; conversationId: string },\n): string {\n if (baseConfig.type === \"container\") return identityKey(\"container\", baseConfig.container);\n if (baseConfig.type === \"host\") return identityKey(\"user\", ids.userId);\n return identityKey(\"conversation\", ids.conversationId);\n}\n\nexport function sanitizeIdentitySegment(value: string): string {\n const sanitized = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return sanitized || \"unknown\";\n}\n\nexport function scopeCloudflareSandboxId(baseId: string, resourceKey: string): string {\n return `${baseId}-${resourceKey}`;\n}\n\nfunction identityKey(kind: \"user\" | \"conversation\" | \"container\", value: string): string {\n const readable = sanitizeIdentitySegment(value).slice(0, 40).replace(/-+$/g, \"\") || \"unknown\";\n const hash = createHash(\"sha256\")\n .update(`${kind}\\0${value}`)\n .digest(\"hex\")\n .slice(0, IDENTITY_HASH_LENGTH);\n return `${readable}-${hash}`;\n}\n"]}
@@ -17,9 +17,10 @@
17
17
  * automatically before their next turn.
18
18
  */
19
19
  import { type WorkspacePolicyChoice } from "./config.js";
20
+ import type { Office } from "./office/index.js";
20
21
  import type { AgentConfig, GlobalRunnerCacheControl, OfficeAddress, RunnerCacheControl, SettingsApplyResult } from "./types.js";
21
22
  export type { GlobalRunnerCacheControl, RunnerCacheControl, SettingsApplyResult } from "./types.js";
22
- export declare function applyConversationSettings(runtime: RunnerCacheControl | undefined, workingDir: string, address: OfficeAddress, patch: Partial<AgentConfig>): SettingsApplyResult;
23
+ export declare function applyConversationSettings(runtime: RunnerCacheControl | undefined, office: Office, patch: Partial<AgentConfig>): SettingsApplyResult;
23
24
  export declare function applyGlobalSettings(runtime: GlobalRunnerCacheControl | undefined, patch: Partial<AgentConfig>): {
24
25
  ok: true;
25
26
  staleConversations: OfficeAddress[];
@@ -31,7 +32,7 @@ export declare function applyGlobalSettings(runtime: GlobalRunnerCacheControl |
31
32
  * write, and the container is re-provisioned on the next message when its
32
33
  * mount signature no longer matches.
33
34
  */
34
- export declare function applyConversationWorkspacePolicy(runtime: RunnerCacheControl | undefined, workingDir: string, address: OfficeAddress, choice: WorkspacePolicyChoice | null): SettingsApplyResult;
35
+ export declare function applyConversationWorkspacePolicy(runtime: RunnerCacheControl | undefined, office: Office, choice: WorkspacePolicyChoice | null): SettingsApplyResult;
35
36
  export declare function applyGlobalWorkspacePolicy(runtime: GlobalRunnerCacheControl | undefined, choice: WorkspacePolicyChoice | null): {
36
37
  ok: true;
37
38
  staleConversations: OfficeAddress[];
@@ -1 +1 @@
1
- {"version":3,"file":"settings-mutation.d.ts","sourceRoot":"","sources":["../src/settings-mutation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,WAAW,EACX,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AASpG,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,GAAG,SAAS,EACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,mBAAmB,CAerB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,wBAAwB,GAAG,SAAS,EAC7C,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,aAAa,EAAE,CAAA;CAAE,CAKnD;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,kBAAkB,GAAG,SAAS,EACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC,mBAAmB,CASrB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,wBAAwB,GAAG,SAAS,EAC7C,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,aAAa,EAAE,CAAA;CAAE,CAInD"}
1
+ {"version":3,"file":"settings-mutation.d.ts","sourceRoot":"","sources":["../src/settings-mutation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EACV,WAAW,EACX,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AASpG,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,GAAG,SAAS,EACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,mBAAmB,CAYrB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,wBAAwB,GAAG,SAAS,EAC7C,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,aAAa,EAAE,CAAA;CAAE,CAKnD;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,kBAAkB,GAAG,SAAS,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC,mBAAmB,CAMrB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,wBAAwB,GAAG,SAAS,EAC7C,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,aAAa,EAAE,CAAA;CAAE,CAInD"}
@@ -17,22 +17,21 @@
17
17
  * automatically before their next turn.
18
18
  */
19
19
  import { setConversationWorkspacePolicy, setGlobalWorkspacePolicy, updateConversationSettings, updateGlobalSettings, } from "./config.js";
20
- import { conversationOfficeDir } from "./office-address.js";
21
20
  /** True when a patch touches keys a cached session runner bakes in. */
22
21
  function affectsCachedRunner(patch) {
23
22
  return (patch.provider !== undefined || patch.model !== undefined || patch.thinkingLevel !== undefined);
24
23
  }
25
- export function applyConversationSettings(runtime, workingDir, address, patch) {
24
+ export function applyConversationSettings(runtime, office, patch) {
26
25
  let runtimeSwitched = null;
27
26
  if (affectsCachedRunner(patch) && runtime) {
28
27
  // Clear-or-refuse before writing. The clear and the write happen in the
29
28
  // same synchronous tick, so no runner can be created in between.
30
- if (!runtime.switchConversationModel(address, patch.provider ?? "", patch.model ?? "")) {
29
+ if (!runtime.switchConversationModel(office.address, patch.provider ?? "", patch.model ?? "")) {
31
30
  return { ok: false, reason: "busy" };
32
31
  }
33
32
  runtimeSwitched = true;
34
33
  }
35
- updateConversationSettings({ address, conversationDir: conversationOfficeDir(workingDir, address) }, patch);
34
+ updateConversationSettings(office, patch);
36
35
  return { ok: true, runtimeSwitched };
37
36
  }
38
37
  export function applyGlobalSettings(runtime, patch) {
@@ -47,11 +46,11 @@ export function applyGlobalSettings(runtime, patch) {
47
46
  * write, and the container is re-provisioned on the next message when its
48
47
  * mount signature no longer matches.
49
48
  */
50
- export function applyConversationWorkspacePolicy(runtime, workingDir, address, choice) {
51
- if (runtime && !runtime.refreshConversationEnvironment(address)) {
49
+ export function applyConversationWorkspacePolicy(runtime, office, choice) {
50
+ if (runtime && !runtime.refreshConversationEnvironment(office.address)) {
52
51
  return { ok: false, reason: "busy" };
53
52
  }
54
- setConversationWorkspacePolicy({ address, conversationDir: conversationOfficeDir(workingDir, address) }, choice);
53
+ setConversationWorkspacePolicy(office, choice);
55
54
  return { ok: true, runtimeSwitched: runtime ? true : null };
56
55
  }
57
56
  export function applyGlobalWorkspacePolicy(runtime, choice) {
@@ -1 +1 @@
1
- {"version":3,"file":"settings-mutation.js","sourceRoot":"","sources":["../src/settings-mutation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EACL,8BAA8B,EAC9B,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,GAErB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAW5D,uEAAuE;AACvE,SAAS,mBAAmB,CAAC,KAA2B;IACtD,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,CAC/F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAAuC,EACvC,UAAkB,EAClB,OAAsB,EACtB,KAA2B;IAE3B,IAAI,eAAe,GAAmB,IAAI,CAAC;IAC3C,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QAC1C,wEAAwE;QACxE,iEAAiE;QACjE,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACvF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACvC,CAAC;QACD,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;IACD,0BAA0B,CACxB,EAAE,OAAO,EAAE,eAAe,EAAE,qBAAqB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EACxE,KAAK,CACN,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAA6C,EAC7C,KAA2B;IAE3B,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,kBAAkB,GACtB,mBAAmB,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAC9C,OAAuC,EACvC,UAAkB,EAClB,OAAsB,EACtB,MAAoC;IAEpC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,8BAA8B,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACvC,CAAC;IACD,8BAA8B,CAC5B,EAAE,OAAO,EAAE,eAAe,EAAE,qBAAqB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EACxE,MAAM,CACP,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAA6C,EAC7C,MAAoC;IAEpC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * The one writer seam for settings mutations that affect live conversations.\n * Chat commands (/model, /sandbox) and the Admin portal are adapters here;\n * none of them call updateConversationSettings/updateGlobalSettings directly\n * for these keys anymore.\n *\n * Policy, uniform across all adapters:\n * - llm.* changes bake into cached session runners, so a conversation-scoped\n * change clears the conversation's cached runners BEFORE writing — and\n * refuses (no write, no clear) while the conversation has a running job.\n * Disk and cache never disagree.\n * - Other keys (sandbox mount, slack replyMode, limits) are re-read at use\n * time and write without touching runners.\n * - Global changes always write (the Admin default surface), then clear every\n * idle conversation's cached runners; conversations that were busy keep\n * their old runner until it settles, are reported as stale, and are cleared\n * automatically before their next turn.\n */\nimport {\n setConversationWorkspacePolicy,\n setGlobalWorkspacePolicy,\n updateConversationSettings,\n updateGlobalSettings,\n type WorkspacePolicyChoice,\n} from \"./config.js\";\nimport { conversationOfficeDir } from \"./office-address.js\";\nimport type {\n AgentConfig,\n GlobalRunnerCacheControl,\n OfficeAddress,\n RunnerCacheControl,\n SettingsApplyResult,\n} from \"./types.js\";\n\nexport type { GlobalRunnerCacheControl, RunnerCacheControl, SettingsApplyResult } from \"./types.js\";\n\n/** True when a patch touches keys a cached session runner bakes in. */\nfunction affectsCachedRunner(patch: Partial<AgentConfig>): boolean {\n return (\n patch.provider !== undefined || patch.model !== undefined || patch.thinkingLevel !== undefined\n );\n}\n\nexport function applyConversationSettings(\n runtime: RunnerCacheControl | undefined,\n workingDir: string,\n address: OfficeAddress,\n patch: Partial<AgentConfig>,\n): SettingsApplyResult {\n let runtimeSwitched: boolean | null = null;\n if (affectsCachedRunner(patch) && runtime) {\n // Clear-or-refuse before writing. The clear and the write happen in the\n // same synchronous tick, so no runner can be created in between.\n if (!runtime.switchConversationModel(address, patch.provider ?? \"\", patch.model ?? \"\")) {\n return { ok: false, reason: \"busy\" };\n }\n runtimeSwitched = true;\n }\n updateConversationSettings(\n { address, conversationDir: conversationOfficeDir(workingDir, address) },\n patch,\n );\n return { ok: true, runtimeSwitched };\n}\n\nexport function applyGlobalSettings(\n runtime: GlobalRunnerCacheControl | undefined,\n patch: Partial<AgentConfig>,\n): { ok: true; staleConversations: OfficeAddress[] } {\n updateGlobalSettings(patch);\n const staleConversations =\n affectsCachedRunner(patch) && runtime ? runtime.refreshAllConversations().busy : [];\n return { ok: true, staleConversations };\n}\n\n/**\n * Door-policy changes follow the same clear-or-refuse contract as model\n * changes: the system prompt bakes the workspace projection (layout line,\n * memory and skill guidance), so the cached runner must clear before the\n * write, and the container is re-provisioned on the next message when its\n * mount signature no longer matches.\n */\nexport function applyConversationWorkspacePolicy(\n runtime: RunnerCacheControl | undefined,\n workingDir: string,\n address: OfficeAddress,\n choice: WorkspacePolicyChoice | null,\n): SettingsApplyResult {\n if (runtime && !runtime.refreshConversationEnvironment(address)) {\n return { ok: false, reason: \"busy\" };\n }\n setConversationWorkspacePolicy(\n { address, conversationDir: conversationOfficeDir(workingDir, address) },\n choice,\n );\n return { ok: true, runtimeSwitched: runtime ? true : null };\n}\n\nexport function applyGlobalWorkspacePolicy(\n runtime: GlobalRunnerCacheControl | undefined,\n choice: WorkspacePolicyChoice | null,\n): { ok: true; staleConversations: OfficeAddress[] } {\n setGlobalWorkspacePolicy(choice);\n const staleConversations = runtime ? runtime.refreshAllConversations().busy : [];\n return { ok: true, staleConversations };\n}\n"]}
1
+ {"version":3,"file":"settings-mutation.js","sourceRoot":"","sources":["../src/settings-mutation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EACL,8BAA8B,EAC9B,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,GAErB,MAAM,aAAa,CAAC;AAYrB,uEAAuE;AACvE,SAAS,mBAAmB,CAAC,KAA2B;IACtD,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,CAC/F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAAuC,EACvC,MAAc,EACd,KAA2B;IAE3B,IAAI,eAAe,GAAmB,IAAI,CAAC;IAC3C,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QAC1C,wEAAwE;QACxE,iEAAiE;QACjE,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YAC9F,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACvC,CAAC;QACD,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;IACD,0BAA0B,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAA6C,EAC7C,KAA2B;IAE3B,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,kBAAkB,GACtB,mBAAmB,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gCAAgC,CAC9C,OAAuC,EACvC,MAAc,EACd,MAAoC;IAEpC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,8BAA8B,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACvC,CAAC;IACD,8BAA8B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAA6C,EAC7C,MAAoC;IAEpC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * The one writer seam for settings mutations that affect live conversations.\n * Chat commands (/model, /sandbox) and the Admin portal are adapters here;\n * none of them call updateConversationSettings/updateGlobalSettings directly\n * for these keys anymore.\n *\n * Policy, uniform across all adapters:\n * - llm.* changes bake into cached session runners, so a conversation-scoped\n * change clears the conversation's cached runners BEFORE writing — and\n * refuses (no write, no clear) while the conversation has a running job.\n * Disk and cache never disagree.\n * - Other keys (sandbox mount, slack replyMode, limits) are re-read at use\n * time and write without touching runners.\n * - Global changes always write (the Admin default surface), then clear every\n * idle conversation's cached runners; conversations that were busy keep\n * their old runner until it settles, are reported as stale, and are cleared\n * automatically before their next turn.\n */\nimport {\n setConversationWorkspacePolicy,\n setGlobalWorkspacePolicy,\n updateConversationSettings,\n updateGlobalSettings,\n type WorkspacePolicyChoice,\n} from \"./config.js\";\nimport type { Office } from \"./office/index.js\";\nimport type {\n AgentConfig,\n GlobalRunnerCacheControl,\n OfficeAddress,\n RunnerCacheControl,\n SettingsApplyResult,\n} from \"./types.js\";\n\nexport type { GlobalRunnerCacheControl, RunnerCacheControl, SettingsApplyResult } from \"./types.js\";\n\n/** True when a patch touches keys a cached session runner bakes in. */\nfunction affectsCachedRunner(patch: Partial<AgentConfig>): boolean {\n return (\n patch.provider !== undefined || patch.model !== undefined || patch.thinkingLevel !== undefined\n );\n}\n\nexport function applyConversationSettings(\n runtime: RunnerCacheControl | undefined,\n office: Office,\n patch: Partial<AgentConfig>,\n): SettingsApplyResult {\n let runtimeSwitched: boolean | null = null;\n if (affectsCachedRunner(patch) && runtime) {\n // Clear-or-refuse before writing. The clear and the write happen in the\n // same synchronous tick, so no runner can be created in between.\n if (!runtime.switchConversationModel(office.address, patch.provider ?? \"\", patch.model ?? \"\")) {\n return { ok: false, reason: \"busy\" };\n }\n runtimeSwitched = true;\n }\n updateConversationSettings(office, patch);\n return { ok: true, runtimeSwitched };\n}\n\nexport function applyGlobalSettings(\n runtime: GlobalRunnerCacheControl | undefined,\n patch: Partial<AgentConfig>,\n): { ok: true; staleConversations: OfficeAddress[] } {\n updateGlobalSettings(patch);\n const staleConversations =\n affectsCachedRunner(patch) && runtime ? runtime.refreshAllConversations().busy : [];\n return { ok: true, staleConversations };\n}\n\n/**\n * Door-policy changes follow the same clear-or-refuse contract as model\n * changes: the system prompt bakes the workspace projection (layout line,\n * memory and skill guidance), so the cached runner must clear before the\n * write, and the container is re-provisioned on the next message when its\n * mount signature no longer matches.\n */\nexport function applyConversationWorkspacePolicy(\n runtime: RunnerCacheControl | undefined,\n office: Office,\n choice: WorkspacePolicyChoice | null,\n): SettingsApplyResult {\n if (runtime && !runtime.refreshConversationEnvironment(office.address)) {\n return { ok: false, reason: \"busy\" };\n }\n setConversationWorkspacePolicy(office, choice);\n return { ok: true, runtimeSwitched: runtime ? true : null };\n}\n\nexport function applyGlobalWorkspacePolicy(\n runtime: GlobalRunnerCacheControl | undefined,\n choice: WorkspacePolicyChoice | null,\n): { ok: true; staleConversations: OfficeAddress[] } {\n setGlobalWorkspacePolicy(choice);\n const staleConversations = runtime ? runtime.refreshAllConversations().busy : [];\n return { ok: true, staleConversations };\n}\n"]}
@@ -8,10 +8,16 @@ declare const schema: import("@sinclair/typebox").TObject<{
8
8
  export declare function createGenerateImageTool(options: {
9
9
  model: Model<Api>;
10
10
  getApiKey: () => Promise<string | undefined>;
11
- workspaceDir: string;
11
+ /** Host directory the generated image is written into. Must be the
12
+ * conversation's own office dir so the agent can also reach the file
13
+ * from inside the sandbox; the workspace base is NOT guest-visible. */
14
+ outputDir: string;
12
15
  }): {
13
16
  tool: AgentTool<typeof schema>;
14
- setUploadFunction: (fn: (filePath: string, title?: string) => Promise<void>) => void;
17
+ /** The callback receives the HOST path of the generated file. The image is
18
+ * written host-side, so upload must not stage it through the sandbox the
19
+ * way the attach tool does — the file may not be mounted there. */
20
+ setUploadFunction: (fn: (hostPath: string, title?: string) => Promise<void>) => void;
15
21
  };
16
22
  export {};
17
23
  //# sourceMappingURL=generate-image.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-image.d.ts","sourceRoot":"","sources":["../../src/tools/generate-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAMxD,QAAA,MAAM,MAAM;;;;EAMV,CAAC;AAOH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG;IACF,IAAI,EAAE,SAAS,CAAC,OAAO,MAAM,CAAC,CAAC;IAC/B,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CACtF,CA2DA"}
1
+ {"version":3,"file":"generate-image.d.ts","sourceRoot":"","sources":["../../src/tools/generate-image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAMxD,QAAA,MAAM,MAAM;;;;EAMV,CAAC;AAOH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C;;4EAEwE;IACxE,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG;IACF,IAAI,EAAE,SAAS,CAAC,OAAO,MAAM,CAAC,CAAC;IAC/B;;wEAEoE;IACpE,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;CACtF,CA6DA"}
@@ -41,14 +41,16 @@ export function createGenerateImageTool(options) {
41
41
  });
42
42
  const body = (await response.json());
43
43
  if (!response.ok) {
44
- throw new Error(body.error?.message ?? `Image generation failed with HTTP ${response.status}`);
44
+ throw new Error(`Image generation with model "${options.model.id}" failed: ` +
45
+ (body.error?.message ?? `HTTP ${response.status}`));
45
46
  }
46
47
  const encoded = body.data?.[0]?.b64_json;
47
48
  if (!encoded)
48
49
  throw new Error("Image generation response contained no image");
49
50
  const fileName = `generated-${randomUUID()}.png`;
50
- await writeFile(join(options.workspaceDir, fileName), Buffer.from(encoded, "base64"));
51
- await uploadFn(fileName, fileName);
51
+ const filePath = join(options.outputDir, fileName);
52
+ await writeFile(filePath, Buffer.from(encoded, "base64"));
53
+ await uploadFn(filePath, fileName);
52
54
  return {
53
55
  content: [{ type: "text", text: `Generated and attached image: ${fileName}` }],
54
56
  details: { fileName },