@geminixiang/mikan 1.0.0-beta.21 → 1.0.0-beta.22

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 (112) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/adapters/intake.d.ts.map +1 -1
  3. package/dist/adapters/intake.js +5 -0
  4. package/dist/adapters/intake.js.map +1 -1
  5. package/dist/adapters/slack/bot.d.ts.map +1 -1
  6. package/dist/adapters/slack/bot.js +13 -2
  7. package/dist/adapters/slack/bot.js.map +1 -1
  8. package/dist/adapters/slack/types.d.ts +2 -0
  9. package/dist/adapters/slack/types.d.ts.map +1 -1
  10. package/dist/adapters/slack/types.js.map +1 -1
  11. package/dist/agent.d.ts.map +1 -1
  12. package/dist/agent.js +26 -15
  13. package/dist/agent.js.map +1 -1
  14. package/dist/commands/login.js +2 -2
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/sandbox.js +2 -2
  17. package/dist/commands/sandbox.js.map +1 -1
  18. package/dist/execution-resolver.d.ts +5 -6
  19. package/dist/execution-resolver.d.ts.map +1 -1
  20. package/dist/execution-resolver.js +72 -103
  21. package/dist/execution-resolver.js.map +1 -1
  22. package/dist/harness/index.d.ts +1 -1
  23. package/dist/harness/index.d.ts.map +1 -1
  24. package/dist/harness/index.js.map +1 -1
  25. package/dist/harness/runner.d.ts +4 -0
  26. package/dist/harness/runner.d.ts.map +1 -1
  27. package/dist/harness/runner.js +16 -2
  28. package/dist/harness/runner.js.map +1 -1
  29. package/dist/harness/subagent-runner.d.ts +14 -13
  30. package/dist/harness/subagent-runner.d.ts.map +1 -1
  31. package/dist/harness/subagent-runner.js +105 -19
  32. package/dist/harness/subagent-runner.js.map +1 -1
  33. package/dist/harness/types.d.ts +11 -0
  34. package/dist/harness/types.d.ts.map +1 -1
  35. package/dist/harness/types.js.map +1 -1
  36. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  37. package/dist/runtime/conversation-runtime.js +23 -79
  38. package/dist/runtime/conversation-runtime.js.map +1 -1
  39. package/dist/runtime/session-lifecycle.d.ts +19 -0
  40. package/dist/runtime/session-lifecycle.d.ts.map +1 -0
  41. package/dist/runtime/session-lifecycle.js +76 -0
  42. package/dist/runtime/session-lifecycle.js.map +1 -0
  43. package/dist/runtime/types.d.ts +5 -0
  44. package/dist/runtime/types.d.ts.map +1 -1
  45. package/dist/runtime/types.js.map +1 -1
  46. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  47. package/dist/sandbox/cloudflare.js +1 -0
  48. package/dist/sandbox/cloudflare.js.map +1 -1
  49. package/dist/sandbox/container.d.ts.map +1 -1
  50. package/dist/sandbox/container.js +1 -0
  51. package/dist/sandbox/container.js.map +1 -1
  52. package/dist/sandbox/firecracker.d.ts.map +1 -1
  53. package/dist/sandbox/firecracker.js +1 -0
  54. package/dist/sandbox/firecracker.js.map +1 -1
  55. package/dist/sandbox/gondolin.d.ts.map +1 -1
  56. package/dist/sandbox/gondolin.js +1 -0
  57. package/dist/sandbox/gondolin.js.map +1 -1
  58. package/dist/sandbox/host.d.ts.map +1 -1
  59. package/dist/sandbox/host.js +1 -0
  60. package/dist/sandbox/host.js.map +1 -1
  61. package/dist/sandbox/identity.d.ts +11 -16
  62. package/dist/sandbox/identity.d.ts.map +1 -1
  63. package/dist/sandbox/identity.js +32 -26
  64. package/dist/sandbox/identity.js.map +1 -1
  65. package/dist/sandbox/image.d.ts.map +1 -1
  66. package/dist/sandbox/image.js +1 -0
  67. package/dist/sandbox/image.js.map +1 -1
  68. package/dist/sandbox/index.d.ts +1 -0
  69. package/dist/sandbox/index.d.ts.map +1 -1
  70. package/dist/sandbox/index.js +6 -0
  71. package/dist/sandbox/index.js.map +1 -1
  72. package/dist/sandbox/types.d.ts +5 -0
  73. package/dist/sandbox/types.d.ts.map +1 -1
  74. package/dist/sandbox/types.js.map +1 -1
  75. package/dist/sessions/session-key.d.ts +9 -0
  76. package/dist/sessions/session-key.d.ts.map +1 -1
  77. package/dist/sessions/session-key.js +50 -2
  78. package/dist/sessions/session-key.js.map +1 -1
  79. package/dist/sessions/store.d.ts.map +1 -1
  80. package/dist/sessions/store.js +36 -8
  81. package/dist/sessions/store.js.map +1 -1
  82. package/dist/tools/sandbox.js +2 -2
  83. package/dist/tools/sandbox.js.map +1 -1
  84. package/dist/tools/subagent-slots.d.ts +3 -3
  85. package/dist/tools/subagent-slots.d.ts.map +1 -1
  86. package/dist/tools/subagent-slots.js +25 -10
  87. package/dist/tools/subagent-slots.js.map +1 -1
  88. package/dist/tools/subagent.d.ts +13 -2
  89. package/dist/tools/subagent.d.ts.map +1 -1
  90. package/dist/tools/subagent.js +16 -16
  91. package/dist/tools/subagent.js.map +1 -1
  92. package/dist/types.d.ts +7 -0
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js.map +1 -1
  95. package/dist/vault/injection.d.ts +4 -14
  96. package/dist/vault/injection.d.ts.map +1 -1
  97. package/dist/vault/injection.js +5 -2
  98. package/dist/vault/injection.js.map +1 -1
  99. package/dist/vault/types.d.ts +4 -0
  100. package/dist/vault/types.d.ts.map +1 -1
  101. package/dist/vault/types.js.map +1 -1
  102. package/dist/web/admin/portal.js +2 -2
  103. package/dist/web/admin/portal.js.map +1 -1
  104. package/dist/workspace-projection/index.d.ts +5 -0
  105. package/dist/workspace-projection/index.d.ts.map +1 -0
  106. package/dist/workspace-projection/index.js +71 -0
  107. package/dist/workspace-projection/index.js.map +1 -0
  108. package/dist/workspace-projection/types.d.ts +7 -0
  109. package/dist/workspace-projection/types.d.ts.map +1 -0
  110. package/dist/workspace-projection/types.js +2 -0
  111. package/dist/workspace-projection/types.js.map +1 -0
  112. package/package.json +1 -1
@@ -124,6 +124,7 @@ export class CloudflareSandboxExecutor {
124
124
  }
125
125
  export const cloudflareSandboxAdapter = {
126
126
  type: "cloudflare",
127
+ credentials: { env: true, fileMounts: false },
127
128
  parse: parseCloudflareSandboxArg,
128
129
  validate: validateCloudflareSandbox,
129
130
  createExecutor: (config, env, ensureReady) => new CloudflareSandboxExecutor(config.sandboxId, env, ensureReady),
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/sandbox/cloudflare.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { execReadFile, execReadFileBase64, execWriteFile } from \"./utils.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 readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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.js","sourceRoot":"","sources":["../../src/sandbox/cloudflare.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { execReadFile, execReadFileBase64, execWriteFile } from \"./utils.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 readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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 credentials: { env: true, fileMounts: false },\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 +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;AAqEpB,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAS1F;AAMD,qBAAa,iBAAkB,YAAW,QAAQ;IAI9C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG,CAAC;IACZ,OAAO,CAAC,WAAW,CAAC;IALtB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,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,CAkBtE;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D;IAED,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;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
+ {"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;AAqEpB,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAS1F;AAMD,qBAAa,iBAAkB,YAAW,QAAQ;IAI9C,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG,CAAC;IACZ,OAAO,CAAC,WAAW,CAAC;IALtB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,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,CAkBtE;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D;IAED,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;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,CAO1E,CAAC"}
@@ -107,6 +107,7 @@ export class ContainerExecutor {
107
107
  }
108
108
  export const containerSandboxAdapter = {
109
109
  type: "container",
110
+ credentials: { env: true, fileMounts: false },
110
111
  parse: parseContainerSandboxArg,
111
112
  validate: validateContainerSandbox,
112
113
  createExecutor: (config, env, ensureReady) => new ContainerExecutor(config.container, env, ensureReady),
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/sandbox/container.ts"],"names":[],"mappings":"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","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 {\n execReadFile,\n execReadFileBase64,\n execSimple,\n execWriteFile,\n shellEscape,\n} 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\nexport function 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 private readonly hostExecutor = new HostExecutor();\n\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 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 this.hostExecutor.exec(dockerCmd, options);\n } finally {\n temp?.cleanup();\n }\n }\n\n readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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.js","sourceRoot":"","sources":["../../src/sandbox/container.ts"],"names":[],"mappings":"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","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 {\n execReadFile,\n execReadFileBase64,\n execSimple,\n execWriteFile,\n shellEscape,\n} 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\nexport function 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 private readonly hostExecutor = new HostExecutor();\n\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 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 this.hostExecutor.exec(dockerCmd, options);\n } finally {\n temp?.cleanup();\n }\n }\n\n readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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 credentials: { env: true, fileMounts: false },\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 +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;AA2FpB,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,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D;IAED,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;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
+ {"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;AA2FpB,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,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D;IAED,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;IAED,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;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,CAO9E,CAAC"}
@@ -214,6 +214,7 @@ function buildRemoteScript(command, env) {
214
214
  }
215
215
  export const firecrackerSandboxAdapter = {
216
216
  type: "firecracker",
217
+ credentials: { env: true, fileMounts: false },
217
218
  parse: parseFirecrackerSandboxArg,
218
219
  validate: validateFirecrackerSandbox,
219
220
  createExecutor: (config, env) => new FirecrackerExecutor(config.vmId, config.hostPath, config.sshUser, config.sshPort, env),
@@ -1 +1 @@
1
- {"version":3,"file":"firecracker.js","sourceRoot":"","sources":["../../src/sandbox/firecracker.ts"],"names":[],"mappings":"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","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 {\n execReadFile,\n execReadFileBase64,\n execWriteFile,\n execSimple,\n killProcessTree,\n shellEscape,\n} 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 readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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.js","sourceRoot":"","sources":["../../src/sandbox/firecracker.ts"],"names":[],"mappings":"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","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 {\n execReadFile,\n execReadFileBase64,\n execWriteFile,\n execSimple,\n killProcessTree,\n shellEscape,\n} 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 readFile(path: string, options?: ExecOptions): Promise<string> {\n return execReadFile(this, path, options);\n }\n\n readFileBase64(path: string, options?: ExecOptions): Promise<string> {\n return execReadFileBase64(this, path, options);\n }\n\n writeFile(path: string, content: string, options?: ExecOptions): Promise<void> {\n return execWriteFile(this, path, content, options);\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 credentials: { env: true, fileMounts: false },\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 +1 @@
1
- {"version":3,"file":"gondolin.d.ts","sourceRoot":"","sources":["../../src/sandbox/gondolin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAcjG,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA8BpB,cAAM,uBAAwB,YAAW,yBAAyB;IAChE,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqC;IAEpE,SAAS,CAAC,aAAa,CAAC,EAAE,cAAc,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI,CAK5E;IAEK,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAMpD;IAEK,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAIhF;IAED,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAE9C;IAED,gBAAgB,IAAI,cAAc,GAAG,SAAS,CAE7C;IAED,cAAc,IAAI,cAAc,GAAG,SAAS,CAE3C;IAED,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAGvB;IAED,OAAO,CAAC,eAAe;CAMxB;AAED,eAAO,MAAM,iBAAiB,yBAAgC,CAAC;AAsC/D;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAe7C;AAwQD,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB5F;AAED;;;;;GAKG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAQnE;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnE;AAWD,qBAAa,gBAAiB,YAAW,QAAQ;IAK7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IALvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,YACmB,MAAM,EAAE,qBAAqB,EAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAO9C;IAEK,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtE;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5C;IAEK,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElD;IAEK,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;IAED,gBAAgB,IAAI,MAAM,CAEzB;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,qBAAqB,CAExC;CACF;AAED,eAAO,MAAM,sBAAsB,EAAE,cAAc,CAAC,qBAAqB,CAKxE,CAAC"}
1
+ {"version":3,"file":"gondolin.d.ts","sourceRoot":"","sources":["../../src/sandbox/gondolin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAcjG,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AA8BpB,cAAM,uBAAwB,YAAW,yBAAyB;IAChE,OAAO,CAAC,aAAa,CAAC,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAC,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqC;IAEpE,SAAS,CAAC,aAAa,CAAC,EAAE,cAAc,EAAE,WAAW,CAAC,EAAE,cAAc,GAAG,IAAI,CAK5E;IAEK,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAMpD;IAEK,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAIhF;IAED,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAE9C;IAED,gBAAgB,IAAI,cAAc,GAAG,SAAS,CAE7C;IAED,cAAc,IAAI,cAAc,GAAG,SAAS,CAE3C;IAED,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAGvB;IAED,OAAO,CAAC,eAAe;CAMxB;AAED,eAAO,MAAM,iBAAiB,yBAAgC,CAAC;AAsC/D;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAe7C;AAwQD,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB5F;AAED;;;;;GAKG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAQnE;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnE;AAWD,qBAAa,gBAAiB,YAAW,QAAQ;IAK7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IALvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,YACmB,MAAM,EAAE,qBAAqB,EAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA,EAO9C;IAEK,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAOtE;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5C;IAEK,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElD;IAEK,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;IAED,gBAAgB,IAAI,MAAM,CAEzB;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,qBAAqB,CAExC;CACF;AAED,eAAO,MAAM,sBAAsB,EAAE,cAAc,CAAC,qBAAqB,CAMxE,CAAC"}
@@ -422,6 +422,7 @@ export class GondolinExecutor {
422
422
  }
423
423
  export const gondolinSandboxAdapter = {
424
424
  type: "gondolin",
425
+ credentials: { env: true, fileMounts: true },
425
426
  parse: parseGondolinSandboxArg,
426
427
  validate: validateGondolinSandbox,
427
428
  createExecutor: (config, env) => new GondolinExecutor(config, env),
@@ -1 +1 @@
1
- {"version":3,"file":"gondolin.js","sourceRoot":"","sources":["../../src/sandbox/gondolin.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport * as log from \"../log.js\";\nimport type { ResourceLimits, SandboxLimitStatus, SandboxResourceController } from \"../types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { gondolinInventory } from \"./gondolin-inventory.js\";\nimport { isRuntimeGone, isRuntimeInterrupted } from \"./gondolin-recovery.js\";\nimport {\n gondolinWorkers,\n type GondolinRuntimeHandle,\n type GondolinRuntimeTransport,\n} from \"./gondolin-worker-client.js\";\nimport { gondolinFleet } from \"./gondolin-fleet.js\";\nimport { gondolinGateway } from \"./gondolin-gateway.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\nimport { withRuntimeBootstrap } from \"./container.js\";\nimport { execReadFile, execReadFileBase64, execWriteFile } from \"./utils.js\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n GondolinSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\n\ntype GondolinModule = typeof import(\"@earendil-works/gondolin\");\n\ninterface GondolinSession {\n runtime: Promise<GondolinRuntimeHandle>;\n transport: GondolinRuntimeTransport;\n fingerprint: string;\n resourceKey?: string;\n activeOperations: number;\n lastUsed: number;\n idleWaiters: Array<() => void>;\n}\n\ninterface GondolinDesiredRuntime {\n image: string;\n imageIdentity: string;\n mounts: Array<{ source: string; target: string }>;\n /** Content identity of projected credential files (rotation → drift). */\n credentialIdentity: Record<string, string>;\n limits?: ResourceLimits;\n}\n\nconst MINIMUM_NODE_VERSION = [23, 6, 0] as const;\nconst MIKAN_IMAGE = \"mikan-sandbox:latest\";\nconst sessions = new Map<string, GondolinSession>();\nconst transitions = new Map<string, Promise<void>>();\nlet activeShutdowns = 0;\nlet shutdownGeneration = 0;\n\nclass GondolinResourceManager implements SandboxResourceController {\n private defaultLimits?: ResourceLimits;\n private boostLimits?: ResourceLimits;\n private readonly boostedKeys = new Set<string>();\n private readonly overrideLimits = new Map<string, ResourceLimits>();\n\n configure(defaultLimits?: ResourceLimits, boostLimits?: ResourceLimits): void {\n this.defaultLimits = defaultLimits;\n this.boostLimits = boostLimits;\n this.boostedKeys.clear();\n this.overrideLimits.clear();\n }\n\n async boost(key: string): Promise<SandboxLimitStatus> {\n if (this.boostLimits?.cpus || this.boostLimits?.memory) {\n this.overrideLimits.delete(key);\n this.boostedKeys.add(key);\n }\n return this.getLimitStatus(key);\n }\n\n async setLimits(key: string, limits: ResourceLimits): Promise<SandboxLimitStatus> {\n this.boostedKeys.delete(key);\n this.overrideLimits.set(key, { ...this.defaultLimits, ...limits });\n return this.getLimitStatus(key);\n }\n\n getLimitStatus(key: string): SandboxLimitStatus {\n return { limits: this.effectiveLimits(key), boosted: this.boostedKeys.has(key) };\n }\n\n getDefaultLimits(): ResourceLimits | undefined {\n return this.defaultLimits;\n }\n\n getBoostLimits(): ResourceLimits | undefined {\n return this.boostLimits;\n }\n\n clear(key: string): void {\n this.boostedKeys.delete(key);\n this.overrideLimits.delete(key);\n }\n\n private effectiveLimits(key: string): ResourceLimits | undefined {\n const override = this.overrideLimits.get(key);\n if (override) return override;\n if (!this.boostedKeys.has(key)) return this.defaultLimits;\n return { ...this.defaultLimits, ...this.boostLimits };\n }\n}\n\nexport const gondolinResources = new GondolinResourceManager();\n\nfunction parseGondolinSandboxArg(value: string): GondolinSandboxConfig | undefined {\n if (!value.startsWith(\"gondolin:\")) return undefined;\n\n const profile = value.slice(\"gondolin:\".length);\n if (!profile) {\n throw new SandboxError(\"Error: gondolin sandbox requires a profile (e.g., gondolin:default)\");\n }\n if (profile !== \"default\" && profile !== \"remote\") {\n throw new SandboxError(\n `Error: unsupported gondolin profile '${profile}'. Use 'gondolin:default' or 'gondolin:remote'`,\n );\n }\n return { type: \"gondolin\", profile };\n}\n\nfunction assertSupportedNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < MINIMUM_NODE_VERSION[0] || (major === MINIMUM_NODE_VERSION[0] && minor < 6)) {\n throw new SandboxError(\n `Error: gondolin:default requires Node.js >=23.6.0 (current: ${process.versions.node}). Other sandbox modes remain available on Node.js >=22.19.0.`,\n );\n }\n}\n\nasync function validateGondolinSandbox(config?: GondolinSandboxConfig): Promise<void> {\n if (config?.profile === \"remote\") {\n // The remote transports are configured from settings later in startup, so\n // \"is a worker source configured?\" is checked there (assertRemoteConfigured),\n // not here where nothing has been wired yet.\n console.log(\" Gondolin microVM enabled. Profile: remote\");\n return;\n }\n assertSupportedNodeVersion();\n console.log(\" Gondolin microVM enabled. Profile: default\");\n}\n\n/**\n * Fail fast when `gondolin:remote` is selected but no worker source is\n * configured. Call after the fleet and gateway have been configured.\n */\nexport function assertRemoteConfigured(): void {\n if (!gondolinFleet.isConfigured() && !gondolinGateway.isConfigured()) {\n throw new SandboxError(\n \"Error: gondolin:remote requires sandbox.gondolin.remote settings (workers[]/url, or gateway for dial-home workers)\",\n );\n }\n // Without a workspaceRoot, mount sources cannot be translated to the worker's\n // filesystem and every runtime is rejected with \"escapes the workspace root\".\n const missing = gondolinFleet.workersMissingWorkspaceRoot();\n if (missing.length > 0) {\n throw new SandboxError(\n `Error: gondolin:remote worker(s) [${missing.join(\", \")}] have no workspaceRoot; ` +\n `set sandbox.gondolin.remote.workspaceRoot (or gateway.workspaceRoot) to the worker-side shared workspace path`,\n );\n }\n}\n\nfunction transportFor(config: GondolinSandboxConfig): GondolinRuntimeTransport {\n return config.profile === \"remote\" ? gondolinFleet : gondolinWorkers;\n}\n\nasync function resolveDesiredRuntime(\n config: GondolinSandboxConfig,\n): Promise<GondolinDesiredRuntime> {\n let image: string;\n let imageIdentity: string;\n if (config.profile === \"remote\") {\n // image assets live on the worker host; the selector is the identity\n image = gondolinFleet.imageSelector() ?? config.image ?? MIKAN_IMAGE;\n imageIdentity = image;\n } else {\n const selector = config.image ?? MIKAN_IMAGE;\n const { ensureImageSelector } = (await import(\"@earendil-works/gondolin\")) as GondolinModule;\n const resolvedImage = await ensureImageSelector(selector);\n image = resolvedImage.assetDir;\n imageIdentity = resolvedImage.buildId ?? resolvedImage.assetDir;\n }\n const mounts = (\n config.mounts ?? [{ source: config.workspacePath ?? process.cwd(), target: \"/workspace\" }]\n ).toSorted((left, right) => left.target.localeCompare(right.target));\n return {\n image,\n imageIdentity,\n mounts,\n credentialIdentity: credentialIdentity(mounts),\n limits: config.resourceKey\n ? gondolinResources.getLimitStatus(config.resourceKey).limits\n : undefined,\n };\n}\n\n/**\n * Content hashes of credential file mounts (files projected outside\n * /workspace). Rotating a credential on the host changes the fingerprint, so\n * the next command recreates the runtime with a fresh projection instead of\n * serving the stale copy for the rest of the VM's life. Workspace files are\n * excluded: the guest writes them back, which would drift the runtime it runs\n * in.\n */\nfunction credentialIdentity(\n mounts: Array<{ source: string; target: string }>,\n): Record<string, string> {\n const identity: Record<string, string> = {};\n for (const mount of mounts) {\n if (mount.target.startsWith(\"/workspace/\") || mount.target === \"/workspace\") continue;\n try {\n if (!statSync(mount.source).isFile()) continue;\n identity[mount.target] = createHash(\"sha256\")\n .update(readFileSync(mount.source))\n .digest(\"hex\");\n } catch {\n // missing source: the worker skips it too, so it has no runtime identity\n }\n }\n return identity;\n}\n\nfunction runtimeFingerprint(desired: GondolinDesiredRuntime): string {\n return createHash(\"sha256\")\n .update(\n JSON.stringify({\n image: desired.imageIdentity,\n mounts: desired.mounts,\n credentials: desired.credentialIdentity,\n limits: desired.limits,\n }),\n )\n .digest(\"hex\");\n}\n\nfunction gondolinCpuCount(cpus: string | undefined): number | undefined {\n if (cpus === undefined) return undefined;\n const parsed = Number(cpus);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new SandboxError(`Error: invalid Gondolin CPU limit '${cpus}'`);\n }\n // ponytail: Gondolin exposes whole vCPUs; add host cgroup quotas if fractional enforcement matters.\n return Math.ceil(parsed);\n}\n\nfunction createSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n): GondolinSession {\n const transport = transportFor(config);\n let session: GondolinSession;\n const runtime = transport\n .ensure(key, {\n image: desired.image,\n mounts: desired.mounts,\n cpus: desired.limits?.cpus,\n vmCpus: gondolinCpuCount(desired.limits?.cpus),\n memory: desired.limits?.memory,\n fingerprint,\n workspacePath: config.workspacePath,\n })\n .catch((error) => {\n if (sessions.get(key) === session) sessions.delete(key);\n throw error;\n });\n session = {\n runtime,\n transport,\n fingerprint,\n resourceKey: config.resourceKey,\n activeOperations: 0,\n lastUsed: Date.now(),\n idleWaiters: [],\n };\n return session;\n}\n\nasync function acquireSession(\n key: string,\n config: GondolinSandboxConfig,\n generation = shutdownGeneration,\n): Promise<GondolinSession> {\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n\n const pending = transitions.get(key);\n if (pending) {\n await pending;\n return acquireSession(key, config, generation);\n }\n\n const desired = await resolveDesiredRuntime(config);\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n const concurrentTransition = transitions.get(key);\n if (concurrentTransition) {\n await concurrentTransition;\n return acquireSession(key, config, generation);\n }\n\n const fingerprint = runtimeFingerprint(desired);\n const existing = sessions.get(key);\n if (existing?.fingerprint === fingerprint) {\n existing.activeOperations += 1;\n return existing;\n }\n\n const transition = replaceSession(key, config, desired, fingerprint, existing);\n transitions.set(key, transition);\n try {\n await transition;\n } finally {\n if (transitions.get(key) === transition) transitions.delete(key);\n }\n return acquireSession(key, config, generation);\n}\n\nasync function replaceSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n existing: GondolinSession | undefined,\n): Promise<void> {\n if (existing) {\n await closeSession(key, existing, {\n waitForActiveOperations: true,\n resetResources: false,\n throwOnError: true,\n });\n }\n const replacement = createSession(key, config, desired, fingerprint);\n sessions.set(key, replacement);\n await replacement.runtime;\n}\n\nfunction discardDeadSession(key: string, session: GondolinSession): void {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n log.logWarning(`Gondolin runtime for '${key}' died; the session will be recreated`);\n}\n\nasync function withRuntime<T>(\n key: string,\n config: GondolinSandboxConfig,\n operation: (handle: GondolinRuntimeHandle) => Promise<T>,\n): Promise<T> {\n for (let attempt = 0; ; attempt += 1) {\n const session = await acquireSession(key, config);\n let handle: GondolinRuntimeHandle | undefined;\n try {\n handle = await session.runtime;\n return await operation(handle);\n } catch (error) {\n const gone = isRuntimeGone(error);\n const interrupted = isRuntimeInterrupted(error);\n if (gone || (interrupted && handle && !(await session.transport.isRuntimeAlive(handle)))) {\n discardDeadSession(key, session);\n }\n // Nothing reached a gone runtime, so recreating and retrying is safe;\n // an interrupted command may have side effects and must surface.\n if (gone && attempt === 0) continue;\n if (gone || interrupted) {\n throw new SandboxError(\n `Error: Gondolin runtime for '${key}' died (${(error as Error).message}); it is recreated on the next command`,\n );\n }\n throw error;\n } finally {\n session.activeOperations -= 1;\n session.lastUsed = Date.now();\n if (session.activeOperations === 0) {\n for (const resolve of session.idleWaiters.splice(0)) resolve();\n }\n }\n }\n}\n\nfunction waitForIdle(session: GondolinSession): Promise<void> {\n if (session.activeOperations === 0) return Promise.resolve();\n return new Promise((resolve) => session.idleWaiters.push(resolve));\n}\n\nasync function closeSession(\n key: string,\n session: GondolinSession,\n options: {\n waitForActiveOperations?: boolean;\n resetResources?: boolean;\n throwOnError?: boolean;\n stopRuntime?: boolean;\n } = {},\n): Promise<void> {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n try {\n if (options.waitForActiveOperations) await waitForIdle(session);\n const handle = await session.runtime;\n if (options.stopRuntime !== false) await session.transport.stop(handle);\n if (\n options.resetResources !== false &&\n session.resourceKey &&\n !Array.from(sessions.values()).some(({ resourceKey }) => resourceKey === session.resourceKey)\n ) {\n gondolinResources.clear(session.resourceKey);\n }\n } catch (error) {\n session.fingerprint = \"\";\n // Re-track for a retried close, unless a replacement already claimed the\n // key — then the failed runtime stays for the reconcile paths and\n // clobbering the replacement would leak it too.\n if (!sessions.has(key)) sessions.set(key, session);\n if (options.throwOnError) throw error;\n log.logWarning(\n `Failed to close Gondolin session '${key}'`,\n error instanceof Error ? error.message : String(error),\n );\n }\n}\n\nexport async function stopIdleGondolinVms(maxIdleMs: number, now = Date.now()): Promise<void> {\n const idle = Array.from(sessions.entries()).filter(\n ([key, session]) =>\n !transitions.has(key) &&\n session.activeOperations === 0 &&\n now - session.lastUsed >= maxIdleMs,\n );\n await Promise.all(\n idle.map(([key, session]) => {\n // Register the close as a transition so a concurrent acquire waits for\n // it instead of racing the shared session slot.\n const transition = closeSession(key, session).finally(() => {\n if (transitions.get(key) === transition) transitions.delete(key);\n });\n transitions.set(key, transition);\n return transition;\n }),\n );\n}\n\n/**\n * Stop workers surviving from a previous mikan that no conversation has\n * adopted — without this, a runtime whose conversation went quiet before the\n * restart would idle forever (its worker only self-stops when every mikan is\n * gone, and the in-memory idle sweep only tracks acquired sessions).\n */\nexport async function sweepUnadoptedGondolinWorkers(): Promise<void> {\n for (const record of gondolinInventory.listWorkerRecords()) {\n if (sessions.has(record.instanceId) || transitions.has(record.instanceId)) continue;\n log.logInfo(\n `Stopping unadopted Gondolin worker ${record.ownerPid} (instance '${record.instanceId}')`,\n );\n await gondolinWorkers.stop({ workerPid: record.ownerPid, sessionId: record.sessionId });\n }\n}\n\n/**\n * Forget every session without stopping the workers: runtimes deliberately\n * outlive the mikan process so the next one adopts them instead of paying a\n * VM boot per conversation on every deploy.\n */\nexport async function disconnectAllGondolinRuntimes(): Promise<void> {\n shutdownGeneration += 1;\n activeShutdowns += 1;\n try {\n await Promise.allSettled(transitions.values());\n const current = Array.from(sessions.entries());\n await Promise.all(\n current.map(([key, session]) =>\n closeSession(key, session, { waitForActiveOperations: true, stopRuntime: false }),\n ),\n );\n } finally {\n activeShutdowns -= 1;\n }\n}\n\nfunction executionSignal(options?: ExecOptions): AbortSignal | undefined {\n const signals = [options?.signal];\n if (options?.timeout && options.timeout > 0) {\n signals.push(AbortSignal.timeout(options.timeout * 1000));\n }\n const active = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n return active.length > 0 ? AbortSignal.any(active) : undefined;\n}\n\nexport class GondolinExecutor implements Executor {\n private readonly workspacePath: string;\n private readonly instanceId: string;\n\n constructor(\n private readonly config: GondolinSandboxConfig,\n private readonly env?: Record<string, string>,\n ) {\n // remote runtimes never load gondolin in this process, so the mikan host\n // may stay on the supported Node floor\n if (config.profile !== \"remote\") assertSupportedNodeVersion();\n this.workspacePath = config.workspacePath ?? process.cwd();\n this.instanceId = config.instanceId ?? this.workspacePath;\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return withRuntime(this.instanceId, this.config, (handle) =>\n transportFor(this.config).exec(handle, withRuntimeBootstrap(command, this.env), {\n env: this.env,\n signal: executionSignal(options),\n }),\n );\n }\n\n async readFile(path: string): Promise<string> {\n return execReadFile(this, path);\n }\n\n async readFileBase64(path: string): Promise<string> {\n return execReadFileBase64(this, path);\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n return execWriteFile(this, path, content);\n }\n\n getWorkspacePath(): string {\n return \"/workspace\";\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, \"/workspace\");\n }\n\n getSandboxConfig(): GondolinSandboxConfig {\n return this.config;\n }\n}\n\nexport const gondolinSandboxAdapter: SandboxAdapter<GondolinSandboxConfig> = {\n type: \"gondolin\",\n parse: parseGondolinSandboxArg,\n validate: validateGondolinSandbox,\n createExecutor: (config, env) => new GondolinExecutor(config, env),\n};\n"]}
1
+ {"version":3,"file":"gondolin.js","sourceRoot":"","sources":["../../src/sandbox/gondolin.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport * as log from \"../log.js\";\nimport type { ResourceLimits, SandboxLimitStatus, SandboxResourceController } from \"../types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { gondolinInventory } from \"./gondolin-inventory.js\";\nimport { isRuntimeGone, isRuntimeInterrupted } from \"./gondolin-recovery.js\";\nimport {\n gondolinWorkers,\n type GondolinRuntimeHandle,\n type GondolinRuntimeTransport,\n} from \"./gondolin-worker-client.js\";\nimport { gondolinFleet } from \"./gondolin-fleet.js\";\nimport { gondolinGateway } from \"./gondolin-gateway.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\nimport { withRuntimeBootstrap } from \"./container.js\";\nimport { execReadFile, execReadFileBase64, execWriteFile } from \"./utils.js\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n GondolinSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\n\ntype GondolinModule = typeof import(\"@earendil-works/gondolin\");\n\ninterface GondolinSession {\n runtime: Promise<GondolinRuntimeHandle>;\n transport: GondolinRuntimeTransport;\n fingerprint: string;\n resourceKey?: string;\n activeOperations: number;\n lastUsed: number;\n idleWaiters: Array<() => void>;\n}\n\ninterface GondolinDesiredRuntime {\n image: string;\n imageIdentity: string;\n mounts: Array<{ source: string; target: string }>;\n /** Content identity of projected credential files (rotation → drift). */\n credentialIdentity: Record<string, string>;\n limits?: ResourceLimits;\n}\n\nconst MINIMUM_NODE_VERSION = [23, 6, 0] as const;\nconst MIKAN_IMAGE = \"mikan-sandbox:latest\";\nconst sessions = new Map<string, GondolinSession>();\nconst transitions = new Map<string, Promise<void>>();\nlet activeShutdowns = 0;\nlet shutdownGeneration = 0;\n\nclass GondolinResourceManager implements SandboxResourceController {\n private defaultLimits?: ResourceLimits;\n private boostLimits?: ResourceLimits;\n private readonly boostedKeys = new Set<string>();\n private readonly overrideLimits = new Map<string, ResourceLimits>();\n\n configure(defaultLimits?: ResourceLimits, boostLimits?: ResourceLimits): void {\n this.defaultLimits = defaultLimits;\n this.boostLimits = boostLimits;\n this.boostedKeys.clear();\n this.overrideLimits.clear();\n }\n\n async boost(key: string): Promise<SandboxLimitStatus> {\n if (this.boostLimits?.cpus || this.boostLimits?.memory) {\n this.overrideLimits.delete(key);\n this.boostedKeys.add(key);\n }\n return this.getLimitStatus(key);\n }\n\n async setLimits(key: string, limits: ResourceLimits): Promise<SandboxLimitStatus> {\n this.boostedKeys.delete(key);\n this.overrideLimits.set(key, { ...this.defaultLimits, ...limits });\n return this.getLimitStatus(key);\n }\n\n getLimitStatus(key: string): SandboxLimitStatus {\n return { limits: this.effectiveLimits(key), boosted: this.boostedKeys.has(key) };\n }\n\n getDefaultLimits(): ResourceLimits | undefined {\n return this.defaultLimits;\n }\n\n getBoostLimits(): ResourceLimits | undefined {\n return this.boostLimits;\n }\n\n clear(key: string): void {\n this.boostedKeys.delete(key);\n this.overrideLimits.delete(key);\n }\n\n private effectiveLimits(key: string): ResourceLimits | undefined {\n const override = this.overrideLimits.get(key);\n if (override) return override;\n if (!this.boostedKeys.has(key)) return this.defaultLimits;\n return { ...this.defaultLimits, ...this.boostLimits };\n }\n}\n\nexport const gondolinResources = new GondolinResourceManager();\n\nfunction parseGondolinSandboxArg(value: string): GondolinSandboxConfig | undefined {\n if (!value.startsWith(\"gondolin:\")) return undefined;\n\n const profile = value.slice(\"gondolin:\".length);\n if (!profile) {\n throw new SandboxError(\"Error: gondolin sandbox requires a profile (e.g., gondolin:default)\");\n }\n if (profile !== \"default\" && profile !== \"remote\") {\n throw new SandboxError(\n `Error: unsupported gondolin profile '${profile}'. Use 'gondolin:default' or 'gondolin:remote'`,\n );\n }\n return { type: \"gondolin\", profile };\n}\n\nfunction assertSupportedNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < MINIMUM_NODE_VERSION[0] || (major === MINIMUM_NODE_VERSION[0] && minor < 6)) {\n throw new SandboxError(\n `Error: gondolin:default requires Node.js >=23.6.0 (current: ${process.versions.node}). Other sandbox modes remain available on Node.js >=22.19.0.`,\n );\n }\n}\n\nasync function validateGondolinSandbox(config?: GondolinSandboxConfig): Promise<void> {\n if (config?.profile === \"remote\") {\n // The remote transports are configured from settings later in startup, so\n // \"is a worker source configured?\" is checked there (assertRemoteConfigured),\n // not here where nothing has been wired yet.\n console.log(\" Gondolin microVM enabled. Profile: remote\");\n return;\n }\n assertSupportedNodeVersion();\n console.log(\" Gondolin microVM enabled. Profile: default\");\n}\n\n/**\n * Fail fast when `gondolin:remote` is selected but no worker source is\n * configured. Call after the fleet and gateway have been configured.\n */\nexport function assertRemoteConfigured(): void {\n if (!gondolinFleet.isConfigured() && !gondolinGateway.isConfigured()) {\n throw new SandboxError(\n \"Error: gondolin:remote requires sandbox.gondolin.remote settings (workers[]/url, or gateway for dial-home workers)\",\n );\n }\n // Without a workspaceRoot, mount sources cannot be translated to the worker's\n // filesystem and every runtime is rejected with \"escapes the workspace root\".\n const missing = gondolinFleet.workersMissingWorkspaceRoot();\n if (missing.length > 0) {\n throw new SandboxError(\n `Error: gondolin:remote worker(s) [${missing.join(\", \")}] have no workspaceRoot; ` +\n `set sandbox.gondolin.remote.workspaceRoot (or gateway.workspaceRoot) to the worker-side shared workspace path`,\n );\n }\n}\n\nfunction transportFor(config: GondolinSandboxConfig): GondolinRuntimeTransport {\n return config.profile === \"remote\" ? gondolinFleet : gondolinWorkers;\n}\n\nasync function resolveDesiredRuntime(\n config: GondolinSandboxConfig,\n): Promise<GondolinDesiredRuntime> {\n let image: string;\n let imageIdentity: string;\n if (config.profile === \"remote\") {\n // image assets live on the worker host; the selector is the identity\n image = gondolinFleet.imageSelector() ?? config.image ?? MIKAN_IMAGE;\n imageIdentity = image;\n } else {\n const selector = config.image ?? MIKAN_IMAGE;\n const { ensureImageSelector } = (await import(\"@earendil-works/gondolin\")) as GondolinModule;\n const resolvedImage = await ensureImageSelector(selector);\n image = resolvedImage.assetDir;\n imageIdentity = resolvedImage.buildId ?? resolvedImage.assetDir;\n }\n const mounts = (\n config.mounts ?? [{ source: config.workspacePath ?? process.cwd(), target: \"/workspace\" }]\n ).toSorted((left, right) => left.target.localeCompare(right.target));\n return {\n image,\n imageIdentity,\n mounts,\n credentialIdentity: credentialIdentity(mounts),\n limits: config.resourceKey\n ? gondolinResources.getLimitStatus(config.resourceKey).limits\n : undefined,\n };\n}\n\n/**\n * Content hashes of credential file mounts (files projected outside\n * /workspace). Rotating a credential on the host changes the fingerprint, so\n * the next command recreates the runtime with a fresh projection instead of\n * serving the stale copy for the rest of the VM's life. Workspace files are\n * excluded: the guest writes them back, which would drift the runtime it runs\n * in.\n */\nfunction credentialIdentity(\n mounts: Array<{ source: string; target: string }>,\n): Record<string, string> {\n const identity: Record<string, string> = {};\n for (const mount of mounts) {\n if (mount.target.startsWith(\"/workspace/\") || mount.target === \"/workspace\") continue;\n try {\n if (!statSync(mount.source).isFile()) continue;\n identity[mount.target] = createHash(\"sha256\")\n .update(readFileSync(mount.source))\n .digest(\"hex\");\n } catch {\n // missing source: the worker skips it too, so it has no runtime identity\n }\n }\n return identity;\n}\n\nfunction runtimeFingerprint(desired: GondolinDesiredRuntime): string {\n return createHash(\"sha256\")\n .update(\n JSON.stringify({\n image: desired.imageIdentity,\n mounts: desired.mounts,\n credentials: desired.credentialIdentity,\n limits: desired.limits,\n }),\n )\n .digest(\"hex\");\n}\n\nfunction gondolinCpuCount(cpus: string | undefined): number | undefined {\n if (cpus === undefined) return undefined;\n const parsed = Number(cpus);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new SandboxError(`Error: invalid Gondolin CPU limit '${cpus}'`);\n }\n // ponytail: Gondolin exposes whole vCPUs; add host cgroup quotas if fractional enforcement matters.\n return Math.ceil(parsed);\n}\n\nfunction createSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n): GondolinSession {\n const transport = transportFor(config);\n let session: GondolinSession;\n const runtime = transport\n .ensure(key, {\n image: desired.image,\n mounts: desired.mounts,\n cpus: desired.limits?.cpus,\n vmCpus: gondolinCpuCount(desired.limits?.cpus),\n memory: desired.limits?.memory,\n fingerprint,\n workspacePath: config.workspacePath,\n })\n .catch((error) => {\n if (sessions.get(key) === session) sessions.delete(key);\n throw error;\n });\n session = {\n runtime,\n transport,\n fingerprint,\n resourceKey: config.resourceKey,\n activeOperations: 0,\n lastUsed: Date.now(),\n idleWaiters: [],\n };\n return session;\n}\n\nasync function acquireSession(\n key: string,\n config: GondolinSandboxConfig,\n generation = shutdownGeneration,\n): Promise<GondolinSession> {\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n\n const pending = transitions.get(key);\n if (pending) {\n await pending;\n return acquireSession(key, config, generation);\n }\n\n const desired = await resolveDesiredRuntime(config);\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n const concurrentTransition = transitions.get(key);\n if (concurrentTransition) {\n await concurrentTransition;\n return acquireSession(key, config, generation);\n }\n\n const fingerprint = runtimeFingerprint(desired);\n const existing = sessions.get(key);\n if (existing?.fingerprint === fingerprint) {\n existing.activeOperations += 1;\n return existing;\n }\n\n const transition = replaceSession(key, config, desired, fingerprint, existing);\n transitions.set(key, transition);\n try {\n await transition;\n } finally {\n if (transitions.get(key) === transition) transitions.delete(key);\n }\n return acquireSession(key, config, generation);\n}\n\nasync function replaceSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n existing: GondolinSession | undefined,\n): Promise<void> {\n if (existing) {\n await closeSession(key, existing, {\n waitForActiveOperations: true,\n resetResources: false,\n throwOnError: true,\n });\n }\n const replacement = createSession(key, config, desired, fingerprint);\n sessions.set(key, replacement);\n await replacement.runtime;\n}\n\nfunction discardDeadSession(key: string, session: GondolinSession): void {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n log.logWarning(`Gondolin runtime for '${key}' died; the session will be recreated`);\n}\n\nasync function withRuntime<T>(\n key: string,\n config: GondolinSandboxConfig,\n operation: (handle: GondolinRuntimeHandle) => Promise<T>,\n): Promise<T> {\n for (let attempt = 0; ; attempt += 1) {\n const session = await acquireSession(key, config);\n let handle: GondolinRuntimeHandle | undefined;\n try {\n handle = await session.runtime;\n return await operation(handle);\n } catch (error) {\n const gone = isRuntimeGone(error);\n const interrupted = isRuntimeInterrupted(error);\n if (gone || (interrupted && handle && !(await session.transport.isRuntimeAlive(handle)))) {\n discardDeadSession(key, session);\n }\n // Nothing reached a gone runtime, so recreating and retrying is safe;\n // an interrupted command may have side effects and must surface.\n if (gone && attempt === 0) continue;\n if (gone || interrupted) {\n throw new SandboxError(\n `Error: Gondolin runtime for '${key}' died (${(error as Error).message}); it is recreated on the next command`,\n );\n }\n throw error;\n } finally {\n session.activeOperations -= 1;\n session.lastUsed = Date.now();\n if (session.activeOperations === 0) {\n for (const resolve of session.idleWaiters.splice(0)) resolve();\n }\n }\n }\n}\n\nfunction waitForIdle(session: GondolinSession): Promise<void> {\n if (session.activeOperations === 0) return Promise.resolve();\n return new Promise((resolve) => session.idleWaiters.push(resolve));\n}\n\nasync function closeSession(\n key: string,\n session: GondolinSession,\n options: {\n waitForActiveOperations?: boolean;\n resetResources?: boolean;\n throwOnError?: boolean;\n stopRuntime?: boolean;\n } = {},\n): Promise<void> {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n try {\n if (options.waitForActiveOperations) await waitForIdle(session);\n const handle = await session.runtime;\n if (options.stopRuntime !== false) await session.transport.stop(handle);\n if (\n options.resetResources !== false &&\n session.resourceKey &&\n !Array.from(sessions.values()).some(({ resourceKey }) => resourceKey === session.resourceKey)\n ) {\n gondolinResources.clear(session.resourceKey);\n }\n } catch (error) {\n session.fingerprint = \"\";\n // Re-track for a retried close, unless a replacement already claimed the\n // key — then the failed runtime stays for the reconcile paths and\n // clobbering the replacement would leak it too.\n if (!sessions.has(key)) sessions.set(key, session);\n if (options.throwOnError) throw error;\n log.logWarning(\n `Failed to close Gondolin session '${key}'`,\n error instanceof Error ? error.message : String(error),\n );\n }\n}\n\nexport async function stopIdleGondolinVms(maxIdleMs: number, now = Date.now()): Promise<void> {\n const idle = Array.from(sessions.entries()).filter(\n ([key, session]) =>\n !transitions.has(key) &&\n session.activeOperations === 0 &&\n now - session.lastUsed >= maxIdleMs,\n );\n await Promise.all(\n idle.map(([key, session]) => {\n // Register the close as a transition so a concurrent acquire waits for\n // it instead of racing the shared session slot.\n const transition = closeSession(key, session).finally(() => {\n if (transitions.get(key) === transition) transitions.delete(key);\n });\n transitions.set(key, transition);\n return transition;\n }),\n );\n}\n\n/**\n * Stop workers surviving from a previous mikan that no conversation has\n * adopted — without this, a runtime whose conversation went quiet before the\n * restart would idle forever (its worker only self-stops when every mikan is\n * gone, and the in-memory idle sweep only tracks acquired sessions).\n */\nexport async function sweepUnadoptedGondolinWorkers(): Promise<void> {\n for (const record of gondolinInventory.listWorkerRecords()) {\n if (sessions.has(record.instanceId) || transitions.has(record.instanceId)) continue;\n log.logInfo(\n `Stopping unadopted Gondolin worker ${record.ownerPid} (instance '${record.instanceId}')`,\n );\n await gondolinWorkers.stop({ workerPid: record.ownerPid, sessionId: record.sessionId });\n }\n}\n\n/**\n * Forget every session without stopping the workers: runtimes deliberately\n * outlive the mikan process so the next one adopts them instead of paying a\n * VM boot per conversation on every deploy.\n */\nexport async function disconnectAllGondolinRuntimes(): Promise<void> {\n shutdownGeneration += 1;\n activeShutdowns += 1;\n try {\n await Promise.allSettled(transitions.values());\n const current = Array.from(sessions.entries());\n await Promise.all(\n current.map(([key, session]) =>\n closeSession(key, session, { waitForActiveOperations: true, stopRuntime: false }),\n ),\n );\n } finally {\n activeShutdowns -= 1;\n }\n}\n\nfunction executionSignal(options?: ExecOptions): AbortSignal | undefined {\n const signals = [options?.signal];\n if (options?.timeout && options.timeout > 0) {\n signals.push(AbortSignal.timeout(options.timeout * 1000));\n }\n const active = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n return active.length > 0 ? AbortSignal.any(active) : undefined;\n}\n\nexport class GondolinExecutor implements Executor {\n private readonly workspacePath: string;\n private readonly instanceId: string;\n\n constructor(\n private readonly config: GondolinSandboxConfig,\n private readonly env?: Record<string, string>,\n ) {\n // remote runtimes never load gondolin in this process, so the mikan host\n // may stay on the supported Node floor\n if (config.profile !== \"remote\") assertSupportedNodeVersion();\n this.workspacePath = config.workspacePath ?? process.cwd();\n this.instanceId = config.instanceId ?? this.workspacePath;\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return withRuntime(this.instanceId, this.config, (handle) =>\n transportFor(this.config).exec(handle, withRuntimeBootstrap(command, this.env), {\n env: this.env,\n signal: executionSignal(options),\n }),\n );\n }\n\n async readFile(path: string): Promise<string> {\n return execReadFile(this, path);\n }\n\n async readFileBase64(path: string): Promise<string> {\n return execReadFileBase64(this, path);\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n return execWriteFile(this, path, content);\n }\n\n getWorkspacePath(): string {\n return \"/workspace\";\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, \"/workspace\");\n }\n\n getSandboxConfig(): GondolinSandboxConfig {\n return this.config;\n }\n}\n\nexport const gondolinSandboxAdapter: SandboxAdapter<GondolinSandboxConfig> = {\n type: \"gondolin\",\n credentials: { env: true, fileMounts: true },\n parse: parseGondolinSandboxArg,\n validate: validateGondolinSandbox,\n createExecutor: (config, env) => new GondolinExecutor(config, env),\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5C;IAEK,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElD;IAEK,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;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,CAIhE,CAAC"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5C;IAEK,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElD;IAEK,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;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"}
@@ -93,6 +93,7 @@ export class HostExecutor {
93
93
  }
94
94
  export const hostSandboxAdapter = {
95
95
  type: "host",
96
+ credentials: { env: false, fileMounts: false },
96
97
  parse: parseHostSandboxArg,
97
98
  createExecutor: () => new HostExecutor(),
98
99
  };
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"child_process\";\nimport { mkdir, readFile, rename, writeFile } from \"fs/promises\";\nimport { dirname } from \"path\";\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\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 async readFile(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n }\n\n async readFileBase64(path: string): Promise<string> {\n return (await readFile(path)).toString(\"base64\");\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const stage = `${path}.mikan-stage`;\n await writeFile(stage, content, \"utf-8\");\n await rename(stage, path);\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 createExecutor: () => new HostExecutor(),\n};\n"]}
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"child_process\";\nimport { mkdir, readFile, rename, writeFile } from \"fs/promises\";\nimport { dirname } from \"path\";\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\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 async readFile(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n }\n\n async readFileBase64(path: string): Promise<string> {\n return (await readFile(path)).toString(\"base64\");\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const stage = `${path}.mikan-stage`;\n await writeFile(stage, content, \"utf-8\");\n await rename(stage, path);\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 credentials: { env: false, fileMounts: false },\n parse: parseHostSandboxArg,\n createExecutor: () => new HostExecutor(),\n};\n"]}
@@ -1,21 +1,16 @@
1
1
  import type { SandboxConfig } from "./types.js";
2
- /**
3
- * Runtime actor identity: the one key that names a conversation's vault dir,
4
- * docker container and network, and cloudflare sandbox suffix. Everything
5
- * that needs such a name consumes actorKey(); nothing may re-derive or
6
- * re-sanitize it — two sanitizers with divergent outputs used to make a
7
- * container/vault mismatch a silent wrong-identity bug rather than an error.
8
- */
9
- export declare function sanitizeIdentitySegment(value: string): string;
10
- /**
11
- * The actor key for a sandbox config: per-conversation for managed sandboxes
12
- * (image/gondolin/cloudflare/firecracker), the fixed container name for a shared
13
- * container, and the platform user id on the host.
14
- */
15
- export declare function actorKey(baseConfig: SandboxConfig, ids: {
2
+ export declare function credentialAuthorizationKey(baseConfig: SandboxConfig, ids: {
16
3
  userId: string;
17
4
  conversationId: string;
18
5
  }): string;
19
- /** Scope a base cloudflare sandbox id to one actor key. */
20
- export declare function scopeCloudflareSandboxId(baseId: string, actorVaultKey: string): string;
6
+ export declare function legacyExactCredentialAuthorizationKey(baseConfig: SandboxConfig, ids: {
7
+ userId: string;
8
+ conversationId: string;
9
+ }): string | undefined;
10
+ export declare function runtimeResourceKey(baseConfig: SandboxConfig, ids: {
11
+ userId: string;
12
+ conversationId: string;
13
+ }): string;
14
+ export declare function sanitizeIdentitySegment(value: string): string;
15
+ export declare function scopeCloudflareSandboxId(baseId: string, resourceKey: string): string;
21
16
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,UAAU,EAAE,aAAa,EACzB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAaR;AAED,2DAA2D;AAC3D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEtF"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,aAAa,EACzB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAIR;AAED,wBAAgB,qCAAqC,CACnD,UAAU,EAAE,aAAa,EACzB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,aAAa,EACzB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAIR;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpF"}