@geminixiang/mikan 1.0.0-beta.23 → 1.0.0-beta.25

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 (107) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +8 -12
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +9 -8
  5. package/dist/agent.js.map +1 -1
  6. package/dist/cli/boot.d.ts +1 -1
  7. package/dist/cli/boot.d.ts.map +1 -1
  8. package/dist/cli/boot.js +15 -7
  9. package/dist/cli/boot.js.map +1 -1
  10. package/dist/commands/sandbox.d.ts.map +1 -1
  11. package/dist/commands/sandbox.js +5 -2
  12. package/dist/commands/sandbox.js.map +1 -1
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +39 -12
  15. package/dist/config.js.map +1 -1
  16. package/dist/execution-resolver.d.ts +2 -1
  17. package/dist/execution-resolver.d.ts.map +1 -1
  18. package/dist/execution-resolver.js +7 -4
  19. package/dist/execution-resolver.js.map +1 -1
  20. package/dist/index.d.ts +2 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/main.js +87 -19
  25. package/dist/main.js.map +1 -1
  26. package/dist/sandbox/firecracker.d.ts +18 -0
  27. package/dist/sandbox/firecracker.d.ts.map +1 -0
  28. package/dist/sandbox/firecracker.js +222 -0
  29. package/dist/sandbox/firecracker.js.map +1 -0
  30. package/dist/sandbox/gondolin-bootstrap.d.ts +26 -0
  31. package/dist/sandbox/gondolin-bootstrap.d.ts.map +1 -0
  32. package/dist/sandbox/gondolin-bootstrap.js +27 -0
  33. package/dist/sandbox/gondolin-bootstrap.js.map +1 -0
  34. package/dist/sandbox/gondolin-contract.d.ts +125 -0
  35. package/dist/sandbox/gondolin-contract.d.ts.map +1 -0
  36. package/dist/sandbox/gondolin-contract.js +155 -0
  37. package/dist/sandbox/gondolin-contract.js.map +1 -0
  38. package/dist/sandbox/gondolin-fleet.d.ts +104 -0
  39. package/dist/sandbox/gondolin-fleet.d.ts.map +1 -0
  40. package/dist/sandbox/gondolin-fleet.js +330 -0
  41. package/dist/sandbox/gondolin-fleet.js.map +1 -0
  42. package/dist/sandbox/gondolin-gateway.d.ts +86 -0
  43. package/dist/sandbox/gondolin-gateway.d.ts.map +1 -0
  44. package/dist/sandbox/gondolin-gateway.js +407 -0
  45. package/dist/sandbox/gondolin-gateway.js.map +1 -0
  46. package/dist/sandbox/gondolin-inventory.d.ts +75 -0
  47. package/dist/sandbox/gondolin-inventory.d.ts.map +1 -0
  48. package/dist/sandbox/gondolin-inventory.js +257 -0
  49. package/dist/sandbox/gondolin-inventory.js.map +1 -0
  50. package/dist/sandbox/gondolin-join.d.ts +62 -0
  51. package/dist/sandbox/gondolin-join.d.ts.map +1 -0
  52. package/dist/sandbox/gondolin-join.js +261 -0
  53. package/dist/sandbox/gondolin-join.js.map +1 -0
  54. package/dist/sandbox/gondolin-nfs-advisory.d.ts +15 -0
  55. package/dist/sandbox/gondolin-nfs-advisory.d.ts.map +1 -0
  56. package/dist/sandbox/gondolin-nfs-advisory.js +60 -0
  57. package/dist/sandbox/gondolin-nfs-advisory.js.map +1 -0
  58. package/dist/sandbox/gondolin-placement.d.ts +30 -0
  59. package/dist/sandbox/gondolin-placement.d.ts.map +1 -0
  60. package/dist/sandbox/gondolin-placement.js +77 -0
  61. package/dist/sandbox/gondolin-placement.js.map +1 -0
  62. package/dist/sandbox/gondolin-recovery.d.ts +33 -0
  63. package/dist/sandbox/gondolin-recovery.d.ts.map +1 -0
  64. package/dist/sandbox/gondolin-recovery.js +39 -0
  65. package/dist/sandbox/gondolin-recovery.js.map +1 -0
  66. package/dist/sandbox/gondolin-remote.d.ts +70 -0
  67. package/dist/sandbox/gondolin-remote.d.ts.map +1 -0
  68. package/dist/sandbox/gondolin-remote.js +325 -0
  69. package/dist/sandbox/gondolin-remote.js.map +1 -0
  70. package/dist/sandbox/gondolin-worker-client.d.ts +135 -0
  71. package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -0
  72. package/dist/sandbox/gondolin-worker-client.js +323 -0
  73. package/dist/sandbox/gondolin-worker-client.js.map +1 -0
  74. package/dist/sandbox/gondolin-worker-main.d.ts +2 -0
  75. package/dist/sandbox/gondolin-worker-main.d.ts.map +1 -0
  76. package/dist/sandbox/gondolin-worker-main.js +22 -0
  77. package/dist/sandbox/gondolin-worker-main.js.map +1 -0
  78. package/dist/sandbox/gondolin-worker.d.ts +17 -0
  79. package/dist/sandbox/gondolin-worker.d.ts.map +1 -0
  80. package/dist/sandbox/gondolin-worker.js +201 -0
  81. package/dist/sandbox/gondolin-worker.js.map +1 -0
  82. package/dist/sandbox/gondolin.d.ts +53 -0
  83. package/dist/sandbox/gondolin.d.ts.map +1 -0
  84. package/dist/sandbox/gondolin.js +430 -0
  85. package/dist/sandbox/gondolin.js.map +1 -0
  86. package/dist/sandbox/index.d.ts +7 -6
  87. package/dist/sandbox/index.d.ts.map +1 -1
  88. package/dist/sandbox/index.js +9 -7
  89. package/dist/sandbox/index.js.map +1 -1
  90. package/dist/sandbox/types.d.ts +16 -12
  91. package/dist/sandbox/types.d.ts.map +1 -1
  92. package/dist/sandbox/types.js.map +1 -1
  93. package/dist/tools/sandbox.d.ts.map +1 -1
  94. package/dist/tools/sandbox.js +3 -2
  95. package/dist/tools/sandbox.js.map +1 -1
  96. package/dist/types.d.ts +63 -7
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/types.js.map +1 -1
  99. package/dist/vault/policy.d.ts +3 -3
  100. package/dist/vault/policy.d.ts.map +1 -1
  101. package/dist/vault/policy.js +4 -6
  102. package/dist/vault/policy.js.map +1 -1
  103. package/package.json +3 -3
  104. package/dist/sandbox/agent-sandbox.d.ts +0 -18
  105. package/dist/sandbox/agent-sandbox.d.ts.map +0 -1
  106. package/dist/sandbox/agent-sandbox.js +0 -234
  107. package/dist/sandbox/agent-sandbox.js.map +0 -1
package/dist/cli/boot.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * process; main.ts just executes the plan.
6
6
  *
7
7
  * Modes, highest priority first: `ext` (own grammar, never flag-parsed here),
8
- * `help`, `version`, `onboard`, `download`, `run`.
8
+ * `help`, `version`, `worker-token`, `onboard`, `download`, `run`.
9
9
  */
10
10
  import { join, resolve } from "path";
11
11
  import { envSummaryLines } from "../env-manifest.js";
@@ -28,6 +28,7 @@ export function resolveBoot(args = process.argv.slice(2)) {
28
28
  let help = false;
29
29
  let version = false;
30
30
  let onboard = false;
31
+ let workerToken = false;
31
32
  for (let i = 0; i < args.length; i++) {
32
33
  const arg = args[i];
33
34
  let taken;
@@ -40,6 +41,9 @@ export function resolveBoot(args = process.argv.slice(2)) {
40
41
  else if (arg === "--onboard") {
41
42
  onboard = true;
42
43
  }
44
+ else if (arg === "--worker-token") {
45
+ workerToken = true;
46
+ }
43
47
  else if ((taken = takeValueFlag(args, i, "--sandbox"))) {
44
48
  sandbox = parseSandboxArg(taken.value);
45
49
  i = taken.lastIndex;
@@ -66,11 +70,13 @@ export function resolveBoot(args = process.argv.slice(2)) {
66
70
  ? "help"
67
71
  : version
68
72
  ? "version"
69
- : onboard
70
- ? "onboard"
71
- : downloadChannel
72
- ? "download"
73
- : "run",
73
+ : workerToken
74
+ ? "worker-token"
75
+ : onboard
76
+ ? "onboard"
77
+ : downloadChannel
78
+ ? "download"
79
+ : "run",
74
80
  stateDir,
75
81
  workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, "workspace"),
76
82
  workingDirExplicit: workingDirArg !== undefined,
@@ -96,10 +102,12 @@ Options:
96
102
  host
97
103
  container:<existing-container-name>
98
104
  image:<image[:tag]>
99
- agent-sandbox:<warm-pool>
105
+ gondolin:default | gondolin:remote
106
+ firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]
100
107
  cloudflare:<sandbox-id>
101
108
  Default: host
102
109
  --onboard Create <state-dir>/settings.json from a template, then exit.
110
+ --worker-token Mint a one-time gondolin worker join token, then exit.
103
111
  --download <channel> Dump a Slack channel's history (Slack only), then exit.
104
112
  --version, -v Print the version.
105
113
  --help, -h Show this help.
@@ -1 +1 @@
1
- {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `ext` (own grammar, never flag-parsed here),\n * `help`, `version`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg, type SandboxConfig } from \"../sandbox/index.js\";\nimport { defaultStateDir, resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\n\nexport interface BootPlan {\n mode: \"ext\" | \"env\" | \"help\" | \"version\" | \"onboard\" | \"download\" | \"run\";\n /** argv after `ext`, handed to runExtCommand. Only set for mode \"ext\". */\n extArgs?: string[];\n stateDir: string;\n /** Resolved working directory; defaults to `<stateDir>/workspace`. */\n workingDir: string;\n /** True when the working directory came from argv (then it is not auto-created). */\n workingDirExplicit: boolean;\n sandbox: SandboxConfig;\n downloadChannel?: string;\n}\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n if (args[0] === \"ext\" || args[0] === \"env\") {\n return {\n mode: args[0],\n ...(args[0] === \"ext\" ? { extArgs: args.slice(1) } : {}),\n stateDir: defaultStateDir(),\n workingDir: join(defaultStateDir(), \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n }\n\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDirArg: string | undefined;\n let downloadChannel: string | undefined;\n let help = false;\n let version = false;\n let onboard = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n let taken;\n if (arg === \"--help\" || arg === \"-h\") {\n help = true;\n } else if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n version = true;\n } else if (arg === \"--onboard\") {\n onboard = true;\n } else if ((taken = takeValueFlag(args, i, \"--sandbox\"))) {\n sandbox = parseSandboxArg(taken.value);\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--state-dir\"))) {\n // Consumed here so its value never reads as the positional working\n // dir; the value itself is resolved by resolveStateDir below.\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--download\"))) {\n downloadChannel = taken.value;\n i = taken.lastIndex;\n } else if (!arg.startsWith(\"-\")) {\n workingDirArg = arg;\n } else {\n throw new Error(`Unknown flag: ${arg}. Run \\`mikan --help\\` for usage.`);\n }\n }\n\n const stateDir = resolveStateDir(args);\n return {\n mode: help\n ? \"help\"\n : version\n ? \"version\"\n : onboard\n ? \"onboard\"\n : downloadChannel\n ? \"download\"\n : \"run\",\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox,\n downloadChannel,\n };\n}\n\nexport function helpText(): string {\n return `mikan — multi-platform chat agent daemon\n\nUsage:\n mikan [options] [working-directory]\n Start the daemon. The working directory defaults to <state-dir>/workspace.\n mikan ext <install|validate|list|remove> …\n Manage extensions (run \\`mikan ext\\` for details).\n mikan env\n Show the full environment-variable inventory and what is currently set.\n\nOptions:\n --state-dir <dir> State directory (settings.json, vaults, extensions).\n Default: ~/.mikan\n --sandbox <spec> Execution sandbox. One of:\n host\n container:<existing-container-name>\n image:<image[:tag]>\n agent-sandbox:<warm-pool>\n cloudflare:<sandbox-id>\n Default: host\n --onboard Create <state-dir>/settings.json from a template, then exit.\n --download <channel> Dump a Slack channel's history (Slack only), then exit.\n --version, -v Print the version.\n --help, -h Show this help.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun \\`mikan env\\` for the full inventory.`;\n}\n"]}
1
+ {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `ext` (own grammar, never flag-parsed here),\n * `help`, `version`, `worker-token`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg, type SandboxConfig } from \"../sandbox/index.js\";\nimport { defaultStateDir, resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\n\nexport interface BootPlan {\n mode: \"ext\" | \"env\" | \"help\" | \"version\" | \"worker-token\" | \"onboard\" | \"download\" | \"run\";\n /** argv after `ext`, handed to runExtCommand. Only set for mode \"ext\". */\n extArgs?: string[];\n stateDir: string;\n /** Resolved working directory; defaults to `<stateDir>/workspace`. */\n workingDir: string;\n /** True when the working directory came from argv (then it is not auto-created). */\n workingDirExplicit: boolean;\n sandbox: SandboxConfig;\n downloadChannel?: string;\n}\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n if (args[0] === \"ext\" || args[0] === \"env\") {\n return {\n mode: args[0],\n ...(args[0] === \"ext\" ? { extArgs: args.slice(1) } : {}),\n stateDir: defaultStateDir(),\n workingDir: join(defaultStateDir(), \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n }\n\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDirArg: string | undefined;\n let downloadChannel: string | undefined;\n let help = false;\n let version = false;\n let onboard = false;\n let workerToken = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n let taken;\n if (arg === \"--help\" || arg === \"-h\") {\n help = true;\n } else if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n version = true;\n } else if (arg === \"--onboard\") {\n onboard = true;\n } else if (arg === \"--worker-token\") {\n workerToken = true;\n } else if ((taken = takeValueFlag(args, i, \"--sandbox\"))) {\n sandbox = parseSandboxArg(taken.value);\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--state-dir\"))) {\n // Consumed here so its value never reads as the positional working\n // dir; the value itself is resolved by resolveStateDir below.\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--download\"))) {\n downloadChannel = taken.value;\n i = taken.lastIndex;\n } else if (!arg.startsWith(\"-\")) {\n workingDirArg = arg;\n } else {\n throw new Error(`Unknown flag: ${arg}. Run \\`mikan --help\\` for usage.`);\n }\n }\n\n const stateDir = resolveStateDir(args);\n return {\n mode: help\n ? \"help\"\n : version\n ? \"version\"\n : workerToken\n ? \"worker-token\"\n : onboard\n ? \"onboard\"\n : downloadChannel\n ? \"download\"\n : \"run\",\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox,\n downloadChannel,\n };\n}\n\nexport function helpText(): string {\n return `mikan — multi-platform chat agent daemon\n\nUsage:\n mikan [options] [working-directory]\n Start the daemon. The working directory defaults to <state-dir>/workspace.\n mikan ext <install|validate|list|remove> …\n Manage extensions (run \\`mikan ext\\` for details).\n mikan env\n Show the full environment-variable inventory and what is currently set.\n\nOptions:\n --state-dir <dir> State directory (settings.json, vaults, extensions).\n Default: ~/.mikan\n --sandbox <spec> Execution sandbox. One of:\n host\n container:<existing-container-name>\n image:<image[:tag]>\n gondolin:default | gondolin:remote\n firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]\n cloudflare:<sandbox-id>\n Default: host\n --onboard Create <state-dir>/settings.json from a template, then exit.\n --worker-token Mint a one-time gondolin worker join token, then exit.\n --download <channel> Dump a Slack channel's history (Slack only), then exit.\n --version, -v Print the version.\n --help, -h Show this help.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun \\`mikan env\\` for the full inventory.`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvF,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAS7E;AAED,qBAAa,qBAAsB,YAAW,cAAc;IACpD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CA6FzD;CACF"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvF,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAS7E;AAED,qBAAa,qBAAsB,YAAW,cAAc;IACpD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAkGzD;CACF"}
@@ -20,8 +20,11 @@ export class SandboxCommandHandler {
20
20
  const parsed = parseSandboxCommand(context.commandText);
21
21
  if (!parsed)
22
22
  return false;
23
- if (context.services.sandbox.type !== "image" || !context.services.resourceController) {
24
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Sandbox", ["`/pi-sandbox` 目前只支援 `image:*` managed sandbox。"]), { style: "muted" });
23
+ if ((context.services.sandbox.type !== "image" && context.services.sandbox.type !== "gondolin") ||
24
+ !context.services.resourceController) {
25
+ await replyDiagnosticWithContext(context.responder, formatCommandSummary("Sandbox", [
26
+ "`/pi-sandbox` 目前只支援 `image:*` 與 `gondolin:*` managed sandbox。",
27
+ ]), { style: "muted" });
25
28
  return true;
26
29
  }
27
30
  const containerKey = runtimeResourceKey(context.services.sandbox, {
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"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","sourcesContent":["import { readConversationWorkspaceMountMode } from \"../execution-resolver.js\";\nimport { applyConversationSettings } from \"../settings-mutation.js\";\nimport { runtimeResourceKey } from \"../sandbox/identity.js\";\nimport { slashForms } from \"./manifest.js\";\nimport { matchCommand } from \"./parse.js\";\nimport type { CommandContext, CommandHandler, ParsedSandboxCommand } from \"./types.js\";\nimport { formatCommandSummary, replyDiagnosticWithContext } from \"./utils.js\";\n\nexport type { ParsedSandboxCommand } from \"./types.js\";\n\nconst SANDBOX_COMMANDS = slashForms(\"sandbox\");\n\nexport function parseSandboxCommand(text: string): ParsedSandboxCommand | null {\n const matched = matchCommand(text, SANDBOX_COMMANDS, { stripMention: true });\n if (!matched) return null;\n\n const action = matched.args.length === 1 ? matched.args[0].toLowerCase() : undefined;\n if (action === \"boost\" || action === \"private\" || action === \"full\") {\n return { action };\n }\n return {};\n}\n\nexport class SandboxCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseSandboxCommand(context.commandText);\n if (!parsed) return false;\n\n if (context.services.sandbox.type !== \"image\" || !context.services.resourceController) {\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox\", [\"`/pi-sandbox` 目前只支援 `image:*` managed sandbox。\"]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const containerKey = runtimeResourceKey(context.services.sandbox, {\n userId: context.platformUserId,\n conversationId: context.conversationId,\n });\n\n if (parsed.action === \"private\" || parsed.action === \"full\") {\n applyConversationSettings(\n context.services.runtime,\n context.services.workingDir,\n context.conversationId,\n {\n sandbox: { image: { workspaceMount: parsed.action } },\n },\n );\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Workspace\", [\n parsed.action === \"full\"\n ? \"已將此 conversation 的 sandbox 設為 full workspace mode。\"\n : \"已將此 conversation 的 sandbox 設為 private workspace mode。\",\n `Workspace mount: ${parsed.action}`,\n parsed.action === \"full\"\n ? \"之後這個 runtime 會把整個 host workspace 掛到 /workspace。\"\n : \"之後這個 runtime 只會掛載 private workspace 檔案與當前 conversation 目錄。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n if (parsed.action === \"boost\") {\n const boostLimits = context.services.resourceController.getBoostLimits();\n if (!boostLimits?.cpus && !boostLimits?.memory) {\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Boost\", [\n \"此 mikan instance 尚未設定 sandbox boost 規格。\",\n \"請先在全域 settings.json 設定 `sandbox.boost`。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const status = await context.services.resourceController.boost(containerKey);\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Boost\", [\n \"已暫時提升此 conversation 的 sandbox 規格。\",\n `Current: ${formatLimits(status.limits)}`,\n \"boost 會在此 sandbox runtime 關閉後結束。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const status = context.services.resourceController.getLimitStatus(containerKey);\n const defaultLimits = context.services.resourceController.getDefaultLimits();\n const boostLimits = context.services.resourceController.getBoostLimits();\n const workspaceMount = readConversationWorkspaceMountMode(\n context.services.workingDir,\n context.conversationId,\n );\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\n \"Sandbox\",\n [\n `Current: ${formatLimits(status.limits)}`,\n `Status: ${status.boosted ? \"boosted\" : \"default\"}`,\n `Workspace mount: ${workspaceMount}`,\n \"\",\n `Default: ${formatLimits(defaultLimits)}`,\n boostLimits ? `Boost: ${formatLimits({ ...defaultLimits, ...boostLimits })}` : undefined,\n ].filter((line): line is string => line !== undefined),\n ),\n { style: \"muted\" },\n );\n return true;\n }\n}\n\nfunction formatLimits(limits: { cpus?: string; memory?: string } | undefined): string {\n return `CPU ${limits?.cpus ?? \"unlimited\"} / Memory ${limits?.memory ?? \"unlimited\"}`;\n}\n"]}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAI9E,MAAM,gBAAgB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;AAE/C,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,OAAO,qBAAqB;IAChC,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAE1B,IACE,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;YAC3F,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,EACpC,CAAC;YACD,MAAM,0BAA0B,CAC9B,OAAO,CAAC,SAAS,EACjB,oBAAoB,CAAC,SAAS,EAAE;gBAC9B,+DAA+D;aAChE,CAAC,EACF,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE;YAChE,MAAM,EAAE,OAAO,CAAC,cAAc;YAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5D,yBAAyB,CACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,EACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,EAC3B,OAAO,CAAC,cAAc,EACtB;gBACE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE;aACtD,CACF,CAAC;YACF,MAAM,0BAA0B,CAC9B,OAAO,CAAC,SAAS,EACjB,oBAAoB,CAAC,mBAAmB,EAAE;gBACxC,MAAM,CAAC,MAAM,KAAK,MAAM;oBACtB,CAAC,CAAC,oDAAoD;oBACtD,CAAC,CAAC,uDAAuD;gBAC3D,oBAAoB,MAAM,CAAC,MAAM,EAAE;gBACnC,MAAM,CAAC,MAAM,KAAK,MAAM;oBACtB,CAAC,CAAC,iDAAiD;oBACnD,CAAC,CAAC,4DAA4D;aACjE,CAAC,EACF,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,cAAc,EAAE,CAAC;YACzE,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;gBAC/C,MAAM,0BAA0B,CAC9B,OAAO,CAAC,SAAS,EACjB,oBAAoB,CAAC,eAAe,EAAE;oBACpC,yCAAyC;oBACzC,yCAAyC;iBAC1C,CAAC,EACF,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC7E,MAAM,0BAA0B,CAC9B,OAAO,CAAC,SAAS,EACjB,oBAAoB,CAAC,eAAe,EAAE;gBACpC,mCAAmC;gBACnC,YAAY,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;gBACzC,kCAAkC;aACnC,CAAC,EACF,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAChF,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,CAAC;QAC7E,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,cAAc,EAAE,CAAC;QACzE,MAAM,cAAc,GAAG,kCAAkC,CACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,EAC3B,OAAO,CAAC,cAAc,CACvB,CAAC;QACF,MAAM,0BAA0B,CAC9B,OAAO,CAAC,SAAS,EACjB,oBAAoB,CAClB,SAAS,EACT;YACE,YAAY,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YACzC,WAAW,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;YACnD,oBAAoB,cAAc,EAAE;YACpC,EAAE;YACF,YAAY,YAAY,CAAC,aAAa,CAAC,EAAE;YACzC,WAAW,CAAC,CAAC,CAAC,UAAU,YAAY,CAAC,EAAE,GAAG,aAAa,EAAE,GAAG,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;SACzF,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CACvD,EACD,EAAE,KAAK,EAAE,OAAO,EAAE,CACnB,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,SAAS,YAAY,CAAC,MAAsD;IAC1E,OAAO,OAAO,MAAM,EAAE,IAAI,IAAI,WAAW,aAAa,MAAM,EAAE,MAAM,IAAI,WAAW,EAAE,CAAC;AACxF,CAAC","sourcesContent":["import { readConversationWorkspaceMountMode } from \"../execution-resolver.js\";\nimport { applyConversationSettings } from \"../settings-mutation.js\";\nimport { runtimeResourceKey } from \"../sandbox/identity.js\";\nimport { slashForms } from \"./manifest.js\";\nimport { matchCommand } from \"./parse.js\";\nimport type { CommandContext, CommandHandler, ParsedSandboxCommand } from \"./types.js\";\nimport { formatCommandSummary, replyDiagnosticWithContext } from \"./utils.js\";\n\nexport type { ParsedSandboxCommand } from \"./types.js\";\n\nconst SANDBOX_COMMANDS = slashForms(\"sandbox\");\n\nexport function parseSandboxCommand(text: string): ParsedSandboxCommand | null {\n const matched = matchCommand(text, SANDBOX_COMMANDS, { stripMention: true });\n if (!matched) return null;\n\n const action = matched.args.length === 1 ? matched.args[0].toLowerCase() : undefined;\n if (action === \"boost\" || action === \"private\" || action === \"full\") {\n return { action };\n }\n return {};\n}\n\nexport class SandboxCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseSandboxCommand(context.commandText);\n if (!parsed) return false;\n\n if (\n (context.services.sandbox.type !== \"image\" && context.services.sandbox.type !== \"gondolin\") ||\n !context.services.resourceController\n ) {\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox\", [\n \"`/pi-sandbox` 目前只支援 `image:*` 與 `gondolin:*` managed sandbox。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const containerKey = runtimeResourceKey(context.services.sandbox, {\n userId: context.platformUserId,\n conversationId: context.conversationId,\n });\n\n if (parsed.action === \"private\" || parsed.action === \"full\") {\n applyConversationSettings(\n context.services.runtime,\n context.services.workingDir,\n context.conversationId,\n {\n sandbox: { image: { workspaceMount: parsed.action } },\n },\n );\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Workspace\", [\n parsed.action === \"full\"\n ? \"已將此 conversation 的 sandbox 設為 full workspace mode。\"\n : \"已將此 conversation 的 sandbox 設為 private workspace mode。\",\n `Workspace mount: ${parsed.action}`,\n parsed.action === \"full\"\n ? \"之後這個 runtime 會把整個 host workspace 掛到 /workspace。\"\n : \"之後這個 runtime 只會掛載 private workspace 檔案與當前 conversation 目錄。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n if (parsed.action === \"boost\") {\n const boostLimits = context.services.resourceController.getBoostLimits();\n if (!boostLimits?.cpus && !boostLimits?.memory) {\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Boost\", [\n \"此 mikan instance 尚未設定 sandbox boost 規格。\",\n \"請先在全域 settings.json 設定 `sandbox.boost`。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const status = await context.services.resourceController.boost(containerKey);\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\"Sandbox Boost\", [\n \"已暫時提升此 conversation 的 sandbox 規格。\",\n `Current: ${formatLimits(status.limits)}`,\n \"boost 會在此 sandbox runtime 關閉後結束。\",\n ]),\n { style: \"muted\" },\n );\n return true;\n }\n\n const status = context.services.resourceController.getLimitStatus(containerKey);\n const defaultLimits = context.services.resourceController.getDefaultLimits();\n const boostLimits = context.services.resourceController.getBoostLimits();\n const workspaceMount = readConversationWorkspaceMountMode(\n context.services.workingDir,\n context.conversationId,\n );\n await replyDiagnosticWithContext(\n context.responder,\n formatCommandSummary(\n \"Sandbox\",\n [\n `Current: ${formatLimits(status.limits)}`,\n `Status: ${status.boosted ? \"boosted\" : \"default\"}`,\n `Workspace mount: ${workspaceMount}`,\n \"\",\n `Default: ${formatLimits(defaultLimits)}`,\n boostLimits ? `Boost: ${formatLimits({ ...defaultLimits, ...boostLimits })}` : undefined,\n ].filter((line): line is string => line !== undefined),\n ),\n { style: \"muted\" },\n );\n return true;\n }\n}\n\nfunction formatLimits(limits: { cpus?: string; memory?: string } | undefined): string {\n return `CPU ${limits?.cpus ?? \"unlimited\"} / Memory ${limits?.memory ?? \"unlimited\"}`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,qBAAa,0BAA2B,SAAQ,KAAK;aACvB,YAAY,EAAE,MAAM;IAAhD,YAA4B,YAAY,EAAE,MAAM,EAG/C;CACF;AAED,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAwNlG,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CA2BxE;AAED,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAahF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAUlF;AAUD;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAYxF;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,eAAe,GACtB,IAAI,CAaN;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAInE;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CAWN;AAOD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAqED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEtE;AAED,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,IAAI,CAEN"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,qBAAa,0BAA2B,SAAQ,KAAK;aACvB,YAAY,EAAE,MAAM;IAAhD,YAA4B,YAAY,EAAE,MAAM,EAG/C;CACF;AAED,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAC;AAgQlG,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CA2BxE;AAED,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAahF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAUlF;AAUD;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAYxF;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,eAAe,GACtB,IAAI,CAaN;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAInE;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CAWN;AAOD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAqED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEtE;AAED,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,IAAI,CAEN"}
package/dist/config.js CHANGED
@@ -73,12 +73,39 @@ const SettingsFileSchema = Type.Object({
73
73
  image: Type.Optional(Type.Object({
74
74
  workspaceMount: Type.Optional(Type.Union([Type.Literal("private"), Type.Literal("full")])),
75
75
  })),
76
- agentSandbox: Type.Optional(Type.Object({
77
- namespace: Type.String(),
78
- runtimeClassName: Type.String(),
79
- apiUrl: Type.Optional(Type.String()),
80
- routerNamespace: Type.Optional(Type.String()),
81
- sandboxReadyTimeout: Type.Optional(Type.Number()),
76
+ gondolin: Type.Optional(Type.Object({
77
+ remote: Type.Optional(Type.Object({
78
+ url: Type.Optional(Type.String()),
79
+ caFile: Type.Optional(Type.String()),
80
+ certFile: Type.Optional(Type.String()),
81
+ keyFile: Type.Optional(Type.String()),
82
+ workspaceRoot: Type.Optional(Type.String()),
83
+ maxRuntimes: Type.Optional(Type.Number()),
84
+ imageSelector: Type.Optional(Type.String()),
85
+ queueWaitSeconds: Type.Optional(Type.Number()),
86
+ workers: Type.Optional(Type.Array(Type.Object({
87
+ name: Type.Optional(Type.String()),
88
+ url: Type.String(),
89
+ caFile: Type.Optional(Type.String()),
90
+ certFile: Type.Optional(Type.String()),
91
+ keyFile: Type.Optional(Type.String()),
92
+ workspaceRoot: Type.Optional(Type.String()),
93
+ maxRuntimes: Type.Optional(Type.Number()),
94
+ draining: Type.Optional(Type.Boolean()),
95
+ }))),
96
+ gateway: Type.Optional(Type.Object({
97
+ port: Type.Number(),
98
+ certFile: Type.Optional(Type.String()),
99
+ keyFile: Type.Optional(Type.String()),
100
+ clientCaFile: Type.Optional(Type.String()),
101
+ hostnames: Type.Optional(Type.Array(Type.String())),
102
+ workspaceRoot: Type.Optional(Type.String()),
103
+ workers: Type.Optional(Type.Record(Type.String(), Type.Object({
104
+ maxRuntimes: Type.Optional(Type.Number()),
105
+ draining: Type.Optional(Type.Boolean()),
106
+ }))),
107
+ })),
108
+ })),
82
109
  })),
83
110
  defaultSharedVault: Type.Optional(Type.String()),
84
111
  })),
@@ -117,7 +144,7 @@ function normalizeSandboxSettings(sandbox) {
117
144
  ...(sandbox.memory !== undefined ? { memory: sandbox.memory } : {}),
118
145
  ...(sandbox.boost !== undefined ? { boost: sandbox.boost } : {}),
119
146
  ...(sandbox.image !== undefined ? { image: sandbox.image } : {}),
120
- ...(sandbox.agentSandbox !== undefined ? { agentSandbox: sandbox.agentSandbox } : {}),
147
+ ...(sandbox.gondolin !== undefined ? { gondolin: sandbox.gondolin } : {}),
121
148
  ...(defaultSharedVault ? { defaultSharedVault } : {}),
122
149
  };
123
150
  }
@@ -138,11 +165,11 @@ function mergeSandboxSettings(base, override) {
138
165
  ...override,
139
166
  ...(base.boost || override.boost ? { boost: { ...base.boost, ...override.boost } } : {}),
140
167
  ...(base.image || override.image ? { image: { ...base.image, ...override.image } } : {}),
141
- ...(override.agentSandbox
142
- ? { agentSandbox: override.agentSandbox }
143
- : base.agentSandbox
144
- ? { agentSandbox: base.agentSandbox }
145
- : {}),
168
+ // `remote` is one connection description; merging two halves of it would
169
+ // pair a URL with the wrong certificates, so the override wins wholesale.
170
+ ...(base.gondolin || override.gondolin
171
+ ? { gondolin: { ...base.gondolin, ...override.gondolin } }
172
+ : {}),
146
173
  };
147
174
  }
148
175
  function getSettingsPath() {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAe,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAA4B,YAAoB;QAC9C,KAAK,CAAC,mCAAmC,YAAY,EAAE,CAAC,CAAC;4BAD/B,YAAY;QAEtC,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAKD,MAAM,gBAAgB,GAAuB;IAC3C,GAAG,EAAE;QACH,QAAQ,EAAE,WAAW;QACrB,KAAK,EAAE,mBAAmB;QAC1B,aAAa,EAAE,KAAK;QACpB,SAAS,EAAE;YACT,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,kBAAkB;SAC1B;KACF;IACD,KAAK,EAAE;QACL,SAAS,EAAE,WAAW;KACvB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE;YACL,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,IAAI;SACb;QACD,KAAK,EAAE;YACL,cAAc,EAAE,SAAS;SAC1B;QACD,kBAAkB,EAAE,EAAE;KACvB;CACF,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAChB,IAAI,CAAC,MAAM,CAAC;QACV,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACtC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACnC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAC1B,IAAI,CAAC,KAAK,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACnB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACnB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YACrB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;SACpB,CAAC,CACH;QACD,SAAS,EAAE,IAAI,CAAC,QAAQ,CACtB,IAAI,CAAC,MAAM,CAAC;YACV,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;SACpC,CAAC,CACH;KACF,CAAC,CACH;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACV,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;KAClC,CAAC,CACH;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,MAAM,CAAC;QACV,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;KAC1F,CAAC,CACH;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACV,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACpC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,MAAM,CAAC;YACV,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;SACrC,CAAC,CACH;QACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CAClB,IAAI,CAAC,MAAM,CAAC;YACV,cAAc,EAAE,IAAI,CAAC,QAAQ,CAC3B,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAC5D;SACF,CAAC,CACH;QACD,YAAY,EAAE,IAAI,CAAC,QAAQ,CACzB,IAAI,CAAC,MAAM,CAAC;YACV,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;YACxB,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE;YAC/B,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7C,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;SAClD,CAAC,CACH;QACD,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;KACjD,CAAC,CACH;IACD,SAAS,EAAE,IAAI,CAAC,QAAQ,CACtB,IAAI,CAAC,MAAM,CAAC;QACV,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACtC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;KAChD,CAAC,CACH;CACF,CAAC,CAAC;AAIH,SAAS,gBAAgB,CAAC,YAAoB;IAC5C,OAAO,0BAA0B,CAAC,YAAY,EAAE,kBAAkB,EAAE,CAAC,MAAM,EAAE,EAAE,CAC7E,MAAM,KAAK,uBAAuB;QAChC,CAAC,CAAC,8BAA8B,YAAY,2CAA2C;QACvF,CAAC,CAAC,8BAA8B,YAAY,KAAK,MAAM,EAAE,CAC5D,CAAC;AACJ,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,iBAAiB,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,uBAAuB,CAAC,MAA0B;IACzD,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,OAAwB;IACxD,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAC9D,OAAO;QACL,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAC3B,IAAiC,EACjC,QAAqC;IAErC,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC3B,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO;QACL,GAAG,IAAI;QACP,GAAG,QAAQ;QACX,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,GAAG,CAAC,QAAQ,CAAC,YAAY;YACvB,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE;YACzC,CAAC,CAAC,IAAI,CAAC,YAAY;gBACjB,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE;gBACrC,CAAC,CAAC,EAAE,CAAC;KACV,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,eAAe,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,qBAAqB;IAC5B,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,0BAA0B,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,KAAyB,EAAE,IAAY;IAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,oCAAoC,IAAI,oDAAoD,CAC7F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAgC;IAC5D,OAAO,aAAa,CAAC,KAAK,EAAE,mBAAmB,CAAkB,CAAC;AACpE,CAAC;AAED,SAAS,aAAa,CAAC,QAA8B;IACnD,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,oBAAoB,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAE7B,OAAO;QACL,QAAQ;QACR,KAAK;QACL,aAAa;QACb,SAAS;QACT,OAAO;QACP,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,uBAAuB,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,aAAa,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wBAAwB,CAAC,eAAuB;IAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;IACvF,IAAI,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE1C,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC1D,IAAI,OAAO,GAAG,MAAM,CAAC;IACrB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC5C,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,gDAAgD,UAAU,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IACD,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,CAAC,UAAU,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,kDAAkD,UAAU,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9F,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,qDAAqD,QAAQ,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,eAAuB;IACjE,MAAM,YAAY,GAAG,qBAAqB,EAAE,CAAC;IAC7C,MAAM,kBAAkB,GAAG,uBAAuB,CAChD,gBAAgB,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAClE,CAAC;IACF,yEAAyE;IACzE,8EAA8E;IAC9E,MAAM,OAAO,GAAG,oBAAoB,CAAC,YAAY,CAAC,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACvF,OAAO,aAAa,CAAC;QACnB,GAAG,YAAY;QACf,GAAG,kBAAkB;QACrB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAwB;IAC9D,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,eAAe;QAC3B,CAAC,CAAC,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;QACrE,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,MAAM,GAA8B,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC1E,MAAM,KAAK,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC;IACpE,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,EAAE,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAC7F,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,IAAI,MAAM,EAAE,KAAK,EAAE,qBAAqB,CAAC,CAAC;IACjF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,eAAe,GAAG,YAAY,CAAC;AACrC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAEvD,SAAS,sBAAsB,CAAC,IAAY;IAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,+BAA+B,CAAC,eAAuB;IACrE,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,sBAAsB,CAAC,WAAW,CAAC,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IACrE,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sBAAsB,CAAC,YAAY,CAAC,EAAE,CAAC;IACzE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,eAAuB,EACvB,MAAuB;IAEvB,eAAe,CAAC,eAAe,CAAC,CAAC;IAEjC,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;IAE9D,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACpC,CAAC;IAED,sBAAsB,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc;IACxD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,SAAS,KAAK,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,UAAkB,EAClB,WAAmB;IAEnB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC;QAAE,OAAO;IAChD,MAAM,OAAO,GACX,gBAAgB,QAAQ,+CAA+C,UAAU,KAAK;QACtF,0EAA0E;QAC1E,qEAAqE,CAAC;IACxE,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QAC3B,GAAG,CAAC,UAAU,CAAC,6BAA6B,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED,6EAA6E;AAC7E,SAAS,aAAa,CAAC,QAA4B;IACjD,OAAO,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,uBAAuB,CAAC,gBAAgB,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACpF,OAAO,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACvD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,qCAAqC,YAAY,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1B,sBAAsB,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,MAA2C;IAClE,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,qBAAqB,CAAC,MAA0B;IACvD,OAAO;QACL,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClE,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA4B,EAC5B,MAA4B;IAE5B,MAAM,OAAO,GAAuB;QAClC,GAAG,QAAQ;QACX,GAAG,EAAE;YACH,GAAG,QAAQ,CAAC,GAAG;YACf,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvF;QACD,MAAM,EAAE;YACN,GAAG,QAAQ,CAAC,MAAM;YAClB,GAAG,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrE;QACD,0EAA0E;QAC1E,6EAA6E;QAC7E,mEAAmE;QACnE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QACrE,KAAK,EAAE;YACL,GAAG,QAAQ,CAAC,KAAK;YACjB,GAAG,MAAM,CAAC,KAAK;SAChB;KACF,CAAC;IACF,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,kBAAkB,CACzB,YAAoB,EACpB,KAA2B,EAC3B,eAAmC;IAEnC,IAAI,QAAQ,GAAG,eAAe,CAAC;IAC/B,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,QAAQ,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,yBAAyB,CAAC;gBAC1D,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,yBAAyB,EAAE,+CAA+C,CAAC;gBAC5F,CAAC,CAAC,MAAM,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,eAAe,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,sBAAsB,CACpB,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAC9D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAA2B;IAC9D,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,eAAe,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,eAAuB,EACvB,KAA2B;IAE3B,kBAAkB,CAAC,wBAAwB,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport { existsSync, readFileSync, renameSync, rmSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { effectiveStateDir } from \"./cli/arg-grammar.js\";\nimport { readEnv } from \"./utils/env.js\";\nimport { ensureDirExists, readJsonSchemaFileIfExists } from \"./utils/file-guards.js\";\nimport { atomicWritePrivateFile } from \"./utils/fs-atomic.js\";\nimport * as log from \"./log.js\";\n\nexport class MissingGlobalSettingsError extends Error {\n constructor(public readonly settingsPath: string) {\n super(`Missing global settings file at ${settingsPath}`);\n this.name = \"MissingGlobalSettingsError\";\n }\n}\n\nexport type { AgentConfig, AutoReplyConfig, JudgeModelConfig, SandboxSettings } from \"./types.js\";\nimport type { AgentConfig, AutoReplyConfig, JudgeModelConfig, SandboxSettings } from \"./types.js\";\n\nconst ONBOARD_SETTINGS: SettingsFileConfig = {\n llm: {\n provider: \"anthropic\",\n model: \"claude-sonnet-4-6\",\n thinkingLevel: \"off\",\n autoReply: {\n provider: \"anthropic\",\n model: \"claude-haiku-4-5\",\n },\n },\n slack: {\n replyMode: \"top-level\",\n },\n sandbox: {\n cpus: \"0.5\",\n memory: \"1g\",\n boost: {\n cpus: \"2\",\n memory: \"4g\",\n },\n image: {\n workspaceMount: \"private\",\n },\n defaultSharedVault: \"\",\n },\n};\n\nconst SettingsFileSchema = Type.Object({\n llm: Type.Optional(\n Type.Object({\n provider: Type.Optional(Type.String()),\n model: Type.Optional(Type.String()),\n thinkingLevel: Type.Optional(\n Type.Union([\n Type.Literal(\"off\"),\n Type.Literal(\"minimal\"),\n Type.Literal(\"low\"),\n Type.Literal(\"medium\"),\n Type.Literal(\"high\"),\n Type.Literal(\"xhigh\"),\n Type.Literal(\"max\"),\n ]),\n ),\n autoReply: Type.Optional(\n Type.Object({\n provider: Type.Optional(Type.String()),\n model: Type.Optional(Type.String()),\n }),\n ),\n }),\n ),\n sentry: Type.Optional(\n Type.Object({\n dsn: Type.Optional(Type.String()),\n }),\n ),\n slack: Type.Optional(\n Type.Object({\n replyMode: Type.Optional(Type.Union([Type.Literal(\"top-level\"), Type.Literal(\"thread\")])),\n }),\n ),\n sandbox: Type.Optional(\n Type.Object({\n cpus: Type.Optional(Type.String()),\n memory: Type.Optional(Type.String()),\n boost: Type.Optional(\n Type.Object({\n cpus: Type.Optional(Type.String()),\n memory: Type.Optional(Type.String()),\n }),\n ),\n image: Type.Optional(\n Type.Object({\n workspaceMount: Type.Optional(\n Type.Union([Type.Literal(\"private\"), Type.Literal(\"full\")]),\n ),\n }),\n ),\n agentSandbox: Type.Optional(\n Type.Object({\n namespace: Type.String(),\n runtimeClassName: Type.String(),\n apiUrl: Type.Optional(Type.String()),\n routerNamespace: Type.Optional(Type.String()),\n sandboxReadyTimeout: Type.Optional(Type.Number()),\n }),\n ),\n defaultSharedVault: Type.Optional(Type.String()),\n }),\n ),\n autoReply: Type.Optional(\n Type.Object({\n enabled: Type.Optional(Type.Boolean()),\n rules: Type.Optional(Type.Array(Type.String())),\n }),\n ),\n});\n\ntype SettingsFileConfig = Static<typeof SettingsFileSchema>;\n\nfunction loadSettingsFile(settingsPath: string): SettingsFileConfig | undefined {\n return readJsonSchemaFileIfExists(settingsPath, SettingsFileSchema, (detail) =>\n detail === \"unexpected JSON shape\"\n ? `Malformed settings file at ${settingsPath}: expected a JSON object at the top level`\n : `Malformed settings file at ${settingsPath}: ${detail}`,\n );\n}\n\nfunction getStateDir(): string {\n return effectiveStateDir();\n}\n\nfunction normalizeSettingsConfig(config: SettingsFileConfig): Partial<AgentConfig> {\n return {\n ...(config.llm?.provider !== undefined ? { provider: config.llm.provider } : {}),\n ...(config.llm?.model !== undefined ? { model: config.llm.model } : {}),\n ...(config.llm?.thinkingLevel !== undefined ? { thinkingLevel: config.llm.thinkingLevel } : {}),\n ...(config.sentry?.dsn !== undefined ? { sentryDsn: config.sentry.dsn } : {}),\n ...(config.sandbox !== undefined ? { sandbox: normalizeSandboxSettings(config.sandbox) } : {}),\n ...(config.slack !== undefined ? { slack: config.slack } : {}),\n };\n}\n\n/**\n * File shape → in-memory shape for the sandbox group. An empty or\n * whitespace-only `defaultSharedVault` means \"no default\" and is dropped;\n * non-empty values are trimmed. Everything else passes through as-is.\n */\nfunction normalizeSandboxSettings(sandbox: SandboxSettings): SandboxSettings {\n const defaultSharedVault = sandbox.defaultSharedVault?.trim();\n return {\n ...(sandbox.cpus !== undefined ? { cpus: sandbox.cpus } : {}),\n ...(sandbox.memory !== undefined ? { memory: sandbox.memory } : {}),\n ...(sandbox.boost !== undefined ? { boost: sandbox.boost } : {}),\n ...(sandbox.image !== undefined ? { image: sandbox.image } : {}),\n ...(sandbox.agentSandbox !== undefined ? { agentSandbox: sandbox.agentSandbox } : {}),\n ...(defaultSharedVault ? { defaultSharedVault } : {}),\n };\n}\n\n/**\n * Merge two sandbox settings groups. The merge invariant is LEAF-LEVEL:\n * an override that only sets `sandbox.memory` keeps the base `sandbox.cpus`,\n * and an override that only sets `boost.memory` keeps the base `boost.cpus`\n * (same for `image`). This mirrors how the fields merged when they were\n * flat top-level keys; a group-level spread would silently drop base leaves.\n */\nfunction mergeSandboxSettings(\n base: SandboxSettings | undefined,\n override: SandboxSettings | undefined,\n): SandboxSettings | undefined {\n if (!base) return override;\n if (!override) return base;\n return {\n ...base,\n ...override,\n ...(base.boost || override.boost ? { boost: { ...base.boost, ...override.boost } } : {}),\n ...(base.image || override.image ? { image: { ...base.image, ...override.image } } : {}),\n ...(override.agentSandbox\n ? { agentSandbox: override.agentSandbox }\n : base.agentSandbox\n ? { agentSandbox: base.agentSandbox }\n : {}),\n };\n}\n\nfunction getSettingsPath(): string {\n return join(getStateDir(), \"settings.json\");\n}\n\nfunction requireGlobalSettings(): SettingsFileConfig {\n const settingsPath = getSettingsPath();\n const config = loadSettingsFile(settingsPath);\n if (!config) {\n throw new MissingGlobalSettingsError(settingsPath);\n }\n return config;\n}\n\nfunction requireString(value: string | undefined, path: string): string {\n if (!value) {\n throw new Error(\n `Missing required global setting: ${path}. Run \\`mikan --onboard\\` to create settings.json.`,\n );\n }\n return value;\n}\n\nfunction requireThinkingLevel(value: ThinkingLevel | undefined): ThinkingLevel {\n return requireString(value, \"llm.thinkingLevel\") as ThinkingLevel;\n}\n\nfunction toAgentConfig(fromFile: Partial<AgentConfig>): AgentConfig {\n const provider = requireString(fromFile.provider, \"llm.provider\");\n const model = requireString(fromFile.model, \"llm.model\");\n const thinkingLevel = requireThinkingLevel(fromFile.thinkingLevel);\n const sentryDsn = sentryDsnFrom(fromFile.sentryDsn);\n const sandbox = fromFile.sandbox;\n const slack = fromFile.slack;\n\n return {\n provider,\n model,\n thinkingLevel,\n sentryDsn,\n sandbox,\n slack,\n };\n}\n\nfunction loadRawGlobalSettings(): Partial<AgentConfig> {\n return normalizeSettingsConfig(requireGlobalSettings());\n}\n\nexport function loadGlobalSettings(): AgentConfig {\n return toAgentConfig(loadRawGlobalSettings());\n}\n\n/**\n * Host-authoritative location of a conversation's settings file:\n * `<stateDir>/conversations/<conversationId>/settings.json`.\n *\n * Conversation settings used to live at `<conversationDir>/settings.json`,\n * but conversation dirs are bind-mounted read-write into sandbox containers\n * in image mode — code inside the sandbox could edit its own settings.json\n * and flip `sandbox.image.workspaceMount` to \"full\", remounting the entire\n * workspace into its container (cross-conversation access). Settings are an\n * administrator surface, so they live under the host-only state dir.\n *\n * Migration: on first access per conversation, a legacy\n * `<conversationDir>/settings.json` is moved here. The new file's existence\n * (an empty `{}` is written when there is nothing to migrate) is the\n * migration marker — a legacy file (re)appearing later, e.g. planted from\n * inside the sandbox, is never read again.\n */\nexport function conversationSettingsPath(conversationDir: string): string {\n const conversationId = basename(resolve(conversationDir));\n const hostPath = join(getStateDir(), \"conversations\", conversationId, \"settings.json\");\n if (existsSync(hostPath)) return hostPath;\n\n ensureDirExists(dirname(hostPath));\n const legacyPath = join(conversationDir, \"settings.json\");\n let content = \"{}\\n\";\n let migrated = false;\n if (existsSync(legacyPath)) {\n try {\n content = readFileSync(legacyPath, \"utf-8\");\n migrated = true;\n } catch (err) {\n log.logWarning(`Could not read legacy conversation settings: ${legacyPath}`, String(err));\n }\n }\n atomicWritePrivateFile(hostPath, content);\n if (migrated) {\n try {\n rmSync(legacyPath);\n } catch (err) {\n log.logWarning(`Could not remove legacy conversation settings: ${legacyPath}`, String(err));\n }\n log.logInfo(`Migrated conversation settings to host-only path: ${hostPath}`);\n }\n return hostPath;\n}\n\nexport function resolveConversationSettings(conversationDir: string): AgentConfig {\n const globalConfig = loadRawGlobalSettings();\n const conversationConfig = normalizeSettingsConfig(\n loadSettingsFile(conversationSettingsPath(conversationDir)) ?? {},\n );\n // The sandbox group merges at the leaf level (see mergeSandboxSettings):\n // a conversation that only sets sandbox.memory keeps the global sandbox.cpus.\n const sandbox = mergeSandboxSettings(globalConfig.sandbox, conversationConfig.sandbox);\n return toAgentConfig({\n ...globalConfig,\n ...conversationConfig,\n ...(sandbox ? { sandbox } : {}),\n });\n}\n\n/**\n * Resolve the model used to judge auto-reply rules. Falls back to the main\n * llm.{provider,model} when llm.autoReply is not set, so a missing override\n * keeps current behavior.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function loadAutoReplyJudgeModel(conversationDir?: string): JudgeModelConfig {\n const global = requireGlobalSettings();\n const local = conversationDir\n ? (loadSettingsFile(conversationSettingsPath(conversationDir)) ?? {})\n : {};\n const merged: SettingsFileConfig[\"llm\"] = { ...global.llm, ...local.llm };\n const judge = { ...global.llm?.autoReply, ...local.llm?.autoReply };\n const provider = requireString(judge.provider ?? merged?.provider, \"llm.autoReply.provider\");\n const model = requireString(judge.model ?? merged?.model, \"llm.autoReply.model\");\n return { provider, model };\n}\n\nconst AUTO_REPLY_FILE = \"auto-reply\";\nconst AUTO_REPLY_DISABLED_FILE = \"auto-reply.disabled\";\n\nfunction readAutoReplyRulesFile(path: string): string[] {\n const text = readFileSync(path, \"utf-8\").trim();\n return text ? [text] : [];\n}\n\n/**\n * Load the mom-compatible auto-reply marker file state for a conversation.\n *\n * - `auto-reply` exists: enabled; empty file means reply to any top-level message.\n * - `auto-reply.disabled` exists: disabled, preserving any rules text for re-enable.\n * - neither exists: disabled.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function loadConversationAutoReplyConfig(conversationDir: string): AutoReplyConfig {\n const enabledPath = join(conversationDir, AUTO_REPLY_FILE);\n if (existsSync(enabledPath)) {\n return { enabled: true, rules: readAutoReplyRulesFile(enabledPath) };\n }\n\n const disabledPath = join(conversationDir, AUTO_REPLY_DISABLED_FILE);\n if (existsSync(disabledPath)) {\n return { enabled: false, rules: readAutoReplyRulesFile(disabledPath) };\n }\n\n return { enabled: false, rules: [] };\n}\n\n/**\n * Save auto-reply state using mom-compatible marker files.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function saveConversationAutoReplyConfig(\n conversationDir: string,\n config: AutoReplyConfig,\n): void {\n ensureDirExists(conversationDir);\n\n const enabledPath = join(conversationDir, AUTO_REPLY_FILE);\n const disabledPath = join(conversationDir, AUTO_REPLY_DISABLED_FILE);\n const targetPath = config.enabled ? enabledPath : disabledPath;\n const otherPath = config.enabled ? disabledPath : enabledPath;\n\n if (existsSync(otherPath)) {\n renameSync(otherPath, targetPath);\n }\n\n atomicWritePrivateFile(targetPath, config.rules.join(\"\\n\"));\n}\n\n/**\n * True when `child` is `parent` or a path inside it. Purely lexical (no\n * symlink resolution) — used for configuration sanity checks, not as the\n * final security boundary.\n */\nexport function isPathInside(child: string, parent: string): boolean {\n const parentPath = resolve(parent);\n const childPath = resolve(child);\n return childPath === parentPath || childPath.startsWith(parentPath + \"/\");\n}\n\n/**\n * The state dir (extensions code, extension data, vaults, auth.json) must\n * never live inside the working dir: conversation opt-in \"full\" mode mounts\n * the entire working dir read-write into sandbox containers, and a mounted\n * state dir would let sandboxed code plant extension modules that the host\n * process later imports — a sandbox escape. Fatal under sandboxed modes;\n * host mode has no mounts, so only warn about the bad hygiene.\n */\nexport function assertStateDirOutsideWorkspace(\n stateDir: string,\n workingDir: string,\n sandboxType: string,\n): void {\n if (!isPathInside(stateDir, workingDir)) return;\n const message =\n `--state-dir (${stateDir}) must not be inside the working directory (${workingDir}): ` +\n `sandbox containers mount the working directory, and a mounted state dir ` +\n `would expose extensions, vaults, and credentials to sandboxed code.`;\n if (sandboxType === \"host\") {\n log.logWarning(\"Insecure state dir location\", message);\n return;\n }\n throw new Error(message);\n}\n\n/** Settings-file DSN wins over SENTRY_DSN env — the rule lives only here. */\nfunction sentryDsnFrom(fromFile: string | undefined): string | undefined {\n return fromFile || readEnv(\"SENTRY_DSN\");\n}\n\nexport function resolveSentryDsn(): string | undefined {\n const fromFile = normalizeSettingsConfig(loadSettingsFile(getSettingsPath()) ?? {});\n return sentryDsnFrom(fromFile.sentryDsn);\n}\n\nexport function createGlobalSettingsFile(stateDir: string): string {\n const settingsPath = join(stateDir, \"settings.json\");\n if (existsSync(settingsPath)) {\n throw new Error(`Global settings already exists at ${settingsPath}`);\n }\n ensureDirExists(stateDir);\n atomicWritePrivateFile(settingsPath, JSON.stringify(ONBOARD_SETTINGS, null, 2));\n return settingsPath;\n}\n\n/**\n * Externally-visible base URL of the link/OAuth server, e.g.\n * `https://mikan.example.com` (no trailing slash). Read from `LINK_URL` or\n * `MIKAN_LINK_URL`, the same env var the bot uses to build credential onboarding links.\n */\nexport function resolveLinkBaseUrl(): string | undefined {\n const raw = readEnv(\"LINK_URL\");\n if (!raw) return undefined;\n return raw.replace(/\\/+$/, \"\");\n}\n\nfunction hasDefinedValue(values: Record<string, unknown> | undefined): boolean {\n return values !== undefined && Object.values(values).some((value) => value !== undefined);\n}\n\nfunction compactSettingsConfig(config: SettingsFileConfig): SettingsFileConfig {\n return {\n ...(hasDefinedValue(config.llm) ? { llm: config.llm } : {}),\n ...(hasDefinedValue(config.sentry) ? { sentry: config.sentry } : {}),\n ...(hasDefinedValue(config.sandbox) ? { sandbox: config.sandbox } : {}),\n ...(hasDefinedValue(config.autoReply) ? { autoReply: config.autoReply } : {}),\n ...(hasDefinedValue(config.slack) ? { slack: config.slack } : {}),\n };\n}\n\nfunction patchSettingsConfig(\n existing: SettingsFileConfig,\n config: Partial<AgentConfig>,\n): SettingsFileConfig {\n const patched: SettingsFileConfig = {\n ...existing,\n llm: {\n ...existing.llm,\n ...(config.provider !== undefined ? { provider: config.provider } : {}),\n ...(config.model !== undefined ? { model: config.model } : {}),\n ...(config.thinkingLevel !== undefined ? { thinkingLevel: config.thinkingLevel } : {}),\n },\n sentry: {\n ...existing.sentry,\n ...(config.sentryDsn !== undefined ? { dsn: config.sentryDsn } : {}),\n },\n // Leaf-level merge: a patch that only sets sandbox.boost.memory keeps the\n // existing boost.cpus (and every other existing leaf). compactSettingsConfig\n // drops the group entirely when it ends up with no defined values.\n sandbox: mergeSandboxSettings(existing.sandbox, config.sandbox) ?? {},\n slack: {\n ...existing.slack,\n ...config.slack,\n },\n };\n return compactSettingsConfig(patched);\n}\n\nfunction updateSettingsFile(\n settingsPath: string,\n patch: Partial<AgentConfig>,\n defaultSettings: SettingsFileConfig,\n): void {\n let existing = defaultSettings;\n if (existsSync(settingsPath)) {\n try {\n existing = loadSettingsFile(settingsPath) ?? {};\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n const message = detail.startsWith(\"Malformed settings file\")\n ? detail.replace(\"Malformed settings file\", \"Refusing to overwrite malformed settings file\")\n : detail;\n throw new Error(message, { cause: err });\n }\n }\n\n ensureDirExists(dirname(settingsPath));\n atomicWritePrivateFile(\n settingsPath,\n JSON.stringify(patchSettingsConfig(existing, patch), null, 2),\n );\n}\n\nexport function updateGlobalSettings(patch: Partial<AgentConfig>): void {\n updateSettingsFile(join(getStateDir(), \"settings.json\"), patch, ONBOARD_SETTINGS);\n}\n\nexport function updateConversationSettings(\n conversationDir: string,\n patch: Partial<AgentConfig>,\n): void {\n updateSettingsFile(conversationSettingsPath(conversationDir), patch, {});\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { Type, type Static } from \"@sinclair/typebox\";\nimport { existsSync, readFileSync, renameSync, rmSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { effectiveStateDir } from \"./cli/arg-grammar.js\";\nimport { readEnv } from \"./utils/env.js\";\nimport { ensureDirExists, readJsonSchemaFileIfExists } from \"./utils/file-guards.js\";\nimport { atomicWritePrivateFile } from \"./utils/fs-atomic.js\";\nimport * as log from \"./log.js\";\n\nexport class MissingGlobalSettingsError extends Error {\n constructor(public readonly settingsPath: string) {\n super(`Missing global settings file at ${settingsPath}`);\n this.name = \"MissingGlobalSettingsError\";\n }\n}\n\nexport type { AgentConfig, AutoReplyConfig, JudgeModelConfig, SandboxSettings } from \"./types.js\";\nimport type { AgentConfig, AutoReplyConfig, JudgeModelConfig, SandboxSettings } from \"./types.js\";\n\nconst ONBOARD_SETTINGS: SettingsFileConfig = {\n llm: {\n provider: \"anthropic\",\n model: \"claude-sonnet-4-6\",\n thinkingLevel: \"off\",\n autoReply: {\n provider: \"anthropic\",\n model: \"claude-haiku-4-5\",\n },\n },\n slack: {\n replyMode: \"top-level\",\n },\n sandbox: {\n cpus: \"0.5\",\n memory: \"1g\",\n boost: {\n cpus: \"2\",\n memory: \"4g\",\n },\n image: {\n workspaceMount: \"private\",\n },\n defaultSharedVault: \"\",\n },\n};\n\nconst SettingsFileSchema = Type.Object({\n llm: Type.Optional(\n Type.Object({\n provider: Type.Optional(Type.String()),\n model: Type.Optional(Type.String()),\n thinkingLevel: Type.Optional(\n Type.Union([\n Type.Literal(\"off\"),\n Type.Literal(\"minimal\"),\n Type.Literal(\"low\"),\n Type.Literal(\"medium\"),\n Type.Literal(\"high\"),\n Type.Literal(\"xhigh\"),\n Type.Literal(\"max\"),\n ]),\n ),\n autoReply: Type.Optional(\n Type.Object({\n provider: Type.Optional(Type.String()),\n model: Type.Optional(Type.String()),\n }),\n ),\n }),\n ),\n sentry: Type.Optional(\n Type.Object({\n dsn: Type.Optional(Type.String()),\n }),\n ),\n slack: Type.Optional(\n Type.Object({\n replyMode: Type.Optional(Type.Union([Type.Literal(\"top-level\"), Type.Literal(\"thread\")])),\n }),\n ),\n sandbox: Type.Optional(\n Type.Object({\n cpus: Type.Optional(Type.String()),\n memory: Type.Optional(Type.String()),\n boost: Type.Optional(\n Type.Object({\n cpus: Type.Optional(Type.String()),\n memory: Type.Optional(Type.String()),\n }),\n ),\n image: Type.Optional(\n Type.Object({\n workspaceMount: Type.Optional(\n Type.Union([Type.Literal(\"private\"), Type.Literal(\"full\")]),\n ),\n }),\n ),\n gondolin: Type.Optional(\n Type.Object({\n remote: Type.Optional(\n Type.Object({\n url: Type.Optional(Type.String()),\n caFile: Type.Optional(Type.String()),\n certFile: Type.Optional(Type.String()),\n keyFile: Type.Optional(Type.String()),\n workspaceRoot: Type.Optional(Type.String()),\n maxRuntimes: Type.Optional(Type.Number()),\n imageSelector: Type.Optional(Type.String()),\n queueWaitSeconds: Type.Optional(Type.Number()),\n workers: Type.Optional(\n Type.Array(\n Type.Object({\n name: Type.Optional(Type.String()),\n url: Type.String(),\n caFile: Type.Optional(Type.String()),\n certFile: Type.Optional(Type.String()),\n keyFile: Type.Optional(Type.String()),\n workspaceRoot: Type.Optional(Type.String()),\n maxRuntimes: Type.Optional(Type.Number()),\n draining: Type.Optional(Type.Boolean()),\n }),\n ),\n ),\n gateway: Type.Optional(\n Type.Object({\n port: Type.Number(),\n certFile: Type.Optional(Type.String()),\n keyFile: Type.Optional(Type.String()),\n clientCaFile: Type.Optional(Type.String()),\n hostnames: Type.Optional(Type.Array(Type.String())),\n workspaceRoot: Type.Optional(Type.String()),\n workers: Type.Optional(\n Type.Record(\n Type.String(),\n Type.Object({\n maxRuntimes: Type.Optional(Type.Number()),\n draining: Type.Optional(Type.Boolean()),\n }),\n ),\n ),\n }),\n ),\n }),\n ),\n }),\n ),\n defaultSharedVault: Type.Optional(Type.String()),\n }),\n ),\n autoReply: Type.Optional(\n Type.Object({\n enabled: Type.Optional(Type.Boolean()),\n rules: Type.Optional(Type.Array(Type.String())),\n }),\n ),\n});\n\ntype SettingsFileConfig = Static<typeof SettingsFileSchema>;\n\nfunction loadSettingsFile(settingsPath: string): SettingsFileConfig | undefined {\n return readJsonSchemaFileIfExists(settingsPath, SettingsFileSchema, (detail) =>\n detail === \"unexpected JSON shape\"\n ? `Malformed settings file at ${settingsPath}: expected a JSON object at the top level`\n : `Malformed settings file at ${settingsPath}: ${detail}`,\n );\n}\n\nfunction getStateDir(): string {\n return effectiveStateDir();\n}\n\nfunction normalizeSettingsConfig(config: SettingsFileConfig): Partial<AgentConfig> {\n return {\n ...(config.llm?.provider !== undefined ? { provider: config.llm.provider } : {}),\n ...(config.llm?.model !== undefined ? { model: config.llm.model } : {}),\n ...(config.llm?.thinkingLevel !== undefined ? { thinkingLevel: config.llm.thinkingLevel } : {}),\n ...(config.sentry?.dsn !== undefined ? { sentryDsn: config.sentry.dsn } : {}),\n ...(config.sandbox !== undefined ? { sandbox: normalizeSandboxSettings(config.sandbox) } : {}),\n ...(config.slack !== undefined ? { slack: config.slack } : {}),\n };\n}\n\n/**\n * File shape → in-memory shape for the sandbox group. An empty or\n * whitespace-only `defaultSharedVault` means \"no default\" and is dropped;\n * non-empty values are trimmed. Everything else passes through as-is.\n */\nfunction normalizeSandboxSettings(sandbox: SandboxSettings): SandboxSettings {\n const defaultSharedVault = sandbox.defaultSharedVault?.trim();\n return {\n ...(sandbox.cpus !== undefined ? { cpus: sandbox.cpus } : {}),\n ...(sandbox.memory !== undefined ? { memory: sandbox.memory } : {}),\n ...(sandbox.boost !== undefined ? { boost: sandbox.boost } : {}),\n ...(sandbox.image !== undefined ? { image: sandbox.image } : {}),\n ...(sandbox.gondolin !== undefined ? { gondolin: sandbox.gondolin } : {}),\n ...(defaultSharedVault ? { defaultSharedVault } : {}),\n };\n}\n\n/**\n * Merge two sandbox settings groups. The merge invariant is LEAF-LEVEL:\n * an override that only sets `sandbox.memory` keeps the base `sandbox.cpus`,\n * and an override that only sets `boost.memory` keeps the base `boost.cpus`\n * (same for `image`). This mirrors how the fields merged when they were\n * flat top-level keys; a group-level spread would silently drop base leaves.\n */\nfunction mergeSandboxSettings(\n base: SandboxSettings | undefined,\n override: SandboxSettings | undefined,\n): SandboxSettings | undefined {\n if (!base) return override;\n if (!override) return base;\n return {\n ...base,\n ...override,\n ...(base.boost || override.boost ? { boost: { ...base.boost, ...override.boost } } : {}),\n ...(base.image || override.image ? { image: { ...base.image, ...override.image } } : {}),\n // `remote` is one connection description; merging two halves of it would\n // pair a URL with the wrong certificates, so the override wins wholesale.\n ...(base.gondolin || override.gondolin\n ? { gondolin: { ...base.gondolin, ...override.gondolin } }\n : {}),\n };\n}\n\nfunction getSettingsPath(): string {\n return join(getStateDir(), \"settings.json\");\n}\n\nfunction requireGlobalSettings(): SettingsFileConfig {\n const settingsPath = getSettingsPath();\n const config = loadSettingsFile(settingsPath);\n if (!config) {\n throw new MissingGlobalSettingsError(settingsPath);\n }\n return config;\n}\n\nfunction requireString(value: string | undefined, path: string): string {\n if (!value) {\n throw new Error(\n `Missing required global setting: ${path}. Run \\`mikan --onboard\\` to create settings.json.`,\n );\n }\n return value;\n}\n\nfunction requireThinkingLevel(value: ThinkingLevel | undefined): ThinkingLevel {\n return requireString(value, \"llm.thinkingLevel\") as ThinkingLevel;\n}\n\nfunction toAgentConfig(fromFile: Partial<AgentConfig>): AgentConfig {\n const provider = requireString(fromFile.provider, \"llm.provider\");\n const model = requireString(fromFile.model, \"llm.model\");\n const thinkingLevel = requireThinkingLevel(fromFile.thinkingLevel);\n const sentryDsn = sentryDsnFrom(fromFile.sentryDsn);\n const sandbox = fromFile.sandbox;\n const slack = fromFile.slack;\n\n return {\n provider,\n model,\n thinkingLevel,\n sentryDsn,\n sandbox,\n slack,\n };\n}\n\nfunction loadRawGlobalSettings(): Partial<AgentConfig> {\n return normalizeSettingsConfig(requireGlobalSettings());\n}\n\nexport function loadGlobalSettings(): AgentConfig {\n return toAgentConfig(loadRawGlobalSettings());\n}\n\n/**\n * Host-authoritative location of a conversation's settings file:\n * `<stateDir>/conversations/<conversationId>/settings.json`.\n *\n * Conversation settings used to live at `<conversationDir>/settings.json`,\n * but conversation dirs are bind-mounted read-write into sandbox containers\n * in image mode — code inside the sandbox could edit its own settings.json\n * and flip `sandbox.image.workspaceMount` to \"full\", remounting the entire\n * workspace into its container (cross-conversation access). Settings are an\n * administrator surface, so they live under the host-only state dir.\n *\n * Migration: on first access per conversation, a legacy\n * `<conversationDir>/settings.json` is moved here. The new file's existence\n * (an empty `{}` is written when there is nothing to migrate) is the\n * migration marker — a legacy file (re)appearing later, e.g. planted from\n * inside the sandbox, is never read again.\n */\nexport function conversationSettingsPath(conversationDir: string): string {\n const conversationId = basename(resolve(conversationDir));\n const hostPath = join(getStateDir(), \"conversations\", conversationId, \"settings.json\");\n if (existsSync(hostPath)) return hostPath;\n\n ensureDirExists(dirname(hostPath));\n const legacyPath = join(conversationDir, \"settings.json\");\n let content = \"{}\\n\";\n let migrated = false;\n if (existsSync(legacyPath)) {\n try {\n content = readFileSync(legacyPath, \"utf-8\");\n migrated = true;\n } catch (err) {\n log.logWarning(`Could not read legacy conversation settings: ${legacyPath}`, String(err));\n }\n }\n atomicWritePrivateFile(hostPath, content);\n if (migrated) {\n try {\n rmSync(legacyPath);\n } catch (err) {\n log.logWarning(`Could not remove legacy conversation settings: ${legacyPath}`, String(err));\n }\n log.logInfo(`Migrated conversation settings to host-only path: ${hostPath}`);\n }\n return hostPath;\n}\n\nexport function resolveConversationSettings(conversationDir: string): AgentConfig {\n const globalConfig = loadRawGlobalSettings();\n const conversationConfig = normalizeSettingsConfig(\n loadSettingsFile(conversationSettingsPath(conversationDir)) ?? {},\n );\n // The sandbox group merges at the leaf level (see mergeSandboxSettings):\n // a conversation that only sets sandbox.memory keeps the global sandbox.cpus.\n const sandbox = mergeSandboxSettings(globalConfig.sandbox, conversationConfig.sandbox);\n return toAgentConfig({\n ...globalConfig,\n ...conversationConfig,\n ...(sandbox ? { sandbox } : {}),\n });\n}\n\n/**\n * Resolve the model used to judge auto-reply rules. Falls back to the main\n * llm.{provider,model} when llm.autoReply is not set, so a missing override\n * keeps current behavior.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function loadAutoReplyJudgeModel(conversationDir?: string): JudgeModelConfig {\n const global = requireGlobalSettings();\n const local = conversationDir\n ? (loadSettingsFile(conversationSettingsPath(conversationDir)) ?? {})\n : {};\n const merged: SettingsFileConfig[\"llm\"] = { ...global.llm, ...local.llm };\n const judge = { ...global.llm?.autoReply, ...local.llm?.autoReply };\n const provider = requireString(judge.provider ?? merged?.provider, \"llm.autoReply.provider\");\n const model = requireString(judge.model ?? merged?.model, \"llm.autoReply.model\");\n return { provider, model };\n}\n\nconst AUTO_REPLY_FILE = \"auto-reply\";\nconst AUTO_REPLY_DISABLED_FILE = \"auto-reply.disabled\";\n\nfunction readAutoReplyRulesFile(path: string): string[] {\n const text = readFileSync(path, \"utf-8\").trim();\n return text ? [text] : [];\n}\n\n/**\n * Load the mom-compatible auto-reply marker file state for a conversation.\n *\n * - `auto-reply` exists: enabled; empty file means reply to any top-level message.\n * - `auto-reply.disabled` exists: disabled, preserving any rules text for re-enable.\n * - neither exists: disabled.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function loadConversationAutoReplyConfig(conversationDir: string): AutoReplyConfig {\n const enabledPath = join(conversationDir, AUTO_REPLY_FILE);\n if (existsSync(enabledPath)) {\n return { enabled: true, rules: readAutoReplyRulesFile(enabledPath) };\n }\n\n const disabledPath = join(conversationDir, AUTO_REPLY_DISABLED_FILE);\n if (existsSync(disabledPath)) {\n return { enabled: false, rules: readAutoReplyRulesFile(disabledPath) };\n }\n\n return { enabled: false, rules: [] };\n}\n\n/**\n * Save auto-reply state using mom-compatible marker files.\n *\n * @deprecated Auto-reply is kept for compatibility while its future is undecided.\n */\nexport function saveConversationAutoReplyConfig(\n conversationDir: string,\n config: AutoReplyConfig,\n): void {\n ensureDirExists(conversationDir);\n\n const enabledPath = join(conversationDir, AUTO_REPLY_FILE);\n const disabledPath = join(conversationDir, AUTO_REPLY_DISABLED_FILE);\n const targetPath = config.enabled ? enabledPath : disabledPath;\n const otherPath = config.enabled ? disabledPath : enabledPath;\n\n if (existsSync(otherPath)) {\n renameSync(otherPath, targetPath);\n }\n\n atomicWritePrivateFile(targetPath, config.rules.join(\"\\n\"));\n}\n\n/**\n * True when `child` is `parent` or a path inside it. Purely lexical (no\n * symlink resolution) — used for configuration sanity checks, not as the\n * final security boundary.\n */\nexport function isPathInside(child: string, parent: string): boolean {\n const parentPath = resolve(parent);\n const childPath = resolve(child);\n return childPath === parentPath || childPath.startsWith(parentPath + \"/\");\n}\n\n/**\n * The state dir (extensions code, extension data, vaults, auth.json) must\n * never live inside the working dir: conversation opt-in \"full\" mode mounts\n * the entire working dir read-write into sandbox containers, and a mounted\n * state dir would let sandboxed code plant extension modules that the host\n * process later imports — a sandbox escape. Fatal under sandboxed modes;\n * host mode has no mounts, so only warn about the bad hygiene.\n */\nexport function assertStateDirOutsideWorkspace(\n stateDir: string,\n workingDir: string,\n sandboxType: string,\n): void {\n if (!isPathInside(stateDir, workingDir)) return;\n const message =\n `--state-dir (${stateDir}) must not be inside the working directory (${workingDir}): ` +\n `sandbox containers mount the working directory, and a mounted state dir ` +\n `would expose extensions, vaults, and credentials to sandboxed code.`;\n if (sandboxType === \"host\") {\n log.logWarning(\"Insecure state dir location\", message);\n return;\n }\n throw new Error(message);\n}\n\n/** Settings-file DSN wins over SENTRY_DSN env — the rule lives only here. */\nfunction sentryDsnFrom(fromFile: string | undefined): string | undefined {\n return fromFile || readEnv(\"SENTRY_DSN\");\n}\n\nexport function resolveSentryDsn(): string | undefined {\n const fromFile = normalizeSettingsConfig(loadSettingsFile(getSettingsPath()) ?? {});\n return sentryDsnFrom(fromFile.sentryDsn);\n}\n\nexport function createGlobalSettingsFile(stateDir: string): string {\n const settingsPath = join(stateDir, \"settings.json\");\n if (existsSync(settingsPath)) {\n throw new Error(`Global settings already exists at ${settingsPath}`);\n }\n ensureDirExists(stateDir);\n atomicWritePrivateFile(settingsPath, JSON.stringify(ONBOARD_SETTINGS, null, 2));\n return settingsPath;\n}\n\n/**\n * Externally-visible base URL of the link/OAuth server, e.g.\n * `https://mikan.example.com` (no trailing slash). Read from `LINK_URL` or\n * `MIKAN_LINK_URL`, the same env var the bot uses to build credential onboarding links.\n */\nexport function resolveLinkBaseUrl(): string | undefined {\n const raw = readEnv(\"LINK_URL\");\n if (!raw) return undefined;\n return raw.replace(/\\/+$/, \"\");\n}\n\nfunction hasDefinedValue(values: Record<string, unknown> | undefined): boolean {\n return values !== undefined && Object.values(values).some((value) => value !== undefined);\n}\n\nfunction compactSettingsConfig(config: SettingsFileConfig): SettingsFileConfig {\n return {\n ...(hasDefinedValue(config.llm) ? { llm: config.llm } : {}),\n ...(hasDefinedValue(config.sentry) ? { sentry: config.sentry } : {}),\n ...(hasDefinedValue(config.sandbox) ? { sandbox: config.sandbox } : {}),\n ...(hasDefinedValue(config.autoReply) ? { autoReply: config.autoReply } : {}),\n ...(hasDefinedValue(config.slack) ? { slack: config.slack } : {}),\n };\n}\n\nfunction patchSettingsConfig(\n existing: SettingsFileConfig,\n config: Partial<AgentConfig>,\n): SettingsFileConfig {\n const patched: SettingsFileConfig = {\n ...existing,\n llm: {\n ...existing.llm,\n ...(config.provider !== undefined ? { provider: config.provider } : {}),\n ...(config.model !== undefined ? { model: config.model } : {}),\n ...(config.thinkingLevel !== undefined ? { thinkingLevel: config.thinkingLevel } : {}),\n },\n sentry: {\n ...existing.sentry,\n ...(config.sentryDsn !== undefined ? { dsn: config.sentryDsn } : {}),\n },\n // Leaf-level merge: a patch that only sets sandbox.boost.memory keeps the\n // existing boost.cpus (and every other existing leaf). compactSettingsConfig\n // drops the group entirely when it ends up with no defined values.\n sandbox: mergeSandboxSettings(existing.sandbox, config.sandbox) ?? {},\n slack: {\n ...existing.slack,\n ...config.slack,\n },\n };\n return compactSettingsConfig(patched);\n}\n\nfunction updateSettingsFile(\n settingsPath: string,\n patch: Partial<AgentConfig>,\n defaultSettings: SettingsFileConfig,\n): void {\n let existing = defaultSettings;\n if (existsSync(settingsPath)) {\n try {\n existing = loadSettingsFile(settingsPath) ?? {};\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n const message = detail.startsWith(\"Malformed settings file\")\n ? detail.replace(\"Malformed settings file\", \"Refusing to overwrite malformed settings file\")\n : detail;\n throw new Error(message, { cause: err });\n }\n }\n\n ensureDirExists(dirname(settingsPath));\n atomicWritePrivateFile(\n settingsPath,\n JSON.stringify(patchSettingsConfig(existing, patch), null, 2),\n );\n}\n\nexport function updateGlobalSettings(patch: Partial<AgentConfig>): void {\n updateSettingsFile(join(getStateDir(), \"settings.json\"), patch, ONBOARD_SETTINGS);\n}\n\nexport function updateConversationSettings(\n conversationDir: string,\n patch: Partial<AgentConfig>,\n): void {\n updateSettingsFile(conversationSettingsPath(conversationDir), patch, {});\n}\n"]}
@@ -10,7 +10,8 @@ export declare class ActorExecutionResolver {
10
10
  private vaultManager;
11
11
  private provisioner?;
12
12
  private workspaceDir?;
13
- constructor(baseConfig: SandboxConfig, vaultManager: VaultManager, provisioner?: DockerContainerManager | undefined, workspaceDir?: string | undefined);
13
+ private hostWorkspacePath?;
14
+ constructor(baseConfig: SandboxConfig, vaultManager: VaultManager, provisioner?: DockerContainerManager | undefined, workspaceDir?: string | undefined, hostWorkspacePath?: string | undefined);
14
15
  resolve(context: ActorContext): Promise<Executor>;
15
16
  private resolvePlan;
16
17
  private ensureDefaultSharedVault;
@@ -1 +1 @@
1
- {"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAuB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAS/E,OAAO,EAEL,2BAA2B,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,kCAAkC,oCAA8B,CAAC;AAE9E,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,YAAY,CAAC;IAJvB,YACU,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,sBAAsB,YAAA,EACpC,YAAY,CAAC,EAAE,MAAM,YAAA,EAC3B;IAEE,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOtD;IAED,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,aAAa;CAwBtB"}
1
+ {"version":3,"file":"execution-resolver.d.ts","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAuB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAS/E,OAAO,EAEL,2BAA2B,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,kCAAkC,oCAA8B,CAAC;AAE9E,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,iBAAiB,CAAC;IAL5B,YACU,UAAU,EAAE,aAAa,EACzB,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,sBAAsB,YAAA,EACpC,YAAY,CAAC,EAAE,MAAM,YAAA,EACrB,iBAAiB,CAAC,EAAE,MAAM,YAAA,EAChC;IAEE,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOtD;IAED,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,oBAAoB;IAuB5B,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,aAAa;CAwBtB"}
@@ -10,11 +10,12 @@ import { credentialAuthorizationKey, legacyExactCredentialAuthorizationKey, runt
10
10
  import { resolveWorkspaceProjection, readWorkspaceProjectionMode, } from "./workspace-projection/index.js";
11
11
  export const readConversationWorkspaceMountMode = readWorkspaceProjectionMode;
12
12
  export class ActorExecutionResolver {
13
- constructor(baseConfig, vaultManager, provisioner, workspaceDir) {
13
+ constructor(baseConfig, vaultManager, provisioner, workspaceDir, hostWorkspacePath) {
14
14
  this.baseConfig = baseConfig;
15
15
  this.vaultManager = vaultManager;
16
16
  this.provisioner = provisioner;
17
17
  this.workspaceDir = workspaceDir;
18
+ this.hostWorkspacePath = hostWorkspacePath;
18
19
  }
19
20
  async resolve(context) {
20
21
  const plan = this.resolvePlan(context);
@@ -39,7 +40,7 @@ export class ActorExecutionResolver {
39
40
  return {
40
41
  credentialKey,
41
42
  resourceKey,
42
- sandboxConfig: this.resolveSandboxConfig(resourceKey, this.baseConfig.type === "agent-sandbox" ? injection.mounts : mounts),
43
+ sandboxConfig: this.resolveSandboxConfig(resourceKey, mounts),
43
44
  env: injection.env,
44
45
  mounts,
45
46
  };
@@ -69,11 +70,13 @@ export class ActorExecutionResolver {
69
70
  sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),
70
71
  };
71
72
  }
72
- if (this.baseConfig.type === "agent-sandbox") {
73
+ if (this.baseConfig.type === "gondolin") {
73
74
  return {
74
75
  ...this.baseConfig,
75
- resourceKey,
76
+ workspacePath: this.hostWorkspacePath,
76
77
  mounts,
78
+ instanceId: resourceKey,
79
+ resourceKey,
77
80
  };
78
81
  }
79
82
  if (this.baseConfig.type !== "image")
@@ -1 +1 @@
1
- {"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from \"node:path\";\nimport { loadGlobalSettings } from \"./config.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport {\n createExecutor,\n getSandboxCredentialCapabilities,\n type Executor,\n type SandboxConfig,\n} from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type VaultManager } from \"./vault/index.js\";\nimport { resolveVaultInjection } from \"./vault/injection.js\";\nimport { allowsAmbientDefaultSharedVault } from \"./vault/policy.js\";\nimport {\n credentialAuthorizationKey,\n legacyExactCredentialAuthorizationKey,\n runtimeResourceKey,\n scopeCloudflareSandboxId,\n} from \"./sandbox/identity.js\";\nimport {\n resolveWorkspaceProjection,\n readWorkspaceProjectionMode,\n} from \"./workspace-projection/index.js\";\n\nexport type { ActorContext } from \"./types.js\";\nimport type { ActorContext, ExecutionPlan } from \"./types.js\";\n\nexport const readConversationWorkspaceMountMode = readWorkspaceProjectionMode;\n\nexport class ActorExecutionResolver {\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const plan = this.resolvePlan(context);\n return createExecutor(\n plan.sandboxConfig,\n plan.env,\n this.buildEnsureReadyCallback(plan, context.conversationId),\n );\n }\n\n private resolvePlan(context: ActorContext): ExecutionPlan {\n const ids = { userId: context.userId, conversationId: context.conversationId };\n const credentialKey = credentialAuthorizationKey(this.baseConfig, ids);\n const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, ids);\n const resourceKey = runtimeResourceKey(this.baseConfig, ids);\n this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);\n\n const vault =\n this.vaultManager.resolve(credentialKey) ??\n (legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);\n const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);\n const injection = resolveVaultInjection({\n vault,\n capabilities,\n sandboxType: this.baseConfig.type,\n conversationId: context.conversationId,\n });\n const mounts = this.resolveMounts(context.conversationId, injection.mounts);\n return {\n credentialKey,\n resourceKey,\n sandboxConfig: this.resolveSandboxConfig(\n resourceKey,\n this.baseConfig.type === \"agent-sandbox\" ? injection.mounts : mounts,\n ),\n env: injection.env,\n mounts,\n };\n }\n\n private ensureDefaultSharedVault(\n credentialKey: string,\n legacyCredentialKey: string | undefined,\n trustModel: ActorContext[\"trustModel\"],\n ): void {\n if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type })) return;\n if (\n this.vaultManager.hasEntry(credentialKey) ||\n (legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))\n ) {\n return;\n }\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n this.vaultManager.copySharedVaultTo(profile, credentialKey);\n }\n\n private resolveSandboxConfig(resourceKey: string, mounts: ContainerMount[]): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),\n };\n }\n if (this.baseConfig.type === \"agent-sandbox\") {\n return {\n ...this.baseConfig,\n resourceKey,\n mounts,\n };\n }\n if (this.baseConfig.type !== \"image\") return this.baseConfig;\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(resourceKey),\n };\n }\n\n private buildEnsureReadyCallback(\n plan: ExecutionPlan,\n conversationId: string,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || plan.sandboxConfig.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = plan.sandboxConfig.type === \"container\" ? plan.sandboxConfig.container : \"\";\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(plan.resourceKey, {\n containerName: expected,\n mounts: plan.mounts,\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n conversationId,\n credentialKey: plan.credentialKey,\n resourceKey: plan.resourceKey,\n expectedContainer: expected,\n hasVault: Boolean(plan.env || plan.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for resource key \"${plan.resourceKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vaultMounts: ContainerMount[]): ContainerMount[] {\n const workspaceMounts = resolveWorkspaceProjection(this.workspaceDir, conversationId).mounts;\n for (let index = 0; index < vaultMounts.length; index += 1) {\n const vaultMount = vaultMounts[index];\n const workspaceCollision = workspaceMounts.find((workspaceMount) =>\n targetsOverlap(workspaceMount.target, vaultMount.target),\n );\n if (workspaceCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps protected workspace target \"${workspaceCollision.target}\"`,\n );\n }\n\n const vaultCollision = vaultMounts\n .slice(0, index)\n .find((other) => targetsOverlap(other.target, vaultMount.target));\n if (vaultCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps vault target \"${vaultCollision.target}\"`,\n );\n }\n }\n return [...workspaceMounts, ...vaultMounts];\n }\n}\n\nfunction targetsOverlap(left: string, right: string): boolean {\n const a = normalizeMountTarget(left);\n const b = normalizeMountTarget(right);\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction normalizeMountTarget(value: string): string {\n const normalized = posix.normalize(value);\n return normalized.replace(/\\/+$/, \"\") || \"/\";\n}\n"]}
1
+ {"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from \"node:path\";\nimport { loadGlobalSettings } from \"./config.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport {\n createExecutor,\n getSandboxCredentialCapabilities,\n type Executor,\n type SandboxConfig,\n} from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type VaultManager } from \"./vault/index.js\";\nimport { resolveVaultInjection } from \"./vault/injection.js\";\nimport { allowsAmbientDefaultSharedVault } from \"./vault/policy.js\";\nimport {\n credentialAuthorizationKey,\n legacyExactCredentialAuthorizationKey,\n runtimeResourceKey,\n scopeCloudflareSandboxId,\n} from \"./sandbox/identity.js\";\nimport {\n resolveWorkspaceProjection,\n readWorkspaceProjectionMode,\n} from \"./workspace-projection/index.js\";\n\nexport type { ActorContext } from \"./types.js\";\nimport type { ActorContext, ExecutionPlan } from \"./types.js\";\n\nexport const readConversationWorkspaceMountMode = readWorkspaceProjectionMode;\n\nexport class ActorExecutionResolver {\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n private hostWorkspacePath?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const plan = this.resolvePlan(context);\n return createExecutor(\n plan.sandboxConfig,\n plan.env,\n this.buildEnsureReadyCallback(plan, context.conversationId),\n );\n }\n\n private resolvePlan(context: ActorContext): ExecutionPlan {\n const ids = { userId: context.userId, conversationId: context.conversationId };\n const credentialKey = credentialAuthorizationKey(this.baseConfig, ids);\n const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, ids);\n const resourceKey = runtimeResourceKey(this.baseConfig, ids);\n this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);\n\n const vault =\n this.vaultManager.resolve(credentialKey) ??\n (legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);\n const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);\n const injection = resolveVaultInjection({\n vault,\n capabilities,\n sandboxType: this.baseConfig.type,\n conversationId: context.conversationId,\n });\n const mounts = this.resolveMounts(context.conversationId, injection.mounts);\n return {\n credentialKey,\n resourceKey,\n sandboxConfig: this.resolveSandboxConfig(resourceKey, mounts),\n env: injection.env,\n mounts,\n };\n }\n\n private ensureDefaultSharedVault(\n credentialKey: string,\n legacyCredentialKey: string | undefined,\n trustModel: ActorContext[\"trustModel\"],\n ): void {\n if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type })) return;\n if (\n this.vaultManager.hasEntry(credentialKey) ||\n (legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))\n ) {\n return;\n }\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n this.vaultManager.copySharedVaultTo(profile, credentialKey);\n }\n\n private resolveSandboxConfig(resourceKey: string, mounts: ContainerMount[]): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),\n };\n }\n if (this.baseConfig.type === \"gondolin\") {\n return {\n ...this.baseConfig,\n workspacePath: this.hostWorkspacePath,\n mounts,\n instanceId: resourceKey,\n resourceKey,\n };\n }\n if (this.baseConfig.type !== \"image\") return this.baseConfig;\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(resourceKey),\n };\n }\n\n private buildEnsureReadyCallback(\n plan: ExecutionPlan,\n conversationId: string,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || plan.sandboxConfig.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = plan.sandboxConfig.type === \"container\" ? plan.sandboxConfig.container : \"\";\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(plan.resourceKey, {\n containerName: expected,\n mounts: plan.mounts,\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n conversationId,\n credentialKey: plan.credentialKey,\n resourceKey: plan.resourceKey,\n expectedContainer: expected,\n hasVault: Boolean(plan.env || plan.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for resource key \"${plan.resourceKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vaultMounts: ContainerMount[]): ContainerMount[] {\n const workspaceMounts = resolveWorkspaceProjection(this.workspaceDir, conversationId).mounts;\n for (let index = 0; index < vaultMounts.length; index += 1) {\n const vaultMount = vaultMounts[index];\n const workspaceCollision = workspaceMounts.find((workspaceMount) =>\n targetsOverlap(workspaceMount.target, vaultMount.target),\n );\n if (workspaceCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps protected workspace target \"${workspaceCollision.target}\"`,\n );\n }\n\n const vaultCollision = vaultMounts\n .slice(0, index)\n .find((other) => targetsOverlap(other.target, vaultMount.target));\n if (vaultCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps vault target \"${vaultCollision.target}\"`,\n );\n }\n }\n return [...workspaceMounts, ...vaultMounts];\n }\n}\n\nfunction targetsOverlap(left: string, right: string): boolean {\n const a = normalizeMountTarget(left);\n const b = normalizeMountTarget(right);\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction normalizeMountTarget(value: string): string {\n const normalized = posix.normalize(value);\n return normalized.replace(/\\/+$/, \"\") || \"/\";\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -7,7 +7,6 @@ export * from "./sessions/policy.js";
7
7
  export * from "./sessions/store.js";
8
8
  export { createConversationRuntime, type RunSessionOptions, type ConversationRuntime, type ConversationRuntimeOptions, } from "./runtime/conversation-runtime.js";
9
9
  export type { MessagingBot, ConversationContext, ConversationEvent, MessagingEventHandler, ChatAdapter, ConversationMessage, ConversationResponder, ChatToolResult, ConversationKind, MessagingInfo, RunningSession, } from "./adapter.js";
10
- export { SandboxError, configureAgentSandboxRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, shutdownAgentSandboxes, stopIdleAgentSandboxes, validateSandbox, } from "./sandbox/index.js";
11
- export type { AgentConfig, AgentSandboxSettings, SandboxSettings } from "./types.js";
12
- export type { AgentSandboxConfig, AgentSandboxRuntimeOptions, CloudflareSandboxConfig, ExecOptions, ExecResult, Executor, SandboxAdapter, SandboxConfig, } from "./sandbox/index.js";
10
+ export { SandboxError, configureGondolinRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, type GondolinBootstrapOptions, } from "./sandbox/index.js";
11
+ export type { CloudflareSandboxConfig, ExecOptions, ExecResult, Executor, SandboxAdapter, SandboxConfig, } from "./sandbox/index.js";
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AACnC,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,4BAA4B,EAC5B,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACrF,YAAY,EACV,kBAAkB,EAClB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AACnC,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,KAAK,wBAAwB,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -5,5 +5,5 @@ export * from "./sessions/metadata.js";
5
5
  export * from "./sessions/policy.js";
6
6
  export * from "./sessions/store.js";
7
7
  export { createConversationRuntime, } from "./runtime/conversation-runtime.js";
8
- export { SandboxError, configureAgentSandboxRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, shutdownAgentSandboxes, stopIdleAgentSandboxes, validateSandbox, } from "./sandbox/index.js";
8
+ export { SandboxError, configureGondolinRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
9
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AAEnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,GAI1B,MAAM,mCAAmC,CAAC;AAc3C,OAAO,EACL,YAAY,EACZ,4BAA4B,EAC5B,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,GAChB,MAAM,oBAAoB,CAAC","sourcesContent":["export { defaultCommandHandlers, dispatchCommand } from \"./commands/registry.js\";\nexport * from \"./harness/index.js\";\nexport type { CommandContext, CommandHandler, CommandServices } from \"./commands/types.js\";\nexport * from \"./sessions/chat-history-sync.js\";\nexport * from \"./sessions/metadata.js\";\nexport * from \"./sessions/policy.js\";\nexport * from \"./sessions/store.js\";\nexport {\n createConversationRuntime,\n type RunSessionOptions,\n type ConversationRuntime,\n type ConversationRuntimeOptions,\n} from \"./runtime/conversation-runtime.js\";\nexport type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ChatAdapter,\n ConversationMessage,\n ConversationResponder,\n ChatToolResult,\n ConversationKind,\n MessagingInfo,\n RunningSession,\n} from \"./adapter.js\";\nexport {\n SandboxError,\n configureAgentSandboxRuntime,\n createExecutor,\n getSandboxAdapters,\n parseSandboxArg,\n shutdownAgentSandboxes,\n stopIdleAgentSandboxes,\n validateSandbox,\n} from \"./sandbox/index.js\";\nexport type { AgentConfig, AgentSandboxSettings, SandboxSettings } from \"./types.js\";\nexport type {\n AgentSandboxConfig,\n AgentSandboxRuntimeOptions,\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n SandboxAdapter,\n SandboxConfig,\n} from \"./sandbox/index.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AAEnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,GAI1B,MAAM,mCAAmC,CAAC;AAc3C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,GAEhB,MAAM,oBAAoB,CAAC","sourcesContent":["export { defaultCommandHandlers, dispatchCommand } from \"./commands/registry.js\";\nexport * from \"./harness/index.js\";\nexport type { CommandContext, CommandHandler, CommandServices } from \"./commands/types.js\";\nexport * from \"./sessions/chat-history-sync.js\";\nexport * from \"./sessions/metadata.js\";\nexport * from \"./sessions/policy.js\";\nexport * from \"./sessions/store.js\";\nexport {\n createConversationRuntime,\n type RunSessionOptions,\n type ConversationRuntime,\n type ConversationRuntimeOptions,\n} from \"./runtime/conversation-runtime.js\";\nexport type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ChatAdapter,\n ConversationMessage,\n ConversationResponder,\n ChatToolResult,\n ConversationKind,\n MessagingInfo,\n RunningSession,\n} from \"./adapter.js\";\nexport {\n SandboxError,\n configureGondolinRuntime,\n createExecutor,\n getSandboxAdapters,\n parseSandboxArg,\n validateSandbox,\n type GondolinBootstrapOptions,\n} from \"./sandbox/index.js\";\nexport type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n SandboxAdapter,\n SandboxConfig,\n} from \"./sandbox/index.js\";\n"]}