@geminixiang/mikan 0.4.8 → 0.5.0

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 (237) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +13 -13
  3. package/dist/adapter.d.ts +1 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/discord/bot.d.ts +9 -6
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +22 -22
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts +6 -6
  11. package/dist/adapters/discord/context.d.ts.map +1 -1
  12. package/dist/adapters/discord/context.js +3 -3
  13. package/dist/adapters/discord/context.js.map +1 -1
  14. package/dist/adapters/discord/types.d.ts +2 -2
  15. package/dist/adapters/discord/types.d.ts.map +1 -1
  16. package/dist/adapters/discord/types.js.map +1 -1
  17. package/dist/adapters/intake.d.ts +2 -2
  18. package/dist/adapters/intake.d.ts.map +1 -1
  19. package/dist/adapters/intake.js +4 -4
  20. package/dist/adapters/intake.js.map +1 -1
  21. package/dist/adapters/shared.d.ts +3 -3
  22. package/dist/adapters/shared.d.ts.map +1 -1
  23. package/dist/adapters/shared.js +2 -2
  24. package/dist/adapters/shared.js.map +1 -1
  25. package/dist/adapters/slack/bot.d.ts +10 -7
  26. package/dist/adapters/slack/bot.d.ts.map +1 -1
  27. package/dist/adapters/slack/bot.js +46 -46
  28. package/dist/adapters/slack/bot.js.map +1 -1
  29. package/dist/adapters/slack/context.d.ts +6 -6
  30. package/dist/adapters/slack/context.d.ts.map +1 -1
  31. package/dist/adapters/slack/context.js +2 -2
  32. package/dist/adapters/slack/context.js.map +1 -1
  33. package/dist/adapters/slack/response-lifecycle.d.ts +6 -6
  34. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  35. package/dist/adapters/slack/response-lifecycle.js +3 -3
  36. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  37. package/dist/adapters/slack/session.d.ts.map +1 -1
  38. package/dist/adapters/slack/tools/attach.d.ts.map +1 -1
  39. package/dist/adapters/slack/tools/block-kit.d.ts.map +1 -1
  40. package/dist/adapters/slack/types.d.ts +1 -1
  41. package/dist/adapters/slack/types.d.ts.map +1 -1
  42. package/dist/adapters/slack/types.js.map +1 -1
  43. package/dist/adapters/streaming.d.ts.map +1 -1
  44. package/dist/adapters/telegram/bot.d.ts +10 -7
  45. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  46. package/dist/adapters/telegram/bot.js +21 -21
  47. package/dist/adapters/telegram/bot.js.map +1 -1
  48. package/dist/adapters/telegram/context.d.ts +6 -6
  49. package/dist/adapters/telegram/context.d.ts.map +1 -1
  50. package/dist/adapters/telegram/context.js +3 -3
  51. package/dist/adapters/telegram/context.js.map +1 -1
  52. package/dist/adapters/telegram/html.d.ts.map +1 -1
  53. package/dist/adapters/telegram/types.d.ts +2 -2
  54. package/dist/adapters/telegram/types.d.ts.map +1 -1
  55. package/dist/adapters/telegram/types.js.map +1 -1
  56. package/dist/adapters/types.d.ts +6 -6
  57. package/dist/adapters/types.d.ts.map +1 -1
  58. package/dist/adapters/types.js.map +1 -1
  59. package/dist/agent-events.d.ts +5 -0
  60. package/dist/agent-events.d.ts.map +1 -0
  61. package/dist/agent-events.js +26 -0
  62. package/dist/agent-events.js.map +1 -0
  63. package/dist/agent.d.ts +7 -7
  64. package/dist/agent.d.ts.map +1 -1
  65. package/dist/agent.js +84 -41
  66. package/dist/agent.js.map +1 -1
  67. package/dist/commands/admin.d.ts.map +1 -1
  68. package/dist/commands/admin.js +1 -1
  69. package/dist/commands/admin.js.map +1 -1
  70. package/dist/commands/auto-reply.d.ts.map +1 -1
  71. package/dist/commands/auto-reply.js +3 -3
  72. package/dist/commands/auto-reply.js.map +1 -1
  73. package/dist/commands/login.d.ts.map +1 -1
  74. package/dist/commands/login.js +1 -1
  75. package/dist/commands/login.js.map +1 -1
  76. package/dist/commands/model.d.ts.map +1 -1
  77. package/dist/commands/model.js +5 -5
  78. package/dist/commands/model.js.map +1 -1
  79. package/dist/commands/new.d.ts.map +1 -1
  80. package/dist/commands/new.js +2 -2
  81. package/dist/commands/new.js.map +1 -1
  82. package/dist/commands/parse.d.ts.map +1 -1
  83. package/dist/commands/registry.d.ts.map +1 -1
  84. package/dist/commands/sandbox.d.ts.map +1 -1
  85. package/dist/commands/sandbox.js +5 -5
  86. package/dist/commands/sandbox.js.map +1 -1
  87. package/dist/commands/session-view.d.ts.map +1 -1
  88. package/dist/commands/session-view.js +1 -1
  89. package/dist/commands/session-view.js.map +1 -1
  90. package/dist/commands/types.d.ts +5 -5
  91. package/dist/commands/types.d.ts.map +1 -1
  92. package/dist/commands/types.js.map +1 -1
  93. package/dist/commands/utils.d.ts +3 -3
  94. package/dist/commands/utils.d.ts.map +1 -1
  95. package/dist/commands/utils.js +6 -6
  96. package/dist/commands/utils.js.map +1 -1
  97. package/dist/config.d.ts.map +1 -1
  98. package/dist/context.d.ts.map +1 -1
  99. package/dist/download.d.ts.map +1 -1
  100. package/dist/events.d.ts +2 -2
  101. package/dist/events.d.ts.map +1 -1
  102. package/dist/events.js.map +1 -1
  103. package/dist/execution-resolver.d.ts.map +1 -1
  104. package/dist/index.d.ts +3 -3
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +2 -2
  107. package/dist/index.js.map +1 -1
  108. package/dist/log.d.ts.map +1 -1
  109. package/dist/main.d.ts.map +1 -1
  110. package/dist/main.js +35 -27
  111. package/dist/main.js.map +1 -1
  112. package/dist/model-registry.d.ts.map +1 -1
  113. package/dist/observability/instrument.d.ts.map +1 -1
  114. package/dist/observability/sentry.d.ts.map +1 -1
  115. package/dist/observability/sentry.js +27 -9
  116. package/dist/observability/sentry.js.map +1 -1
  117. package/dist/observability/types.d.ts.map +1 -1
  118. package/dist/platform-messages.d.ts +2 -2
  119. package/dist/platform-messages.d.ts.map +1 -1
  120. package/dist/platform-messages.js +2 -2
  121. package/dist/platform-messages.js.map +1 -1
  122. package/dist/portal-shell.d.ts.map +1 -1
  123. package/dist/provisioner.d.ts.map +1 -1
  124. package/dist/runtime/{conversation-orchestrator.d.ts → agent-run-controller.d.ts} +5 -5
  125. package/dist/runtime/agent-run-controller.d.ts.map +1 -0
  126. package/dist/runtime/{conversation-orchestrator.js → agent-run-controller.js} +17 -17
  127. package/dist/runtime/agent-run-controller.js.map +1 -0
  128. package/dist/runtime/conversation-runtime.d.ts +4 -0
  129. package/dist/runtime/conversation-runtime.d.ts.map +1 -0
  130. package/dist/runtime/{session-runtime.js → conversation-runtime.js} +12 -12
  131. package/dist/runtime/conversation-runtime.js.map +1 -0
  132. package/dist/runtime/types.d.ts +9 -9
  133. package/dist/runtime/types.d.ts.map +1 -1
  134. package/dist/runtime/types.js.map +1 -1
  135. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  136. package/dist/sandbox/container.d.ts.map +1 -1
  137. package/dist/sandbox/errors.d.ts.map +1 -1
  138. package/dist/sandbox/firecracker.d.ts.map +1 -1
  139. package/dist/sandbox/host.d.ts.map +1 -1
  140. package/dist/sandbox/image.d.ts.map +1 -1
  141. package/dist/sandbox/index.d.ts.map +1 -1
  142. package/dist/sandbox/path-context.d.ts.map +1 -1
  143. package/dist/sandbox/types.d.ts.map +1 -1
  144. package/dist/sandbox/utils.d.ts.map +1 -1
  145. package/dist/sessions/{chat-session-manager.d.ts → agent-memory-file-manager.d.ts} +6 -6
  146. package/dist/sessions/agent-memory-file-manager.d.ts.map +1 -0
  147. package/dist/sessions/{chat-session-manager.js → agent-memory-file-manager.js} +16 -16
  148. package/dist/sessions/agent-memory-file-manager.js.map +1 -0
  149. package/dist/sessions/metadata.d.ts.map +1 -1
  150. package/dist/sessions/policy.d.ts.map +1 -1
  151. package/dist/sessions/store.d.ts.map +1 -1
  152. package/dist/sessions/store.js +4 -4
  153. package/dist/sessions/store.js.map +1 -1
  154. package/dist/sessions/types.d.ts +3 -3
  155. package/dist/sessions/types.d.ts.map +1 -1
  156. package/dist/sessions/types.js.map +1 -1
  157. package/dist/store.d.ts +3 -0
  158. package/dist/store.d.ts.map +1 -1
  159. package/dist/store.js +1 -1
  160. package/dist/store.js.map +1 -1
  161. package/dist/tool-diagnostics.d.ts.map +1 -1
  162. package/dist/tools/bash.d.ts.map +1 -1
  163. package/dist/tools/edit.d.ts.map +1 -1
  164. package/dist/tools/event.d.ts.map +1 -1
  165. package/dist/tools/index.d.ts.map +1 -1
  166. package/dist/tools/read.d.ts.map +1 -1
  167. package/dist/tools/sandbox.d.ts.map +1 -1
  168. package/dist/tools/truncate.d.ts.map +1 -1
  169. package/dist/tools/types.d.ts.map +1 -1
  170. package/dist/tools/write.d.ts.map +1 -1
  171. package/dist/trigger.d.ts +2 -2
  172. package/dist/trigger.d.ts.map +1 -1
  173. package/dist/trigger.js +1 -1
  174. package/dist/trigger.js.map +1 -1
  175. package/dist/types.d.ts +47 -24
  176. package/dist/types.d.ts.map +1 -1
  177. package/dist/types.js +1 -1
  178. package/dist/types.js.map +1 -1
  179. package/dist/utils/date.d.ts +1 -1
  180. package/dist/utils/date.d.ts.map +1 -1
  181. package/dist/utils/date.js +1 -1
  182. package/dist/utils/date.js.map +1 -1
  183. package/dist/utils/env.d.ts.map +1 -1
  184. package/dist/utils/file-guards.d.ts.map +1 -1
  185. package/dist/utils/fs-atomic.d.ts.map +1 -1
  186. package/dist/utils/html.d.ts.map +1 -1
  187. package/dist/utils/http-body.d.ts.map +1 -1
  188. package/dist/vault/index.d.ts.map +1 -1
  189. package/dist/vault/routing.d.ts.map +1 -1
  190. package/dist/vault/types.d.ts.map +1 -1
  191. package/dist/web/admin/portal.d.ts.map +1 -1
  192. package/dist/web/admin/portal.js +1 -1
  193. package/dist/web/admin/portal.js.map +1 -1
  194. package/dist/web/admin/provider-models.d.ts.map +1 -1
  195. package/dist/web/admin/store.d.ts.map +1 -1
  196. package/dist/web/admin/types.d.ts +1 -1
  197. package/dist/web/admin/types.d.ts.map +1 -1
  198. package/dist/web/admin/types.js.map +1 -1
  199. package/dist/web/agent-events/portal.d.ts +3 -0
  200. package/dist/web/agent-events/portal.d.ts.map +1 -0
  201. package/dist/web/agent-events/portal.js +18 -0
  202. package/dist/web/agent-events/portal.js.map +1 -0
  203. package/dist/web/login/oauth.d.ts.map +1 -1
  204. package/dist/web/login/oauth.js.map +1 -1
  205. package/dist/web/login/portal.d.ts +2 -14
  206. package/dist/web/login/portal.d.ts.map +1 -1
  207. package/dist/web/login/portal.js +53 -130
  208. package/dist/web/login/portal.js.map +1 -1
  209. package/dist/web/login/store.d.ts.map +1 -1
  210. package/dist/web/login/types.d.ts.map +1 -1
  211. package/dist/web/request.d.ts +3 -0
  212. package/dist/web/request.d.ts.map +1 -0
  213. package/dist/web/request.js +13 -0
  214. package/dist/web/request.js.map +1 -0
  215. package/dist/web/server.d.ts +28 -0
  216. package/dist/web/server.d.ts.map +1 -0
  217. package/dist/web/server.js +66 -0
  218. package/dist/web/server.js.map +1 -0
  219. package/dist/web/session-view/command.d.ts.map +1 -1
  220. package/dist/web/session-view/portal.d.ts.map +1 -1
  221. package/dist/web/session-view/portal.js +8 -8
  222. package/dist/web/session-view/portal.js.map +1 -1
  223. package/dist/web/session-view/service.d.ts.map +1 -1
  224. package/dist/web/session-view/store.d.ts.map +1 -1
  225. package/dist/web/session-view/types.d.ts +4 -4
  226. package/dist/web/session-view/types.d.ts.map +1 -1
  227. package/dist/web/session-view/types.js.map +1 -1
  228. package/dist/web/token-store.d.ts.map +1 -1
  229. package/dist/web/types.d.ts.map +1 -1
  230. package/package.json +44 -20
  231. package/dist/runtime/conversation-orchestrator.d.ts.map +0 -1
  232. package/dist/runtime/conversation-orchestrator.js.map +0 -1
  233. package/dist/runtime/session-runtime.d.ts +0 -4
  234. package/dist/runtime/session-runtime.d.ts.map +0 -1
  235. package/dist/runtime/session-runtime.js.map +0 -1
  236. package/dist/sessions/chat-session-manager.d.ts.map +0 -1
  237. package/dist/sessions/chat-session-manager.js.map +0 -1
@@ -2,7 +2,7 @@ import type { ConversationKind } from "../adapter.js";
2
2
  import type { CommandHandler, CommandServices } from "../commands/types.js";
3
3
  export type { ConversationRuntimeState, RunSessionOptions } from "./types.js";
4
4
  import type { ConversationRuntimeState, RunSessionOptions } from "./types.js";
5
- interface ConversationOrchestratorOptions {
5
+ interface AgentRunControllerOptions {
6
6
  workingDir: string;
7
7
  commandHandlers: readonly CommandHandler[];
8
8
  commandServices: CommandServices;
@@ -22,10 +22,10 @@ interface ConversationOrchestratorOptions {
22
22
  afterRunTracked: (runPromise: Promise<void>) => void;
23
23
  onRunFinished: () => void;
24
24
  }
25
- export declare class ConversationOrchestrator {
25
+ export declare class AgentRunController {
26
26
  private readonly options;
27
- constructor(options: ConversationOrchestratorOptions);
28
- runSession({ event, bot, adapters }: RunSessionOptions): Promise<void>;
27
+ constructor(options: AgentRunControllerOptions);
28
+ runSession({ event, bot, context }: RunSessionOptions): Promise<void>;
29
29
  private runWithInstrumentation;
30
30
  }
31
- //# sourceMappingURL=conversation-orchestrator.d.ts.map
31
+ //# sourceMappingURL=agent-run-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-run-controller.d.ts","sourceRoot":"","sources":["../../src/runtime/agent-run-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAGzF,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAc5E,YAAY,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9E,UAAU,yBAAyB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,eAAe,EAAE,eAAe,CAAC;IACjC,cAAc,EAAE,MAAM,OAAO,CAAC;IAC9B,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,wBAAwB,GAAG,SAAS,CAAC;IACvE,gBAAgB,EAAE,CAAC,OAAO,EAAE;QAC1B,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;KACrC,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACxC,sBAAsB,EAAE,CAAC,OAAO,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;IAC9F,gBAAgB,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACtD,eAAe,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACrD,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,yBAAyB,EAAI;IAE7D,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+G1E;YAEa,sBAAsB;CAmGrC"}
@@ -1,4 +1,4 @@
1
- import { waitForThreadSessionBootstrap } from "../sessions/chat-session-manager.js";
1
+ import { waitForThreadSessionBootstrap } from "../sessions/agent-memory-file-manager.js";
2
2
  import { dispatchCommand } from "../commands/registry.js";
3
3
  import { isPrivateConversation } from "../commands/utils.js";
4
4
  import * as log from "../log.js";
@@ -6,11 +6,11 @@ import { addLifecycleBreadcrumb, applyRunScope, createRunAttributionAttributes,
6
6
  import { formatStopped } from "../platform-messages.js";
7
7
  import * as Sentry from "@sentry/node";
8
8
  import { join } from "path";
9
- export class ConversationOrchestrator {
9
+ export class AgentRunController {
10
10
  constructor(options) {
11
11
  this.options = options;
12
12
  }
13
- async runSession({ event, bot, adapters }) {
13
+ async runSession({ event, bot, context }) {
14
14
  const conversationId = event.conversationId;
15
15
  if (this.options.isShuttingDown()) {
16
16
  log.logInfo(`[${conversationId}] Rejected event during shutdown: ${event.text.substring(0, 50)}`);
@@ -20,8 +20,8 @@ export class ConversationOrchestrator {
20
20
  const privateConversation = isPrivateConversation(event);
21
21
  const handledCommand = await dispatchCommand(this.options.commandHandlers, {
22
22
  bot,
23
- responseCtx: adapters.responseCtx,
24
- platform: adapters.platform.name,
23
+ responder: context.responder,
24
+ platform: context.platform.name,
25
25
  platformUserId: event.user,
26
26
  conversationId,
27
27
  vaultConversationId: event.vaultConversationId,
@@ -58,13 +58,13 @@ export class ConversationOrchestrator {
58
58
  surface: "session_setup",
59
59
  operation: "get_or_create_state",
60
60
  severity: "error",
61
- platform: adapters.platform.name,
61
+ platform: context.platform.name,
62
62
  context: {
63
63
  conversationId,
64
64
  sessionKey,
65
- messageId: adapters.message.id,
66
- threadTs: adapters.message.threadTs,
67
- attachmentCount: adapters.message.attachments?.length ?? 0,
65
+ messageId: context.message.id,
66
+ threadTs: context.message.threadTs,
67
+ attachmentCount: context.message.attachments?.length ?? 0,
68
68
  },
69
69
  });
70
70
  throw err;
@@ -76,11 +76,11 @@ export class ConversationOrchestrator {
76
76
  log.logInfo(`[${conversationId}] Starting run: ${event.text.substring(0, 50)}`);
77
77
  const runPromise = (async () => {
78
78
  try {
79
- const result = await this.runWithInstrumentation(adapters, { conversationId, sessionKey, startedAt: state.startedAt }, async () => {
80
- await adapters.responseCtx.setTyping(true);
81
- await adapters.responseCtx.setWorking(true);
82
- const runnerResult = await state.runner.run(adapters.message, adapters.responseCtx, adapters.platform);
83
- await adapters.responseCtx.setWorking(false);
79
+ const result = await this.runWithInstrumentation(context, { conversationId, sessionKey, startedAt: state.startedAt }, async () => {
80
+ await context.responder.setTyping(true);
81
+ await context.responder.setWorking(true);
82
+ const runnerResult = await state.runner.run(context.message, context.responder, context.platform);
83
+ await context.responder.setWorking(false);
84
84
  return runnerResult;
85
85
  });
86
86
  if (result?.stopReason === "aborted" && state.stopRequested) {
@@ -107,9 +107,9 @@ export class ConversationOrchestrator {
107
107
  this.options.afterRunTracked(runPromise);
108
108
  }
109
109
  }
110
- async runWithInstrumentation(adapters, meta, body) {
110
+ async runWithInstrumentation(context, meta, body) {
111
111
  const { conversationId, sessionKey, startedAt } = meta;
112
- const { message, platform } = adapters;
112
+ const { message, platform } = context;
113
113
  const attribution = createRunAttributionAttributes({
114
114
  conversationId,
115
115
  sessionKey,
@@ -189,4 +189,4 @@ export class ConversationOrchestrator {
189
189
  }));
190
190
  }
191
191
  }
192
- //# sourceMappingURL=conversation-orchestrator.js.map
192
+ //# sourceMappingURL=agent-run-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-run-controller.js","sourceRoot":"","sources":["../../src/runtime/agent-run-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationContext, ConversationKind, PlatformName } from \"../adapter.js\";\nimport { waitForThreadSessionBootstrap } from \"../sessions/agent-memory-file-manager.js\";\nimport { 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 { formatStopped } from \"../platform-messages.js\";\nimport * as Sentry from \"@sentry/node\";\nimport { join } from \"path\";\n\nexport type { ConversationRuntimeState, RunSessionOptions } from \"./types.js\";\nimport type { ConversationRuntimeState, RunSessionOptions } from \"./types.js\";\n\ninterface AgentRunControllerOptions {\n workingDir: string;\n commandHandlers: readonly CommandHandler[];\n commandServices: CommandServices;\n isShuttingDown: () => boolean;\n getState: (sessionKey: string) => ConversationRuntimeState | undefined;\n getOrCreateState: (options: {\n conversationId: string;\n sessionKey: string;\n currentMessageId?: string;\n conversationKind?: ConversationKind;\n }) => Promise<ConversationRuntimeState>;\n hasMaterializedSession: (options: { conversationDir: string; sessionKey: string }) => boolean;\n beforeRunTracked: (runPromise: Promise<void>) => void;\n afterRunTracked: (runPromise: Promise<void>) => void;\n onRunFinished: () => void;\n}\n\nexport class AgentRunController {\n constructor(private readonly options: AgentRunControllerOptions) {}\n\n async runSession({ event, bot, context }: RunSessionOptions): Promise<void> {\n const conversationId = event.conversationId;\n if (this.options.isShuttingDown()) {\n log.logInfo(\n `[${conversationId}] Rejected event during shutdown: ${event.text.substring(0, 50)}`,\n );\n return;\n }\n\n const sessionKey = event.sessionKey ?? `${conversationId}:${event.thread_ts ?? event.ts}`;\n const privateConversation = isPrivateConversation(event);\n const handledCommand = await dispatchCommand(this.options.commandHandlers, {\n bot,\n responder: context.responder,\n platform: context.platform.name as PlatformName,\n platformUserId: event.user,\n conversationId,\n vaultConversationId: event.vaultConversationId,\n sessionKey,\n commandText: event.text,\n privateConversation,\n services: this.options.commandServices,\n });\n if (handledCommand) return;\n\n const conversationDir = join(this.options.workingDir, conversationId);\n const waitedForParent = await waitForThreadSessionBootstrap({\n parentSessionKey: conversationId,\n sessionKey,\n hasThreadSession: () => this.options.hasMaterializedSession({ conversationDir, sessionKey }),\n isParentRunning: () => this.options.getState(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: ConversationRuntimeState;\n try {\n state = await this.options.getOrCreateState({\n conversationId,\n sessionKey,\n currentMessageId: event.ts,\n conversationKind: event.conversationKind,\n });\n state.runner.syncChatHistory(event.ts);\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 const runnerResult = await state.runner.run(\n context.message,\n context.responder,\n context.platform,\n );\n await context.responder.setWorking(false);\n return runnerResult;\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 this.options.onRunFinished();\n }\n })();\n\n this.options.beforeRunTracked(runPromise);\n try {\n await runPromise;\n } finally {\n this.options.afterRunTracked(runPromise);\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"]}
@@ -0,0 +1,4 @@
1
+ export type { CreateSessionSandboxOptions, RunSessionOptions, ConversationRuntime, ConversationRuntimeOptions, } from "./types.js";
2
+ import type { ConversationRuntime, ConversationRuntimeOptions } from "./types.js";
3
+ export declare function createConversationRuntime(options: ConversationRuntimeOptions): ConversationRuntime;
4
+ //# sourceMappingURL=conversation-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/conversation-runtime.ts"],"names":[],"mappings":"AAuBA,YAAY,EACV,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAGV,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CAErB"}
@@ -2,9 +2,9 @@ import { createRunner } from "../agent.js";
2
2
  import { defaultCommandHandlers } from "../commands/registry.js";
3
3
  import * as log from "../log.js";
4
4
  import { reportUserFacingError } from "../observability/sentry.js";
5
- import { ChatSessionManager, hasMaterializedChatSession, } from "../sessions/chat-session-manager.js";
5
+ import { AgentMemoryFileManager, hasMaterializedChatSession, } from "../sessions/agent-memory-file-manager.js";
6
6
  import { formatNothingRunning, formatStopping } from "../platform-messages.js";
7
- import { ConversationOrchestrator, } from "./conversation-orchestrator.js";
7
+ import { AgentRunController } from "./agent-run-controller.js";
8
8
  import * as Sentry from "@sentry/node";
9
9
  import { join } from "path";
10
10
  import { getUnresolvedSandboxPathContext } from "../agent.js";
@@ -14,20 +14,20 @@ function runtimeCwdForSandbox(sandbox, hostWorkspaceRoot, conversationId) {
14
14
  const runtimeWorkspaceRoot = getUnresolvedSandboxPathContext(sandbox, hostWorkspaceRoot).runtimeWorkspaceRoot;
15
15
  return `${runtimeWorkspaceRoot.replace(/\/+$/, "")}/${conversationId}`;
16
16
  }
17
- export function createSessionRuntime(options) {
18
- return new MikanSessionRuntime(options);
17
+ export function createConversationRuntime(options) {
18
+ return new ConversationRuntimeImpl(options);
19
19
  }
20
- class MikanSessionRuntime {
20
+ class ConversationRuntimeImpl {
21
21
  constructor(options) {
22
22
  this.options = options;
23
23
  this.conversationStates = new Map();
24
24
  this.sessionQueues = new Map();
25
25
  this.inFlightRuns = new Set();
26
- this.chatSessionManager = new ChatSessionManager();
26
+ this.chatSessionManager = new AgentMemoryFileManager();
27
27
  this.isShuttingDown = false;
28
28
  const commandServices = { ...options, runtime: this };
29
29
  const commandHandlers = options.commandHandlers ?? defaultCommandHandlers();
30
- this.orchestrator = new ConversationOrchestrator({
30
+ this.orchestrator = new AgentRunController({
31
31
  workingDir: options.workingDir,
32
32
  commandHandlers,
33
33
  commandServices,
@@ -101,10 +101,10 @@ class MikanSessionRuntime {
101
101
  log.logInfo(`[${conversationId}] Session reset: ${sessionKey}`);
102
102
  await bot.postMessage(conversationId, "Conversation reset. Send a new message to start fresh.");
103
103
  }
104
- async handleEvent(event, bot, adapters) {
104
+ async handleEvent(event, bot, context) {
105
105
  const sessionKey = event.sessionKey ?? `${event.conversationId}:${event.thread_ts ?? event.ts}`;
106
106
  const previous = this.sessionQueues.get(sessionKey) ?? Promise.resolve();
107
- const next = previous.catch(() => { }).then(() => this.runSession({ event, bot, adapters }));
107
+ const next = previous.catch(() => { }).then(() => this.runSession({ event, bot, context }));
108
108
  this.sessionQueues.set(sessionKey, next);
109
109
  try {
110
110
  await next;
@@ -115,8 +115,8 @@ class MikanSessionRuntime {
115
115
  }
116
116
  }
117
117
  }
118
- async runSession({ event, bot, adapters }) {
119
- await this.orchestrator.runSession({ event, bot, adapters });
118
+ async runSession({ event, bot, context }) {
119
+ await this.orchestrator.runSession({ event, bot, context });
120
120
  }
121
121
  async createSessionSandbox(options) {
122
122
  const state = await this.getOrCreateState(options);
@@ -219,4 +219,4 @@ class MikanSessionRuntime {
219
219
  }
220
220
  }
221
221
  }
222
- //# sourceMappingURL=session-runtime.js.map
222
+ //# sourceMappingURL=conversation-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-runtime.js","sourceRoot":"","sources":["../../src/runtime/conversation-runtime.ts"],"names":[],"mappings":"AAMA,OAAO,EAAuB,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EACL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAiC,MAAM,2BAA2B,CAAC;AAC9F,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAiB9D,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,MAAM,eAAe,GAAG,SAAS,CAAC;AAElC,SAAS,oBAAoB,CAC3B,OAA8C,EAC9C,iBAAyB,EACzB,cAAsB;IAEtB,MAAM,oBAAoB,GAAG,+BAA+B,CAC1D,OAAO,EACP,iBAAiB,CAClB,CAAC,oBAAoB,CAAC;IACvB,OAAO,GAAG,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,cAAc,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAAmC;IAEnC,OAAO,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,uBAAuB;IAQ3B,YAA6B,OAAmC;QAAnC,YAAO,GAAP,OAAO,CAA4B;QAP/C,uBAAkB,GAAG,IAAI,GAAG,EAA6B,CAAC;QAC1D,kBAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;QACjD,iBAAY,GAAG,IAAI,GAAG,EAAiB,CAAC;QAExC,uBAAkB,GAAG,IAAI,sBAAsB,EAAE,CAAC;QAC3D,mBAAc,GAAG,KAAK,CAAC;QAG7B,MAAM,eAAe,GAAoB,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACvE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,sBAAsB,EAAE,CAAC;QAC5E,IAAI,CAAC,YAAY,GAAG,IAAI,kBAAkB,CAAC;YACzC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,eAAe;YACf,eAAe;YACf,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc;YACzC,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC;YACjE,gBAAgB,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;YACzE,sBAAsB,EAAE,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE,CAC1D,0BAA0B,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC;YAC7D,gBAAgB,EAAE,CAAC,UAAU,EAAE,EAAE;gBAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAClC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACxE,CAAC;YACD,eAAe,EAAE,CAAC,UAAU,EAAE,EAAE;gBAC9B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACvC,CAAC;YACD,aAAa,EAAE,GAAG,EAAE;gBAClB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBAC1E,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,UAAkB;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC;IAC1B,CAAC;IAED,kBAAkB;QAChB,MAAM,QAAQ,GAAqB,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1D,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACrC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;gBAClD,QAAQ,CAAC,IAAI,CAAC;oBACZ,UAAU;oBACV,SAAS,EAAE,KAAK,CAAC,SAAS;oBAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;oBACpC,WAAW,EAAE,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,QAAQ;iBACzD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAAkB,EAAE,cAAsB,EAAE,GAAiB;QAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YACnB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,cAAc,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;YACtE,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC,WAAW,CAAC,cAAc,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,SAAS,CAAC,UAAkB;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YACnB,GAAG,CAAC,OAAO,CAAC,wCAAwC,UAAU,EAAE,CAAC,CAAC;YAClE,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACrB,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,UAAkB,EAClB,cAAsB,EACtB,GAAiB;QAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC;YACnB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;YAC3B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,oBAAoB,CACrC,IAAI,CAAC,OAAO,CAAC,OAAO,EACpB,IAAI,CAAC,OAAO,CAAC,UAAU,EACvB,cAAc,CACf,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QAEvF,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE3C,GAAG,CAAC,OAAO,CAAC,IAAI,cAAc,oBAAoB,UAAU,EAAE,CAAC,CAAC;QAChE,MAAM,GAAG,CAAC,WAAW,CAAC,cAAc,EAAE,wDAAwD,CAAC,CAAC;IAClG,CAAC;IAED,KAAK,CAAC,WAAW,CACf,KAAwB,EACxB,GAAiB,EACjB,OAA4B;QAE5B,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QAChG,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACzE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;gBAChD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAqB;QACzD,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,OAAoC;QAC7D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED,uBAAuB,CAAC,cAAsB,EAAE,SAAiB,EAAE,MAAc;QAC/E,OAAO,IAAI,CAAC,uBAAuB,CACjC,cAAc,EACd,IAAI,cAAc,kDAAkD,CACrE,CAAC;IACJ,CAAC;IAED,8BAA8B,CAAC,cAAsB;QACnD,OAAO,IAAI,CAAC,uBAAuB,CACjC,cAAc,EACd,IAAI,cAAc,yDAAyD,CAC5E,CAAC;IACJ,CAAC;IAEO,qBAAqB,CAAC,UAAkB,EAAE,cAAsB;QACtE,OAAO,UAAU,KAAK,cAAc,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC;IACtF,CAAC;IAEO,uBAAuB,CAAC,cAAsB,EAAE,OAAe;QACrE,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1D,IAAI,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,cAAc,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC5E,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,IAAI,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC;gBAC3D,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,OAAoE;QAEpE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC;QACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,QAAQ,EAAE,OAAO;YAAE,OAAO,QAAQ,CAAC;QAEvC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,oBAAoB,CACrC,IAAI,CAAC,OAAO,CAAC,OAAO,EACpB,IAAI,CAAC,OAAO,CAAC,UAAU,EACvB,cAAc,CACf,CAAC;QACF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC;YACrE,eAAe;YACf,UAAU;YACV,GAAG,EAAE,UAAU;YACf,gBAAgB;YAChB,qBAAqB,EAAE,OAAO,CAAC,gBAAgB,KAAK,QAAQ,IAAI,UAAU,KAAK,cAAc;SAC9F,CAAC,CAAC;QAEH,IAAI,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,YAAY,CAAC,WAAW,EAAE,CAAC;YAClE,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACrC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAsB;YAC/B,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,MAAM,YAAY,CACxB,IAAI,CAAC,OAAO,CAAC,OAAO,EACpB,UAAU,EACV,cAAc,EACd,eAAe,EACf,IAAI,CAAC,OAAO,CAAC,UAAU,EACvB,YAAY,EACZ,IAAI,CAAC,OAAO,CAAC,YAAY,EACzB,IAAI,CAAC,OAAO,CAAC,WAAW,EACxB;gBACE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB;gBAC9C,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;aAC1C,CACF;YACD,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;YAC1B,WAAW,EAAE,YAAY,CAAC,WAAW;YACrC,SAAS,EAAE,CAAC;SACb,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAS,GAAG,MAAM;QAC/B,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAChC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACvC,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAC1D,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,UAAU,CAAC,qBAAqB,IAAI,CAAC,YAAY,CAAC,IAAI,yBAAyB,CAAC,CAAC;YACrF,qBAAqB,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,EAAE;gBAC5E,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,+BAA+B;gBAC1C,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE;aAC7D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,GAAG,KAAK,CAAC,cAAc,GAAG,eAAe,EAAE,CAAC;gBACnE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,YAAY,EAAE,CAAC;YAChD,MAAM,YAAY,GAAmD,EAAE,CAAC;YACxE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACnD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBACnB,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;YAEjE,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5D,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["import type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n RunningSession,\n} from \"../adapter.js\";\nimport { type PiAgentWrapper, createRunner } from \"../agent.js\";\nimport { defaultCommandHandlers } from \"../commands/registry.js\";\nimport type { CommandServices } from \"../commands/types.js\";\nimport * as log from \"../log.js\";\nimport { reportUserFacingError } from \"../observability/sentry.js\";\nimport {\n AgentMemoryFileManager,\n hasMaterializedChatSession,\n} from \"../sessions/agent-memory-file-manager.js\";\nimport { formatNothingRunning, formatStopping } from \"../platform-messages.js\";\nimport { AgentRunController, type ConversationRuntimeState } from \"./agent-run-controller.js\";\nimport * as Sentry from \"@sentry/node\";\nimport { join } from \"path\";\nimport { getUnresolvedSandboxPathContext } from \"../agent.js\";\n\ntype ConversationState = ConversationRuntimeState;\n\nexport type {\n CreateSessionSandboxOptions,\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n} from \"./types.js\";\nimport type {\n CreateSessionSandboxOptions,\n RunSessionOptions,\n ConversationRuntime,\n ConversationRuntimeOptions,\n} from \"./types.js\";\n\nconst MAX_SESSIONS = 500;\nconst IDLE_TIMEOUT_MS = 3_600_000;\n\nfunction runtimeCwdForSandbox(\n sandbox: ConversationRuntimeOptions[\"sandbox\"],\n hostWorkspaceRoot: string,\n conversationId: string,\n): string {\n const runtimeWorkspaceRoot = getUnresolvedSandboxPathContext(\n sandbox,\n hostWorkspaceRoot,\n ).runtimeWorkspaceRoot;\n return `${runtimeWorkspaceRoot.replace(/\\/+$/, \"\")}/${conversationId}`;\n}\n\nexport function createConversationRuntime(\n options: ConversationRuntimeOptions,\n): ConversationRuntime {\n return new ConversationRuntimeImpl(options);\n}\n\nclass ConversationRuntimeImpl implements ConversationRuntime {\n private readonly conversationStates = new Map<string, ConversationState>();\n private readonly sessionQueues = new Map<string, Promise<void>>();\n private readonly inFlightRuns = new Set<Promise<void>>();\n private readonly orchestrator: AgentRunController;\n private readonly chatSessionManager = new AgentMemoryFileManager();\n private isShuttingDown = false;\n\n constructor(private readonly options: ConversationRuntimeOptions) {\n const commandServices: CommandServices = { ...options, runtime: this };\n const commandHandlers = options.commandHandlers ?? defaultCommandHandlers();\n this.orchestrator = new AgentRunController({\n workingDir: options.workingDir,\n commandHandlers,\n commandServices,\n isShuttingDown: () => this.isShuttingDown,\n getState: (sessionKey) => this.conversationStates.get(sessionKey),\n getOrCreateState: (createOptions) => this.getOrCreateState(createOptions),\n hasMaterializedSession: ({ conversationDir, sessionKey }) =>\n hasMaterializedChatSession({ conversationDir, sessionKey }),\n beforeRunTracked: (runPromise) => {\n this.inFlightRuns.add(runPromise);\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size);\n },\n afterRunTracked: (runPromise) => {\n this.inFlightRuns.delete(runPromise);\n },\n onRunFinished: () => {\n Sentry.metrics.gauge(\"agent.sessions.active\", this.inFlightRuns.size - 1);\n this.evictIdleSessions();\n },\n });\n }\n\n isRunning(sessionKey: string): boolean {\n const state = this.conversationStates.get(sessionKey);\n return !!state?.running;\n }\n\n getRunningSessions(): RunningSession[] {\n const sessions: RunningSession[] = [];\n for (const [sessionKey, state] of this.conversationStates) {\n if (state.running && state.startedAt) {\n const currentStep = state.runner.getCurrentStep();\n sessions.push({\n 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(sessionKey: string, conversationId: string, bot: MessagingBot): Promise<void> {\n const state = this.conversationStates.get(sessionKey);\n if (state?.running) {\n state.stopRequested = true;\n state.runner.abort();\n const ts = await bot.postMessage(conversationId, formatStopping(bot));\n state.stopMessageTs = ts;\n } else {\n await bot.postMessage(conversationId, formatNothingRunning(bot));\n }\n }\n\n forceStop(sessionKey: string): void {\n const state = this.conversationStates.get(sessionKey);\n if (state?.running) {\n log.logInfo(`[Force Stop] Force stopping session: ${sessionKey}`);\n state.stopRequested = true;\n state.runner.abort();\n state.running = false;\n }\n }\n\n async handleNewCommand(\n sessionKey: string,\n conversationId: string,\n bot: MessagingBot,\n ): Promise<void> {\n const state = this.conversationStates.get(sessionKey);\n if (state?.running) {\n state.stopRequested = true;\n state.runner.abort();\n }\n\n const conversationDir = join(this.options.workingDir, conversationId);\n const runtimeCwd = runtimeCwdForSandbox(\n this.options.sandbox,\n this.options.workingDir,\n conversationId,\n );\n this.chatSessionManager.resetSession({ conversationDir, sessionKey, cwd: runtimeCwd });\n\n this.conversationStates.delete(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 = event.sessionKey ?? `${event.conversationId}:${event.thread_ts ?? event.ts}`;\n const previous = this.sessionQueues.get(sessionKey) ?? Promise.resolve();\n const next = previous.catch(() => {}).then(() => this.runSession({ event, bot, context }));\n this.sessionQueues.set(sessionKey, next);\n try {\n await next;\n } finally {\n if (this.sessionQueues.get(sessionKey) === next) {\n this.sessionQueues.delete(sessionKey);\n }\n }\n }\n\n async runSession({ event, bot, context }: RunSessionOptions): Promise<void> {\n await this.orchestrator.runSession({ event, bot, context });\n }\n\n async createSessionSandbox(options: CreateSessionSandboxOptions): Promise<PiAgentWrapper> {\n const state = await this.getOrCreateState(options);\n return state.runner;\n }\n\n switchConversationModel(conversationId: string, _provider: string, _model: string): boolean {\n return this.clearConversationStates(\n conversationId,\n `[${conversationId}] Model switched; cleared cached session runners`,\n );\n }\n\n refreshConversationEnvironment(conversationId: string): boolean {\n return this.clearConversationStates(\n conversationId,\n `[${conversationId}] Environment refreshed; cleared cached session runners`,\n );\n }\n\n private isConversationSession(sessionKey: string, conversationId: string): boolean {\n return sessionKey === conversationId || sessionKey.startsWith(`${conversationId}:`);\n }\n\n private clearConversationStates(conversationId: string, message: string): boolean {\n for (const [sessionKey, state] of this.conversationStates) {\n if (this.isConversationSession(sessionKey, conversationId) && state.running) {\n return false;\n }\n }\n\n for (const sessionKey of Array.from(this.conversationStates.keys())) {\n if (this.isConversationSession(sessionKey, conversationId)) {\n this.conversationStates.delete(sessionKey);\n }\n }\n log.logInfo(message);\n return true;\n }\n\n private async getOrCreateState(\n options: CreateSessionSandboxOptions & { currentMessageId?: string },\n ): Promise<ConversationState> {\n const { conversationId, sessionKey, currentMessageId } = options;\n const existing = this.conversationStates.get(sessionKey);\n if (existing?.running) return existing;\n\n const conversationDir = join(this.options.workingDir, conversationId);\n const runtimeCwd = runtimeCwdForSandbox(\n this.options.sandbox,\n this.options.workingDir,\n conversationId,\n );\n const sessionScope = await this.chatSessionManager.resolveSessionScope({\n conversationDir,\n sessionKey,\n cwd: runtimeCwd,\n currentMessageId,\n rotateTopLevelSession: options.conversationKind === \"shared\" && sessionKey === conversationId,\n });\n\n if (existing && existing.sessionFile === sessionScope.contextFile) {\n existing.lastAccessedAt = Date.now();\n return existing;\n }\n\n const state: ConversationState = {\n running: false,\n runner: await createRunner(\n this.options.sandbox,\n sessionKey,\n conversationId,\n conversationDir,\n this.options.workingDir,\n sessionScope,\n this.options.vaultManager,\n this.options.provisioner,\n {\n tokenStore: this.options.sessionViewTokenStore,\n portalBaseUrl: this.options.portalBaseUrl,\n },\n ),\n stopRequested: false,\n lastAccessedAt: Date.now(),\n sessionFile: sessionScope.contextFile,\n startedAt: 0,\n };\n this.conversationStates.set(sessionKey, 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 private evictIdleSessions(): void {\n const now = Date.now();\n\n for (const [key, state] of this.conversationStates) {\n if (!state.running && now - state.lastAccessedAt > IDLE_TIMEOUT_MS) {\n this.conversationStates.delete(key);\n }\n }\n\n if (this.conversationStates.size > MAX_SESSIONS) {\n const idleSessions: Array<{ key: string; lastAccessedAt: number }> = [];\n for (const [key, state] of this.conversationStates) {\n if (!state.running) {\n idleSessions.push({ key, lastAccessedAt: state.lastAccessedAt });\n }\n }\n\n idleSessions.sort((a, b) => a.lastAccessedAt - b.lastAccessedAt);\n\n const toEvict = this.conversationStates.size - MAX_SESSIONS;\n for (let i = 0; i < toEvict && i < idleSessions.length; i++) {\n this.conversationStates.delete(idleSessions[i].key);\n }\n }\n }\n}\n"]}
@@ -1,9 +1,9 @@
1
- import type { AgentRunner } from "../agent.js";
2
- import type { Bot, BotAdapters, BotEvent, BotHandler, ConversationKind } from "../adapter.js";
1
+ import type { PiAgentWrapper } from "../agent.js";
2
+ import type { MessagingBot, ConversationContext, ConversationEvent, MessagingEventHandler, ConversationKind } from "../adapter.js";
3
3
  import type { CommandServices } from "../commands/types.js";
4
4
  export interface ConversationRuntimeState {
5
5
  running: boolean;
6
- runner: AgentRunner;
6
+ runner: PiAgentWrapper;
7
7
  stopRequested: boolean;
8
8
  stopMessageTs?: string;
9
9
  lastAccessedAt: number;
@@ -13,23 +13,23 @@ export interface ConversationRuntimeState {
13
13
  lastActivityAt?: number;
14
14
  }
15
15
  export interface RunSessionOptions {
16
- event: BotEvent;
17
- bot: Bot;
18
- adapters: BotAdapters;
16
+ event: ConversationEvent;
17
+ bot: MessagingBot;
18
+ context: ConversationContext;
19
19
  }
20
20
  export interface CreateSessionSandboxOptions {
21
21
  conversationId: string;
22
22
  sessionKey: string;
23
23
  conversationKind?: ConversationKind;
24
24
  }
25
- export interface SessionRuntimeOptions extends Omit<CommandServices, "runtime"> {
25
+ export interface ConversationRuntimeOptions extends Omit<CommandServices, "runtime"> {
26
26
  /** Override the default command handlers (e.g., to add /help, /status). */
27
27
  commandHandlers?: readonly CommandHandler[];
28
28
  }
29
29
  import type { CommandHandler } from "../commands/types.js";
30
- export interface SessionRuntime extends BotHandler {
30
+ export interface ConversationRuntime extends MessagingEventHandler {
31
31
  runSession(options: RunSessionOptions): Promise<void>;
32
- createSessionSandbox(options: CreateSessionSandboxOptions): Promise<AgentRunner>;
32
+ createSessionSandbox(options: CreateSessionSandboxOptions): Promise<PiAgentWrapper>;
33
33
  switchConversationModel(conversationId: string, provider: string, model: string): boolean;
34
34
  refreshConversationEnvironment(conversationId: string): boolean;
35
35
  shutdown(timeoutMs?: number): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAC7E,2EAA2E;IAC3E,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7C;AAED,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACjF,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1F,8BAA8B,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C","sourcesContent":["import type { AgentRunner } from \"../agent.js\";\nimport type { Bot, BotAdapters, BotEvent, BotHandler, ConversationKind } from \"../adapter.js\";\nimport type { CommandServices } from \"../commands/types.js\";\n\nexport interface ConversationRuntimeState {\n running: boolean;\n runner: AgentRunner;\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: BotEvent;\n bot: Bot;\n adapters: BotAdapters;\n}\n\nexport interface CreateSessionSandboxOptions {\n conversationId: string;\n sessionKey: string;\n conversationKind?: ConversationKind;\n}\n\nexport interface SessionRuntimeOptions extends Omit<CommandServices, \"runtime\"> {\n /** Override the default command handlers (e.g., to add /help, /status). */\n commandHandlers?: readonly CommandHandler[];\n}\n\nimport type { CommandHandler } from \"../commands/types.js\";\n\nexport interface SessionRuntime extends BotHandler {\n runSession(options: RunSessionOptions): Promise<void>;\n createSessionSandbox(options: CreateSessionSandboxOptions): Promise<AgentRunner>;\n switchConversationModel(conversationId: string, provider: string, model: string): boolean;\n refreshConversationEnvironment(conversationId: string): boolean;\n shutdown(timeoutMs?: number): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,YAAY,CAAC;IAClB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IAClF,2EAA2E;IAC3E,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7C;AAED,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpF,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1F,8BAA8B,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentRunner } from \"../agent.js\";\nimport type { Bot, BotAdapters, BotEvent, BotHandler, ConversationKind } from \"../adapter.js\";\nimport type { CommandServices } from \"../commands/types.js\";\n\nexport interface ConversationRuntimeState {\n running: boolean;\n runner: AgentRunner;\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: BotEvent;\n bot: Bot;\n adapters: BotAdapters;\n}\n\nexport interface CreateSessionSandboxOptions {\n conversationId: string;\n sessionKey: string;\n conversationKind?: ConversationKind;\n}\n\nexport interface SessionRuntimeOptions extends Omit<CommandServices, \"runtime\"> {\n /** Override the default command handlers (e.g., to add /help, /status). */\n commandHandlers?: readonly CommandHandler[];\n}\n\nimport type { CommandHandler } from \"../commands/types.js\";\n\nexport interface SessionRuntime extends BotHandler {\n runSession(options: RunSessionOptions): Promise<void>;\n createSessionSandbox(options: CreateSessionSandboxOptions): Promise<AgentRunner>;\n switchConversationModel(conversationId: string, provider: string, model: string): boolean;\n refreshConversationEnvironment(conversationId: string): boolean;\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} from \"../adapter.js\";\nimport type { CommandServices } from \"../commands/types.js\";\n\nexport interface ConversationRuntimeState {\n running: boolean;\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\nexport interface CreateSessionSandboxOptions {\n conversationId: string;\n sessionKey: string;\n conversationKind?: ConversationKind;\n}\n\nexport interface ConversationRuntimeOptions extends Omit<CommandServices, \"runtime\"> {\n /** Override the default command handlers (e.g., to add /help, /status). */\n commandHandlers?: readonly CommandHandler[];\n}\n\nimport type { CommandHandler } from \"../commands/types.js\";\n\nexport interface ConversationRuntime extends MessagingEventHandler {\n runSession(options: RunSessionOptions): Promise<void>;\n createSessionSandbox(options: CreateSessionSandboxOptions): Promise<PiAgentWrapper>;\n switchConversationModel(conversationId: string, provider: string, model: string): boolean;\n refreshConversationEnvironment(conversationId: string): boolean;\n shutdown(timeoutMs?: number): Promise<void>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/sandbox/cloudflare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA4DpB,qBAAa,yBAA0B,YAAW,QAAQ;IAItD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IAJvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YACmB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAC7C,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAGnC;IAEK,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAiEtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAK5D;IAED,gBAAgB,IAAI,uBAAuB,CAE1C;CACF;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,uBAAuB,CAM5E,CAAC","sourcesContent":["import type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { readEnv } from \"../utils/env.js\";\nimport { SandboxError } from \"./errors.js\";\n\nconst DEFAULT_CLOUDFLARE_CWD = \"/workspace\";\n\ninterface CloudflareExecPayload {\n sandboxId: string;\n command: string;\n timeoutSeconds?: number;\n cwd?: string;\n env?: Record<string, string>;\n}\n\ninterface CloudflareExecResponse {\n stdout?: string;\n stderr?: string;\n code?: number;\n error?: string;\n}\n\nfunction parseCloudflareSandboxArg(value: string): CloudflareSandboxConfig | undefined {\n if (!value.startsWith(\"cloudflare:\")) {\n return undefined;\n }\n\n const sandboxId = value.slice(\"cloudflare:\".length).trim();\n if (!sandboxId) {\n throw new SandboxError(\n \"Error: cloudflare sandbox requires sandbox id (e.g., cloudflare:slack-u123)\",\n );\n }\n\n return { type: \"cloudflare\", sandboxId };\n}\n\nasync function validateCloudflareSandbox(_config: CloudflareSandboxConfig): Promise<void> {\n const url = resolveCloudflareSandboxUrl();\n try {\n const response = await fetch(new URL(\"/health\", url), {\n headers: buildCloudflareHeaders(),\n });\n if (!response.ok) {\n throw new SandboxError(\n `Error: Cloudflare sandbox bridge health check failed with HTTP ${response.status}`,\n );\n }\n } catch (error) {\n if (error instanceof SandboxError) {\n throw error;\n }\n const detail = error instanceof Error ? error.message : String(error);\n throw new SandboxError(`Error: Cloudflare sandbox bridge is not reachable: ${detail}`);\n }\n\n console.log(\n ` Cloudflare sandbox bridge enabled. Base URL: ${url.toString().replace(/\\/$/, \"\")}`,\n );\n}\n\nexport class CloudflareSandboxExecutor implements Executor {\n private readonly cwd: string;\n\n constructor(\n private readonly sandboxId: string,\n private readonly env?: Record<string, string>,\n _ensureReady?: () => Promise<void>,\n ) {\n this.cwd = readEnv(\"CLOUDFLARE_SANDBOX_CWD\") || DEFAULT_CLOUDFLARE_CWD;\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n const controller = new AbortController();\n const timeoutHandle =\n options?.timeout && options.timeout > 0\n ? setTimeout(() => controller.abort(), options.timeout * 1000)\n : undefined;\n\n const onAbort = () => controller.abort();\n if (options?.signal) {\n if (options.signal.aborted) {\n controller.abort();\n } else {\n options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n try {\n const payload: CloudflareExecPayload = {\n sandboxId: this.sandboxId,\n command,\n cwd: this.cwd,\n };\n if (options?.timeout) payload.timeoutSeconds = options.timeout;\n if (this.env && Object.keys(this.env).length > 0) payload.env = this.env;\n\n const response = await fetch(new URL(\"/exec\", resolveCloudflareSandboxUrl()), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n ...buildCloudflareHeaders(),\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n const raw = (await response.text()).trim();\n const parsed = raw ? (JSON.parse(raw) as CloudflareExecResponse) : {};\n\n if (!response.ok) {\n throw new Error(\n parsed.error ||\n parsed.stderr ||\n `Cloudflare sandbox bridge returned HTTP ${response.status}`,\n );\n }\n\n return {\n stdout: parsed.stdout || \"\",\n stderr: parsed.stderr || \"\",\n code: parsed.code ?? 0,\n };\n } catch (error) {\n if (controller.signal.aborted) {\n if (options?.signal?.aborted) {\n throw new Error(\"Command aborted\", { cause: error });\n }\n throw new Error(`Command timed out after ${options?.timeout} seconds`, { cause: error });\n }\n throw error;\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n }\n }\n\n getWorkspacePath(_hostPath: string): string {\n return this.cwd;\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return {\n hostWorkspaceRoot,\n runtimeWorkspaceRoot: this.cwd,\n };\n }\n\n getSandboxConfig(): CloudflareSandboxConfig {\n return { type: \"cloudflare\", sandboxId: this.sandboxId };\n }\n}\n\nexport const cloudflareSandboxAdapter: SandboxAdapter<CloudflareSandboxConfig> = {\n type: \"cloudflare\",\n parse: parseCloudflareSandboxArg,\n validate: validateCloudflareSandbox,\n createExecutor: (config, env, ensureReady) =>\n new CloudflareSandboxExecutor(config.sandboxId, env, ensureReady),\n};\n\nfunction resolveCloudflareSandboxUrl(): URL {\n const raw = readEnv(\"CLOUDFLARE_SANDBOX_URL\");\n if (!raw) {\n throw new SandboxError(\n \"Error: CLOUDFLARE_SANDBOX_URL or MIKAN_CLOUDFLARE_SANDBOX_URL is required for cloudflare sandbox mode\",\n );\n }\n\n try {\n return new URL(raw);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new SandboxError(`Error: invalid CLOUDFLARE_SANDBOX_URL: ${detail}`);\n }\n}\n\nfunction buildCloudflareHeaders(): Record<string, string> {\n const token = readEnv(\"CLOUDFLARE_SANDBOX_TOKEN\");\n return token ? { authorization: `Bearer ${token}` } : {};\n}\n"]}
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/sandbox/cloudflare.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA4DpB,qBAAa,yBAA0B,YAAW,QAAQ;IAItD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IAJvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YACmB,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAC7C,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAGnC;IAEK,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAiEtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAK5D;IAED,gBAAgB,IAAI,uBAAuB,CAE1C;CACF;AAED,eAAO,MAAM,wBAAwB,EAAE,cAAc,CAAC,uBAAuB,CAM5E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/sandbox/container.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA8EpB,qBAAa,iBAAkB,YAAW,QAAQ;IAE9C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG,CAAC;IACZ,OAAO,CAAC,WAAW,CAAC;IAHtB,YACU,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAC5B,WAAW,CAAC,GAAE,MAAM,OAAO,CAAC,IAAI,CAAC,aAAA,EACvC;IAEE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,sBAAsB,CAEzC;CACF;AAED,eAAO,MAAM,uBAAuB,EAAE,cAAc,CAAC,sBAAsB,CAM1E,CAAC","sourcesContent":["import { chmodSync, mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {\n ContainerSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { execSimple, shellEscape } from \"./utils.js\";\nimport { HostExecutor } from \"./host.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\n\nconst PRIVATE_DIR_MODE = 0o700;\nconst PRIVATE_FILE_MODE = 0o600;\n\nfunction parseContainerSandboxArg(value: string): ContainerSandboxConfig | undefined {\n if (!value.startsWith(\"container:\")) {\n return undefined;\n }\n\n const container = value.slice(\"container:\".length);\n if (!container) {\n throw new SandboxError(\n \"Error: container sandbox requires container name (e.g., container:mikan-sandbox)\",\n );\n }\n return { type: \"container\", container };\n}\n\nasync function validateContainerSandbox(config: ContainerSandboxConfig): Promise<void> {\n try {\n await execSimple(\"docker\", [\"--version\"]);\n } catch {\n throw new SandboxError(\"Error: Docker is not installed or not in PATH\");\n }\n\n try {\n const result = await execSimple(\"docker\", [\n \"inspect\",\n \"-f\",\n \"{{.State.Running}}\",\n config.container,\n ]);\n if (result.trim() !== \"true\") {\n throw new SandboxError(`Error: Container '${config.container}' is not running.`, [\n `Start it with: docker start ${config.container}`,\n ]);\n }\n } catch (error) {\n if (error instanceof SandboxError) {\n throw error;\n }\n throw new SandboxError(`Error: Container '${config.container}' does not exist.`, [\n `Create it with: docker run -d --name ${config.container} -v <workspace>:/workspace alpine:latest sleep infinity`,\n ]);\n }\n\n console.log(` Container '${config.container}' is running.`);\n}\n\nfunction buildContainerExecCommand(\n container: string,\n command: string,\n envFilePath?: string,\n): string {\n const envPart = envFilePath ? `--env-file ${shellEscape(envFilePath)} ` : \"\";\n return `docker exec ${envPart}-w /workspace ${container} sh -c ${shellEscape(command)}`;\n}\n\nfunction withRuntimeBootstrap(command: string, env?: Record<string, string>): string {\n if (!hasGitHubToken(env)) {\n return command;\n }\n\n return [\n \"if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then gh auth setup-git >/dev/null 2>&1 || true; fi\",\n command,\n ].join(\"\\n\");\n}\n\nfunction hasGitHubToken(env?: Record<string, string>): boolean {\n return Boolean(env?.GH_TOKEN || env?.GITHUB_TOKEN || env?.GITHUB_OAUTH_ACCESS_TOKEN);\n}\n\nexport class ContainerExecutor implements Executor {\n constructor(\n private container: string,\n private env?: Record<string, string>,\n private ensureReady?: () => Promise<void>,\n ) {}\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n if (this.ensureReady) {\n await this.ensureReady();\n } else {\n await ensureContainerRunning(this.container);\n }\n\n const hostExecutor = new HostExecutor();\n const temp = this.env ? createSecureEnvFile(this.env) : undefined;\n try {\n const dockerCmd = buildContainerExecCommand(\n this.container,\n withRuntimeBootstrap(command, this.env),\n temp?.envFilePath,\n );\n return await hostExecutor.exec(dockerCmd, options);\n } finally {\n temp?.cleanup();\n }\n }\n\n getWorkspacePath(_hostPath: string): string {\n return \"/workspace\";\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, \"/workspace\");\n }\n\n getSandboxConfig(): ContainerSandboxConfig {\n return { type: \"container\", container: this.container };\n }\n}\n\nexport const containerSandboxAdapter: SandboxAdapter<ContainerSandboxConfig> = {\n type: \"container\",\n parse: parseContainerSandboxArg,\n validate: validateContainerSandbox,\n createExecutor: (config, env, ensureReady) =>\n new ContainerExecutor(config.container, env, ensureReady),\n};\n\nasync function ensureContainerRunning(container: string): Promise<void> {\n try {\n const running = await execSimple(\"docker\", [\"inspect\", \"-f\", \"{{.State.Running}}\", container]);\n if (running.trim() === \"true\") {\n return;\n }\n await execSimple(\"docker\", [\"start\", container]);\n } catch (error) {\n const details = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Container \"${container}\" is not available. ` +\n `Expected a pre-existing container or image provisioning to keep it running.\\n${details}`.trim(),\n { cause: error },\n );\n }\n}\n\nfunction createSecureEnvFile(env: Record<string, string>): {\n envFilePath: string;\n cleanup: () => void;\n} {\n const tempDir = mkdtempSync(join(tmpdir(), \"mikan-docker-env-\"));\n chmodSync(tempDir, PRIVATE_DIR_MODE);\n const envFilePath = join(tempDir, \"env.list\");\n const content =\n Object.entries(env)\n .map(([key, value]) => `${key}=${value.replace(/\\r?\\n/g, \"\")}`)\n .join(\"\\n\") + \"\\n\";\n writeFileSync(envFilePath, content, { encoding: \"utf-8\", mode: PRIVATE_FILE_MODE });\n chmodSync(envFilePath, PRIVATE_FILE_MODE);\n\n return {\n envFilePath,\n cleanup: () => {\n rmSync(tempDir, { recursive: true, force: true });\n },\n };\n}\n"]}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../src/sandbox/container.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA8EpB,qBAAa,iBAAkB,YAAW,QAAQ;IAE9C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG,CAAC;IACZ,OAAO,CAAC,WAAW,CAAC;IAHtB,YACU,SAAS,EAAE,MAAM,EACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAC5B,WAAW,CAAC,GAAE,MAAM,OAAO,CAAC,IAAI,CAAC,aAAA,EACvC;IAEE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,sBAAsB,CAEzC;CACF;AAED,eAAO,MAAM,uBAAuB,EAAE,cAAc,CAAC,sBAAsB,CAM1E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/sandbox/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAE3B,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,EAI9C;IAED,YAAY,IAAI,MAAM,EAAE,CAEvB;CACF","sourcesContent":["export class SandboxError extends Error {\n readonly details: string[];\n\n constructor(message: string, details?: string[]) {\n super(message);\n this.name = \"SandboxError\";\n this.details = details ?? [];\n }\n\n formatForCli(): string[] {\n return [this.message, ...this.details];\n }\n}\n"]}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/sandbox/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAE3B,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,EAI9C;IAED,YAAY,IAAI,MAAM,EAAE,CAEvB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"firecracker.d.ts","sourceRoot":"","sources":["../../src/sandbox/firecracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,wBAAwB,EACxB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAoFpB,qBAAa,mBAAoB,YAAW,QAAQ;IAEhD,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,GAAG,CAAC;IALd,YACU,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAe,EACxB,OAAO,GAAE,MAAW,EACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAClC;IAEE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAqGtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAK5D;IAED,gBAAgB,IAAI,wBAAwB,CAQ3C;CACF;AAgBD,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,wBAAwB,CAM9E,CAAC","sourcesContent":["import { spawn } from \"child_process\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n FirecrackerSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { HostExecutor } from \"./host.js\";\nimport { execSimple, killProcessTree, shellEscape } from \"./utils.js\";\n\nfunction parseFirecrackerSandboxArg(value: string): FirecrackerSandboxConfig | undefined {\n if (!value.startsWith(\"firecracker:\")) {\n return undefined;\n }\n\n const arg = value.slice(\"firecracker:\".length);\n // Format: firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]\n // Example: firecracker:vm1:/home/user/workspace\n // firecracker:vm1:/home/user/workspace:root\n // firecracker:vm1:/home/user/workspace:root:22\n const parts = arg.split(\":\");\n if (parts.length < 2) {\n throw new SandboxError(\n \"Error: firecracker sandbox requires vm-id and host-path\\n\" +\n \"Usage: firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]\\n\" +\n \"Example: firecracker:vm1:/home/user/workspace\",\n );\n }\n const vmId = parts[0];\n const hostPath = parts[1];\n const sshUser = parts[2] || \"root\";\n const sshPort = parts[3] ? parseInt(parts[3], 10) : 22;\n\n if (!vmId || !hostPath) {\n throw new SandboxError(\"Error: firecracker sandbox requires vm-id and host-path\");\n }\n if (isNaN(sshPort) || sshPort <= 0 || sshPort > 65535) {\n throw new SandboxError(\"Error: invalid SSH port\");\n }\n return { type: \"firecracker\", vmId, hostPath, sshUser, sshPort };\n}\n\nasync function validateFirecrackerSandbox(config: FirecrackerSandboxConfig): Promise<void> {\n // Check if fc-agent or firecracker CLI is available\n try {\n await execSimple(\"fc-agent\", [\"--version\"]);\n } catch {\n // Try alternative: firecracker\n try {\n await execSimple(\"firecracker\", [\"--version\"]);\n } catch {\n throw new SandboxError(\n \"Error: Firecracker tools (fc-agent or firecracker) not found in PATH\",\n [\"Install firecracker: https://github.com/firecracker-microvm/firecracker\"],\n );\n }\n }\n\n // Check if VM is running using fc-agent\n try {\n const result = await execSimple(\"fc-agent\", [\"status\", config.vmId]);\n if (!result.includes(\"running\") && !result.includes(\"Running\")) {\n throw new SandboxError(`Error: Firecracker VM '${config.vmId}' is not running.`, [\n `Start it with: fc-agent start ${config.vmId}`,\n ]);\n }\n } catch (error) {\n if (error instanceof SandboxError) {\n throw error;\n }\n // Try alternative: firecracker-ctl or direct check\n try {\n await execSimple(\"firecracker-ctl\", [\"status\", config.vmId]);\n } catch {\n console.error(`Warning: Could not verify if VM '${config.vmId}' is running.`);\n console.error(\"Make sure the VM is started before running mikan.\");\n }\n }\n\n // Verify host path exists\n try {\n await execSimple(\"ls\", [\"-d\", config.hostPath]);\n } catch {\n throw new SandboxError(`Error: Host path '${config.hostPath}' does not exist.`);\n }\n\n console.log(` Firecracker VM '${config.vmId}' configured with workspace '${config.hostPath}'.`);\n}\n\nexport class FirecrackerExecutor implements Executor {\n constructor(\n private vmId: string,\n private hostPath: string,\n private sshUser: string = \"root\",\n private sshPort: number = 22,\n private env?: Record<string, string>,\n ) {}\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n if (!this.env || Object.keys(this.env).length === 0) {\n const sshCmd =\n this.sshPort === 22\n ? `ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 ${this.sshUser}@${this.vmId} sh -c ${shellEscape(command)}`\n : `ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -p ${this.sshPort} ${this.sshUser}@${this.vmId} sh -c ${shellEscape(command)}`;\n const hostExecutor = new HostExecutor();\n return hostExecutor.exec(sshCmd, options);\n }\n\n return new Promise((resolve, reject) => {\n const sshArgs = [\"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"ConnectTimeout=10\"];\n if (this.sshPort !== 22) {\n sshArgs.push(\"-p\", String(this.sshPort));\n }\n sshArgs.push(`${this.sshUser}@${this.vmId}`, \"sh\", \"-se\");\n\n const child = spawn(\"ssh\", sshArgs, {\n detached: true,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n let settled = false;\n\n const timeoutHandle =\n options?.timeout && options.timeout > 0\n ? setTimeout(() => {\n timedOut = true;\n if (child.pid) killProcessTree(child.pid);\n }, options.timeout * 1000)\n : undefined;\n\n const onAbort = () => {\n if (child.pid) killProcessTree(child.pid);\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n onAbort();\n } else {\n options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n child.on(\"error\", (error) => {\n if (settled) return;\n settled = true;\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n reject(error);\n });\n\n child.stdout?.on(\"data\", (data) => {\n stdout += data.toString();\n if (stdout.length > 10 * 1024 * 1024) {\n stdout = stdout.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.stderr?.on(\"data\", (data) => {\n stderr += data.toString();\n if (stderr.length > 10 * 1024 * 1024) {\n stderr = stderr.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.stdin?.on(\"error\", (error) => {\n stderr += `${error.message}\\n`;\n });\n child.stdin?.end(buildRemoteScript(command, this.env));\n\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n\n if (options?.signal?.aborted) {\n reject(new Error(`${stdout}\\n${stderr}\\nCommand aborted`.trim()));\n return;\n }\n\n if (timedOut) {\n reject(\n new Error(\n `${stdout}\\n${stderr}\\nCommand timed out after ${options?.timeout} seconds`.trim(),\n ),\n );\n return;\n }\n\n resolve({ stdout, stderr, code: code ?? 0 });\n });\n });\n }\n\n getWorkspacePath(_hostPath: string): string {\n return \"/workspace\";\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return {\n hostWorkspaceRoot,\n runtimeWorkspaceRoot: \"/workspace\",\n };\n }\n\n getSandboxConfig(): FirecrackerSandboxConfig {\n return {\n type: \"firecracker\",\n vmId: this.vmId,\n hostPath: this.hostPath,\n sshUser: this.sshUser,\n sshPort: this.sshPort,\n };\n }\n}\n\nfunction buildRemoteScript(command: string, env?: Record<string, string>): string {\n const exports = env\n ? Object.entries(env)\n .map(([key, value]) => {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n throw new SandboxError(`Invalid environment variable name for firecracker: ${key}`);\n }\n return `export ${key}=${shellEscape(value)}`;\n })\n .join(\"\\n\") + \"\\n\"\n : \"\";\n return `${exports}${command}\\n`;\n}\n\nexport const firecrackerSandboxAdapter: SandboxAdapter<FirecrackerSandboxConfig> = {\n type: \"firecracker\",\n parse: parseFirecrackerSandboxArg,\n validate: validateFirecrackerSandbox,\n createExecutor: (config, env) =>\n new FirecrackerExecutor(config.vmId, config.hostPath, config.sshUser, config.sshPort, env),\n};\n"]}
1
+ {"version":3,"file":"firecracker.d.ts","sourceRoot":"","sources":["../../src/sandbox/firecracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,wBAAwB,EACxB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAoFpB,qBAAa,mBAAoB,YAAW,QAAQ;IAEhD,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,GAAG,CAAC;IALd,YACU,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAe,EACxB,OAAO,GAAE,MAAW,EACpB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAClC;IAEE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAqGtE;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1C;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAK5D;IAED,gBAAgB,IAAI,wBAAwB,CAQ3C;CACF;AAgBD,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,wBAAwB,CAM9E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAepB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAED,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzC;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,iBAAiB,CAEpC;CACF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CAKhE,CAAC","sourcesContent":["import { spawn } from \"child_process\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n HostSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { killProcessTree } from \"./utils.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\n\nfunction parseHostSandboxArg(value: string): HostSandboxConfig | undefined {\n if (value === \"host\") {\n return { type: \"host\" };\n }\n return undefined;\n}\n\nasync function validateHostSandbox(_config: HostSandboxConfig): Promise<void> {\n return;\n}\n\nexport class HostExecutor implements Executor {\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const shell = process.platform === \"win32\" ? \"cmd\" : \"sh\";\n const shellArgs = process.platform === \"win32\" ? [\"/c\"] : [\"-c\"];\n\n const child = spawn(shell, [...shellArgs, command], {\n detached: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n\n const timeoutHandle =\n options?.timeout && options.timeout > 0\n ? setTimeout(() => {\n timedOut = true;\n killProcessTree(child.pid!);\n }, options.timeout * 1000)\n : undefined;\n\n const onAbort = () => {\n if (child.pid) killProcessTree(child.pid);\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n onAbort();\n } else {\n options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n child.stdout?.on(\"data\", (data) => {\n stdout += data.toString();\n if (stdout.length > 10 * 1024 * 1024) {\n stdout = stdout.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.stderr?.on(\"data\", (data) => {\n stderr += data.toString();\n if (stderr.length > 10 * 1024 * 1024) {\n stderr = stderr.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.on(\"close\", (code) => {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n\n if (options?.signal?.aborted) {\n reject(new Error(`${stdout}\\n${stderr}\\nCommand aborted`.trim()));\n return;\n }\n\n if (timedOut) {\n reject(\n new Error(\n `${stdout}\\n${stderr}\\nCommand timed out after ${options?.timeout} seconds`.trim(),\n ),\n );\n return;\n }\n\n resolve({ stdout, stderr, code: code ?? 0 });\n });\n });\n }\n\n getWorkspacePath(hostPath: string): string {\n return hostPath;\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, hostWorkspaceRoot);\n }\n\n getSandboxConfig(): HostSandboxConfig {\n return { type: \"host\" };\n }\n}\n\nexport const hostSandboxAdapter: SandboxAdapter<HostSandboxConfig> = {\n type: \"host\",\n parse: parseHostSandboxArg,\n validate: validateHostSandbox,\n createExecutor: () => new HostExecutor(),\n};\n"]}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAepB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAED,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzC;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,iBAAiB,CAEpC;CACF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CAKhE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/sandbox/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBrE,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,kBAAkB,CAOlE,CAAC","sourcesContent":["import type { ImageSandboxConfig, SandboxAdapter } from \"./types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { execSimple } from \"./utils.js\";\n\nfunction parseImageSandboxArg(value: string): ImageSandboxConfig | undefined {\n if (!value.startsWith(\"image:\")) {\n return undefined;\n }\n\n const image = value.slice(\"image:\".length);\n if (!image) {\n throw new SandboxError(\"Error: image sandbox requires image name (e.g., image:ubuntu:24.04)\");\n }\n return { type: \"image\", image };\n}\n\nasync function validateImageSandbox(config: ImageSandboxConfig): Promise<void> {\n try {\n await execSimple(\"docker\", [\"--version\"]);\n } catch {\n throw new SandboxError(\"Error: Docker is not installed or not in PATH\");\n }\n console.log(` Image auto-provisioning enabled. Image: ${config.image}`);\n}\n\nexport const imageSandboxAdapter: SandboxAdapter<ImageSandboxConfig> = {\n type: \"image\",\n parse: parseImageSandboxArg,\n validate: validateImageSandbox,\n createExecutor: () => {\n throw new SandboxError(\"Error: image sandbox must resolve to a concrete container executor\");\n },\n};\n"]}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/sandbox/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBrE,eAAO,MAAM,mBAAmB,EAAE,cAAc,CAAC,kBAAkB,CAOlE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAA6B,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAA4B,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAsB,MAAM,WAAW,CAAC;AAG7D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1E,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,QAAA,MAAM,eAAe,sTAMX,CAAC;AAKX,wBAAgB,kBAAkB,IAAI,SAAS,CAAC,GAAG,OAAO,eAAe,CAAC,CAEzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiB5D;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAO1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,QAAQ,CAMV","sourcesContent":["import { ContainerExecutor, containerSandboxAdapter } from \"./container.js\";\nimport { FirecrackerExecutor, firecrackerSandboxAdapter } from \"./firecracker.js\";\nimport { CloudflareSandboxExecutor, cloudflareSandboxAdapter } from \"./cloudflare.js\";\nimport { HostExecutor, hostSandboxAdapter } from \"./host.js\";\nimport { imageSandboxAdapter } from \"./image.js\";\nimport { SandboxError } from \"./errors.js\";\nimport type { Executor, SandboxAdapter, SandboxConfig } from \"./types.js\";\n\nexport type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n RuntimePathContext,\n SandboxAdapter,\n SandboxConfig,\n} from \"./types.js\";\nexport { CloudflareSandboxExecutor, ContainerExecutor, FirecrackerExecutor, HostExecutor };\nexport { SandboxError } from \"./errors.js\";\n\nconst sandboxAdapters = [\n hostSandboxAdapter,\n containerSandboxAdapter,\n imageSandboxAdapter,\n firecrackerSandboxAdapter,\n cloudflareSandboxAdapter,\n] as const;\nconst sandboxAdapterByType = new Map(\n sandboxAdapters.map((adapter) => [adapter.type, adapter]),\n) as Map<SandboxConfig[\"type\"], SandboxAdapter>;\n\nexport function getSandboxAdapters(): readonly [...typeof sandboxAdapters] {\n return sandboxAdapters;\n}\n\nexport function parseSandboxArg(value: string): SandboxConfig {\n for (const adapter of sandboxAdapters) {\n const config = adapter.parse(value);\n if (config) {\n return config;\n }\n }\n\n if (value.startsWith(\"docker:\")) {\n throw new SandboxError(\n `Error: '${value}' is not supported. Use 'container:<container-name>' for the shared-container mode or 'image:<image-name>' for mikan-managed per-user containers.`,\n );\n }\n\n throw new SandboxError(\n `Error: Invalid sandbox type '${value}'. Use 'host', 'container:<container-name>', 'image:<image-name>', 'firecracker:<vm-id>:<host-path>', or 'cloudflare:<sandbox-id>'`,\n );\n}\n\nexport async function validateSandbox(config: SandboxConfig): Promise<void> {\n const adapter = sandboxAdapterByType.get(config.type);\n if (!adapter) {\n throw new SandboxError(`Error: Unsupported sandbox type '${config.type}'`);\n }\n\n await adapter.validate(config);\n}\n\n/**\n * Create an executor that runs commands on host, in Docker, in a Firecracker VM, or through a Cloudflare sandbox bridge.\n */\nexport function createExecutor(\n config: SandboxConfig,\n env?: Record<string, string>,\n ensureReady?: () => Promise<void>,\n): Executor {\n const adapter = sandboxAdapterByType.get(config.type);\n if (!adapter) {\n throw new SandboxError(`Error: Unsupported sandbox type '${config.type}'`);\n }\n return adapter.createExecutor(config, env, ensureReady);\n}\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sandbox/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA2B,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAA6B,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAA4B,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAsB,MAAM,WAAW,CAAC;AAG7D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1E,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,QAAA,MAAM,eAAe,sTAMX,CAAC;AAKX,wBAAgB,kBAAkB,IAAI,SAAS,CAAC,GAAG,OAAO,eAAe,CAAC,CAEzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiB5D;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAO1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,QAAQ,CAMV"}
@@ -1 +1 @@
1
- {"version":3,"file":"path-context.d.ts","sourceRoot":"","sources":["../../src/sandbox/path-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,MAAM,EACzB,oBAAoB,EAAE,MAAM,GAC3B,kBAAkB,CAOpB","sourcesContent":["import { join } from \"node:path\";\nimport type { RuntimePathContext } from \"./types.js\";\n\nexport function createMountedRuntimePathContext(\n hostWorkspaceRoot: string,\n runtimeWorkspaceRoot: string,\n): RuntimePathContext {\n return {\n hostWorkspaceRoot,\n runtimeWorkspaceRoot,\n runtimeToHostPath: (runtimePath) =>\n translateMountedRuntimePathToHost(runtimePath, runtimeWorkspaceRoot, hostWorkspaceRoot),\n };\n}\n\nfunction translateMountedRuntimePathToHost(\n runtimePath: string,\n runtimeWorkspaceRoot: string,\n hostWorkspaceRoot: string,\n): string {\n const runtimeRoot = runtimeWorkspaceRoot.replace(/\\/+$/, \"\");\n if (runtimePath === runtimeRoot) {\n return hostWorkspaceRoot;\n }\n\n const workspacePrefix = `${runtimeRoot}/`;\n if (runtimePath.startsWith(workspacePrefix)) {\n return join(hostWorkspaceRoot, runtimePath.slice(workspacePrefix.length));\n }\n\n return runtimePath;\n}\n"]}
1
+ {"version":3,"file":"path-context.d.ts","sourceRoot":"","sources":["../../src/sandbox/path-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,MAAM,EACzB,oBAAoB,EAAE,MAAM,GAC3B,kBAAkB,CAOpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,GAClB,wBAAwB,GACxB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAElE;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAE3C;;OAEG;IACH,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAE9D;;OAEG;IACH,gBAAgB,IAAI,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;CACrD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa;IAC3E,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,cAAc,CACZ,MAAM,EAAE,OAAO,EACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,QAAQ,CAAC;CACb","sourcesContent":["export type SandboxConfig =\n | HostSandboxConfig\n | ContainerSandboxConfig\n | ImageSandboxConfig\n | FirecrackerSandboxConfig\n | CloudflareSandboxConfig;\n\nexport interface HostSandboxConfig {\n type: \"host\";\n}\n\nexport interface ContainerSandboxConfig {\n type: \"container\";\n container: string;\n}\n\nexport interface ImageSandboxConfig {\n type: \"image\";\n image: string;\n}\n\nexport interface FirecrackerSandboxConfig {\n type: \"firecracker\";\n vmId: string;\n hostPath: string;\n sshUser?: string;\n sshPort?: number;\n}\n\nexport interface CloudflareSandboxConfig {\n type: \"cloudflare\";\n sandboxId: string;\n}\n\nexport interface Executor {\n /**\n * Execute a bash command.\n */\n exec(command: string, options?: ExecOptions): Promise<ExecResult>;\n\n /**\n * Get the workspace path prefix for this executor.\n * Host: returns the actual path.\n * Container/Firecracker: returns /workspace.\n */\n getWorkspacePath(hostPath: string): string;\n\n /**\n * Return explicit host/control-plane/runtime path semantics for this executor.\n */\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext;\n\n /**\n * Get the current sandbox config used by this executor.\n */\n getSandboxConfig(): SandboxConfig;\n}\n\nexport interface RuntimePathContext {\n /** Host-side workspace root used by mikan's control plane. */\n hostWorkspaceRoot: string;\n /** Workspace root as seen by bash/read/write/edit inside the runtime. */\n runtimeWorkspaceRoot: string;\n /** Translate a runtime path back to a host path when the runtime is host-backed. */\n runtimeToHostPath?: (runtimePath: string) => string;\n}\n\nexport interface ExecOptions {\n timeout?: number;\n signal?: AbortSignal;\n}\n\nexport interface ExecResult {\n stdout: string;\n stderr: string;\n code: number;\n}\n\nexport interface SandboxAdapter<TConfig extends SandboxConfig = SandboxConfig> {\n type: TConfig[\"type\"];\n parse(value: string): TConfig | undefined;\n validate(config: TConfig): Promise<void>;\n createExecutor(\n config: TConfig,\n env?: Record<string, string>,\n ensureReady?: () => Promise<void>,\n ): Executor;\n}\n"]}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,sBAAsB,GACtB,kBAAkB,GAClB,wBAAwB,GACxB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAElE;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAE3C;;OAEG;IACH,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAE9D;;OAEG;IACH,gBAAgB,IAAI,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;CACrD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa;IAC3E,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,cAAc,CACZ,MAAM,EAAE,OAAO,EACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,QAAQ,CAAC;CACb"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/sandbox/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBvE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAqBjD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG7C","sourcesContent":["import { spawn } from \"child_process\";\n\nexport function execSimple(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.on(\"data\", (d) => {\n stdout += d;\n });\n child.stderr?.on(\"data\", (d) => {\n stderr += d;\n });\n child.on(\"close\", (code) => {\n if (code === 0) resolve(stdout);\n else reject(new Error(stderr || `Exit code ${code}`));\n });\n });\n}\n\nexport function killProcessTree(pid: number): void {\n if (process.platform === \"win32\") {\n try {\n spawn(\"taskkill\", [\"/F\", \"/T\", \"/PID\", String(pid)], {\n stdio: \"ignore\",\n detached: true,\n });\n } catch {\n // Ignore errors\n }\n } else {\n try {\n process.kill(-pid, \"SIGKILL\");\n } catch {\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // Process already dead\n }\n }\n }\n}\n\nexport function shellEscape(s: string): string {\n // Escape for passing to sh -c\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n"]}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/sandbox/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBvE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAqBjD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG7C"}
@@ -1,19 +1,19 @@
1
1
  import { type ResolvedSessionScope } from "./store.js";
2
- export type { ChatSessionManagerOptions, HasMaterializedSessionOptions, RegisterThreadSessionOptions, ResetChatSessionOptions, ResolveChatSessionScopeOptions, SyncChatSessionManagerOptions, ThreadBootstrapWaitOptions, } from "./types.js";
3
- import type { ChatSessionManagerOptions, HasMaterializedSessionOptions, RegisterThreadSessionOptions, ResetChatSessionOptions, ResolveChatSessionScopeOptions, SyncChatSessionManagerOptions, ThreadBootstrapWaitOptions } from "./types.js";
2
+ export type { AgentMemoryFileManagerOptions, HasMaterializedSessionOptions, RegisterThreadSessionOptions, ResetChatSessionOptions, ResolveChatSessionScopeOptions, SyncAgentMemoryFileManagerOptions, ThreadBootstrapWaitOptions, } from "./types.js";
3
+ import type { AgentMemoryFileManagerOptions, HasMaterializedSessionOptions, RegisterThreadSessionOptions, ResetChatSessionOptions, ResolveChatSessionScopeOptions, SyncAgentMemoryFileManagerOptions, ThreadBootstrapWaitOptions } from "./types.js";
4
4
  export declare function hasMaterializedChatSession(options: HasMaterializedSessionOptions): boolean;
5
5
  export declare function registerThreadSession(options: RegisterThreadSessionOptions): string | null;
6
6
  export declare function waitForThreadSessionBootstrap(options: ThreadBootstrapWaitOptions): Promise<boolean>;
7
- export declare class ChatSessionManager {
7
+ export declare class AgentMemoryFileManager {
8
8
  private readonly recentDays;
9
9
  private readonly maxTopLevelMessages;
10
10
  private readonly now;
11
- constructor(options?: ChatSessionManagerOptions);
11
+ constructor(options?: AgentMemoryFileManagerOptions);
12
12
  resolveSessionScope(options: ResolveChatSessionScopeOptions): Promise<ResolvedSessionScope>;
13
- syncSessionManager(options: SyncChatSessionManagerOptions): void;
13
+ syncSessionManager(options: SyncAgentMemoryFileManagerOptions): void;
14
14
  resetSession(options: ResetChatSessionOptions): string;
15
15
  private resolveTopLevelSessionFile;
16
16
  private historyWindow;
17
17
  private resolveThreadSessionScope;
18
18
  }
19
- //# sourceMappingURL=chat-session-manager.d.ts.map
19
+ //# sourceMappingURL=agent-memory-file-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-memory-file-manager.d.ts","sourceRoot":"","sources":["../../src/sessions/agent-memory-file-manager.ts"],"names":[],"mappings":"AAQA,OAAO,EAUL,KAAK,oBAAoB,EAE1B,MAAM,YAAY,CAAC;AAepB,YAAY,EACV,6BAA6B,EAC7B,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,8BAA8B,EAC9B,iCAAiC,EACjC,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACV,6BAA6B,EAC7B,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,8BAA8B,EAC9B,iCAAiC,EACjC,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAEpB,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAQ1F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,MAAM,GAAG,IAAI,CAQ1F;AAED,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IAEjC,YAAY,OAAO,GAAE,6BAAkC,EAItD;IAEK,mBAAmB,CACvB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,oBAAoB,CAAC,CAsB/B;IAED,kBAAkB,CAAC,OAAO,EAAE,iCAAiC,GAAG,IAAI,CAUnE;IAED,YAAY,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAUrD;IAED,OAAO,CAAC,0BAA0B;IA6ClC,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,yBAAyB;CA8ClC"}