@geminixiang/mikan 1.4.0-beta.0 → 1.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +43 -3
  2. package/dist/adapters/commands/desktop.d.ts +5 -0
  3. package/dist/adapters/commands/desktop.d.ts.map +1 -0
  4. package/dist/adapters/commands/desktop.js +58 -0
  5. package/dist/adapters/commands/desktop.js.map +1 -0
  6. package/dist/adapters/commands/manifest.d.ts.map +1 -1
  7. package/dist/adapters/commands/manifest.js +8 -0
  8. package/dist/adapters/commands/manifest.js.map +1 -1
  9. package/dist/adapters/commands/registry.d.ts.map +1 -1
  10. package/dist/adapters/commands/registry.js +2 -0
  11. package/dist/adapters/commands/registry.js.map +1 -1
  12. package/dist/adapters/commands/types.d.ts +3 -1
  13. package/dist/adapters/commands/types.d.ts.map +1 -1
  14. package/dist/adapters/commands/types.js.map +1 -1
  15. package/dist/adapters/slack/app-config.d.ts +27 -0
  16. package/dist/adapters/slack/app-config.d.ts.map +1 -0
  17. package/dist/adapters/slack/app-config.js +241 -0
  18. package/dist/adapters/slack/app-config.js.map +1 -0
  19. package/dist/adapters/slack/types.d.ts +46 -1
  20. package/dist/adapters/slack/types.d.ts.map +1 -1
  21. package/dist/adapters/slack/types.js.map +1 -1
  22. package/dist/adapters/web/desktop/index.d.ts +16 -0
  23. package/dist/adapters/web/desktop/index.d.ts.map +1 -0
  24. package/dist/adapters/web/desktop/index.js +163 -0
  25. package/dist/adapters/web/desktop/index.js.map +1 -0
  26. package/dist/adapters/web/desktop/page.d.ts +2 -0
  27. package/dist/adapters/web/desktop/page.d.ts.map +1 -0
  28. package/dist/adapters/web/desktop/page.js +83 -0
  29. package/dist/adapters/web/desktop/page.js.map +1 -0
  30. package/dist/adapters/web/desktop/types.d.ts +8 -0
  31. package/dist/adapters/web/desktop/types.d.ts.map +1 -0
  32. package/dist/adapters/web/desktop/types.js +2 -0
  33. package/dist/adapters/web/desktop/types.js.map +1 -0
  34. package/dist/adapters/web/server.d.ts +2 -0
  35. package/dist/adapters/web/server.d.ts.map +1 -1
  36. package/dist/adapters/web/server.js +19 -0
  37. package/dist/adapters/web/server.js.map +1 -1
  38. package/dist/cli/boot.d.ts.map +1 -1
  39. package/dist/cli/boot.js +4 -1
  40. package/dist/cli/boot.js.map +1 -1
  41. package/dist/cli/onboard.d.ts +3 -0
  42. package/dist/cli/onboard.d.ts.map +1 -1
  43. package/dist/cli/onboard.js +79 -3
  44. package/dist/cli/onboard.js.map +1 -1
  45. package/dist/cli/slack.d.ts +9 -0
  46. package/dist/cli/slack.d.ts.map +1 -0
  47. package/dist/cli/slack.js +96 -0
  48. package/dist/cli/slack.js.map +1 -0
  49. package/dist/cli/types.d.ts +2 -1
  50. package/dist/cli/types.d.ts.map +1 -1
  51. package/dist/cli/types.js.map +1 -1
  52. package/dist/harness/desktop.d.ts +16 -0
  53. package/dist/harness/desktop.d.ts.map +1 -0
  54. package/dist/harness/desktop.js +6 -0
  55. package/dist/harness/desktop.js.map +1 -0
  56. package/dist/harness/execution-resolver.d.ts +1 -0
  57. package/dist/harness/execution-resolver.d.ts.map +1 -1
  58. package/dist/harness/execution-resolver.js +5 -0
  59. package/dist/harness/execution-resolver.js.map +1 -1
  60. package/dist/harness/presenter.d.ts.map +1 -1
  61. package/dist/harness/presenter.js +6 -1
  62. package/dist/harness/presenter.js.map +1 -1
  63. package/dist/harness/runner.d.ts.map +1 -1
  64. package/dist/harness/runner.js +22 -1
  65. package/dist/harness/runner.js.map +1 -1
  66. package/dist/harness/session.d.ts +1 -1
  67. package/dist/harness/session.d.ts.map +1 -1
  68. package/dist/harness/session.js +30 -9
  69. package/dist/harness/session.js.map +1 -1
  70. package/dist/harness/tools/codemode.d.ts.map +1 -1
  71. package/dist/harness/tools/codemode.js +2 -2
  72. package/dist/harness/tools/codemode.js.map +1 -1
  73. package/dist/harness/tools/index.d.ts +2 -2
  74. package/dist/harness/tools/index.d.ts.map +1 -1
  75. package/dist/harness/tools/index.js +10 -2
  76. package/dist/harness/tools/index.js.map +1 -1
  77. package/dist/harness/tools/jev-browser.d.ts +12 -1
  78. package/dist/harness/tools/jev-browser.d.ts.map +1 -1
  79. package/dist/harness/tools/jev-browser.js +189 -30
  80. package/dist/harness/tools/jev-browser.js.map +1 -1
  81. package/dist/harness/tools/pi-tools.d.ts.map +1 -1
  82. package/dist/harness/tools/pi-tools.js +2 -1
  83. package/dist/harness/tools/pi-tools.js.map +1 -1
  84. package/dist/harness/tools/types.d.ts +4 -0
  85. package/dist/harness/tools/types.d.ts.map +1 -1
  86. package/dist/harness/tools/types.js.map +1 -1
  87. package/dist/harness/types.d.ts +2 -1
  88. package/dist/harness/types.d.ts.map +1 -1
  89. package/dist/harness/types.js.map +1 -1
  90. package/dist/main.js +29 -0
  91. package/dist/main.js.map +1 -1
  92. package/dist/runtime/conversation-runtime.js +7 -0
  93. package/dist/runtime/conversation-runtime.js.map +1 -1
  94. package/dist/sandbox/desktop.d.ts +30 -0
  95. package/dist/sandbox/desktop.d.ts.map +1 -0
  96. package/dist/sandbox/desktop.js +112 -0
  97. package/dist/sandbox/desktop.js.map +1 -0
  98. package/dist/sandbox/provisioner.d.ts +6 -2
  99. package/dist/sandbox/provisioner.d.ts.map +1 -1
  100. package/dist/sandbox/provisioner.js +41 -6
  101. package/dist/sandbox/provisioner.js.map +1 -1
  102. package/dist/sandbox/types.d.ts +19 -0
  103. package/dist/sandbox/types.d.ts.map +1 -1
  104. package/dist/sandbox/types.js.map +1 -1
  105. package/dist/types.d.ts +17 -1
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js.map +1 -1
  108. package/package.json +9 -8
@@ -0,0 +1,112 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { isRecord } from "../unknown-values.js";
4
+ import { DockerContainerManager } from "./provisioner.js";
5
+ export const DESKTOP_COMMAND = "mikan-desktop";
6
+ export const DESKTOP_RUNTIME_DIR = "/run/user/0";
7
+ const MISSING_COMMAND = /executable file not found|not found in \$PATH/i;
8
+ const DESKTOP_EXEC_TIMEOUT_MS = 20_000;
9
+ const HAND_BACK_DELAY_MS = 10_000;
10
+ const execFileAsync = promisify(execFile);
11
+ export function parseDesktopStatus(stdout) {
12
+ let parsed;
13
+ try {
14
+ parsed = JSON.parse(stdout);
15
+ }
16
+ catch {
17
+ return { display: undefined, control: "agent" };
18
+ }
19
+ if (!isRecord(parsed))
20
+ return { display: undefined, control: "agent" };
21
+ const display = typeof parsed.display === "string" && parsed.display ? parsed.display : undefined;
22
+ return { display, control: parsed.control === "user" ? "user" : "agent" };
23
+ }
24
+ export class OfficeDesktop {
25
+ constructor(containers, runners = {}) {
26
+ this.containers = containers;
27
+ this.viewers = new Map();
28
+ this.handBacks = new Map();
29
+ this.execFile =
30
+ runners.execFile ??
31
+ ((file, args) => execFileAsync(file, args, { timeout: DESKTOP_EXEC_TIMEOUT_MS }));
32
+ this.spawn = runners.spawn ?? spawn;
33
+ this.handBackDelayMs = runners.handBackDelayMs ?? HAND_BACK_DELAY_MS;
34
+ }
35
+ async start(containerKey) {
36
+ if (!this.containers.isRunning(containerKey))
37
+ return "stopped";
38
+ try {
39
+ await this.desktopCommand(containerKey, ["start"]);
40
+ return "ready";
41
+ }
42
+ catch (error) {
43
+ const output = isRecord(error)
44
+ ? `${String(error.stdout ?? "")}\n${String(error.stderr ?? "")}`
45
+ : "";
46
+ if (MISSING_COMMAND.test(output)) {
47
+ return "outdated-image";
48
+ }
49
+ throw error;
50
+ }
51
+ }
52
+ async status(containerKey) {
53
+ const { stdout } = await this.desktopCommand(containerKey, ["status"]);
54
+ return parseDesktopStatus(stdout);
55
+ }
56
+ async setBrowserOwner(containerKey, owner) {
57
+ await this.desktopCommand(containerKey, ["control", owner]);
58
+ }
59
+ connect(containerKey) {
60
+ const container = DockerContainerManager.containerName(containerKey);
61
+ const child = this.spawn(this.containers.engine, ["exec", "-i", container, DESKTOP_COMMAND, "connect"], { stdio: ["pipe", "pipe", "ignore"] });
62
+ const retained = this.containers.retain(containerKey);
63
+ const left = this.joinViewer(containerKey);
64
+ let released = false;
65
+ const release = () => {
66
+ if (released)
67
+ return;
68
+ released = true;
69
+ retained();
70
+ left();
71
+ };
72
+ const close = () => {
73
+ release();
74
+ child.kill();
75
+ };
76
+ child.once("exit", release);
77
+ child.once("error", release);
78
+ if (!child.stdin || !child.stdout) {
79
+ close();
80
+ throw new Error(`${this.containers.engine} exec for ${container} has no stdio`);
81
+ }
82
+ return { input: child.stdin, output: child.stdout, process: child, close };
83
+ }
84
+ joinViewer(containerKey) {
85
+ clearTimeout(this.handBacks.get(containerKey));
86
+ this.handBacks.delete(containerKey);
87
+ this.viewers.set(containerKey, (this.viewers.get(containerKey) ?? 0) + 1);
88
+ return () => {
89
+ const remaining = (this.viewers.get(containerKey) ?? 1) - 1;
90
+ if (remaining > 0) {
91
+ this.viewers.set(containerKey, remaining);
92
+ return;
93
+ }
94
+ this.viewers.delete(containerKey);
95
+ const timer = setTimeout(() => {
96
+ this.handBacks.delete(containerKey);
97
+ this.setBrowserOwner(containerKey, "agent").catch(() => { });
98
+ }, this.handBackDelayMs);
99
+ timer.unref();
100
+ this.handBacks.set(containerKey, timer);
101
+ };
102
+ }
103
+ desktopCommand(containerKey, args) {
104
+ return this.execFile(this.containers.engine, [
105
+ "exec",
106
+ DockerContainerManager.containerName(containerKey),
107
+ DESKTOP_COMMAND,
108
+ ...args,
109
+ ]);
110
+ }
111
+ }
112
+ //# sourceMappingURL=desktop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop.js","sourceRoot":"","sources":["../../src/sandbox/desktop.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { isRecord } from \"../unknown-values.js\";\nimport { DockerContainerManager } from \"./provisioner.js\";\nimport type {\n BrowserOwner,\n DesktopProcess,\n DesktopStart,\n DesktopStatus,\n DesktopStream,\n DockerExecFile,\n} from \"./types.js\";\n\nexport const DESKTOP_COMMAND = \"mikan-desktop\";\n\nexport const DESKTOP_RUNTIME_DIR = \"/run/user/0\";\n\ntype DesktopContainers = Pick<DockerContainerManager, \"engine\" | \"retain\" | \"isRunning\">;\n\ninterface DesktopProcessRunners {\n execFile?: DockerExecFile;\n handBackDelayMs?: number;\n spawn?: (\n file: string,\n args: string[],\n options: { stdio: [\"pipe\", \"pipe\", \"ignore\"] },\n ) => DesktopProcess;\n}\n\nconst MISSING_COMMAND = /executable file not found|not found in \\$PATH/i;\n\nconst DESKTOP_EXEC_TIMEOUT_MS = 20_000;\n\nconst HAND_BACK_DELAY_MS = 10_000;\n\nconst execFileAsync = promisify(execFile);\n\nexport function parseDesktopStatus(stdout: string): DesktopStatus {\n let parsed: unknown;\n try {\n parsed = JSON.parse(stdout);\n } catch {\n return { display: undefined, control: \"agent\" };\n }\n if (!isRecord(parsed)) return { display: undefined, control: \"agent\" };\n const display = typeof parsed.display === \"string\" && parsed.display ? parsed.display : undefined;\n return { display, control: parsed.control === \"user\" ? \"user\" : \"agent\" };\n}\n\nexport class OfficeDesktop {\n private readonly execFile: NonNullable<DesktopProcessRunners[\"execFile\"]>;\n private readonly spawn: NonNullable<DesktopProcessRunners[\"spawn\"]>;\n private readonly handBackDelayMs: number;\n private readonly viewers = new Map<string, number>();\n private readonly handBacks = new Map<string, NodeJS.Timeout>();\n\n constructor(\n private readonly containers: DesktopContainers,\n runners: DesktopProcessRunners = {},\n ) {\n this.execFile =\n runners.execFile ??\n ((file, args) => execFileAsync(file, args, { timeout: DESKTOP_EXEC_TIMEOUT_MS }));\n this.spawn = runners.spawn ?? spawn;\n this.handBackDelayMs = runners.handBackDelayMs ?? HAND_BACK_DELAY_MS;\n }\n\n async start(containerKey: string): Promise<DesktopStart> {\n if (!this.containers.isRunning(containerKey)) return \"stopped\";\n try {\n await this.desktopCommand(containerKey, [\"start\"]);\n return \"ready\";\n } catch (error) {\n const output = isRecord(error)\n ? `${String(error.stdout ?? \"\")}\\n${String(error.stderr ?? \"\")}`\n : \"\";\n if (MISSING_COMMAND.test(output)) {\n return \"outdated-image\";\n }\n throw error;\n }\n }\n\n async status(containerKey: string): Promise<DesktopStatus> {\n const { stdout } = await this.desktopCommand(containerKey, [\"status\"]);\n return parseDesktopStatus(stdout);\n }\n\n async setBrowserOwner(containerKey: string, owner: BrowserOwner): Promise<void> {\n await this.desktopCommand(containerKey, [\"control\", owner]);\n }\n\n connect(containerKey: string): DesktopStream {\n const container = DockerContainerManager.containerName(containerKey);\n const child = this.spawn(\n this.containers.engine,\n [\"exec\", \"-i\", container, DESKTOP_COMMAND, \"connect\"],\n { stdio: [\"pipe\", \"pipe\", \"ignore\"] },\n );\n const retained = this.containers.retain(containerKey);\n const left = this.joinViewer(containerKey);\n let released = false;\n const release = () => {\n if (released) return;\n released = true;\n retained();\n left();\n };\n const close = () => {\n release();\n child.kill();\n };\n child.once(\"exit\", release);\n child.once(\"error\", release);\n if (!child.stdin || !child.stdout) {\n close();\n throw new Error(`${this.containers.engine} exec for ${container} has no stdio`);\n }\n return { input: child.stdin, output: child.stdout, process: child, close };\n }\n\n private joinViewer(containerKey: string): () => void {\n clearTimeout(this.handBacks.get(containerKey));\n this.handBacks.delete(containerKey);\n this.viewers.set(containerKey, (this.viewers.get(containerKey) ?? 0) + 1);\n return () => {\n const remaining = (this.viewers.get(containerKey) ?? 1) - 1;\n if (remaining > 0) {\n this.viewers.set(containerKey, remaining);\n return;\n }\n this.viewers.delete(containerKey);\n const timer = setTimeout(() => {\n this.handBacks.delete(containerKey);\n this.setBrowserOwner(containerKey, \"agent\").catch(() => {});\n }, this.handBackDelayMs);\n timer.unref();\n this.handBacks.set(containerKey, timer);\n };\n }\n\n private desktopCommand(containerKey: string, args: string[]): Promise<{ stdout: string }> {\n return this.execFile(this.containers.engine, [\n \"exec\",\n DockerContainerManager.containerName(containerKey),\n DESKTOP_COMMAND,\n ...args,\n ]);\n }\n}\n"]}
@@ -14,13 +14,14 @@ export declare class DockerContainerManager {
14
14
  private readonly limits?;
15
15
  private readonly boostLimits?;
16
16
  private readonly boostedKeys;
17
+ private readonly retained;
17
18
  private readonly overrideLimits;
18
19
  private readonly execFileImpl;
19
20
  private readonly configuredEngine;
20
21
  private readonly timeZone;
21
22
  private imagePull?;
22
23
  constructor(image: string, options?: DockerContainerManagerOptions);
23
- private get engine();
24
+ get engine(): string;
24
25
  private run;
25
26
  static containerName(containerKey: string): string;
26
27
  static networkName(containerKey: string): string;
@@ -33,6 +34,8 @@ export declare class DockerContainerManager {
33
34
  getDefaultLimits(): ResourceLimits | undefined;
34
35
  getBoostLimits(): ResourceLimits | undefined;
35
36
  markUsed(containerKey: string): void;
37
+ isRunning(containerKey: string): boolean;
38
+ retain(containerKey: string): () => void;
36
39
  stop(containerKey: string): Promise<void>;
37
40
  private stopInner;
38
41
  remove(containerKey: string): Promise<void>;
@@ -60,7 +63,8 @@ export declare class DockerContainerManager {
60
63
  private localImageId;
61
64
  prepareImage(): Promise<void>;
62
65
  private pullImage;
63
- private containerImage;
66
+ private imageLeftBehind;
67
+ private isUnnamedImage;
64
68
  private removeImageIfUnused;
65
69
  private pulledImageId;
66
70
  private replaceContainer;
@@ -1 +1 @@
1
- {"version":3,"file":"provisioner.d.ts","sourceRoot":"","sources":["../../src/sandbox/provisioner.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAKrB,qBAAa,sBAAsB;IAsB/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IArBxB,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAwB;IAC7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IACjE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IAC9D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAA2B;IAC5E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAA2B;IAC5E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAoB;IAE9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqC;IACpE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,SAAS,CAAC,CAAgB;IAElC,YACmB,KAAK,EAAE,MAAM,EAC9B,OAAO,GAAE,6BAAkC,EAO5C;IAED,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,CAAC,GAAG;IAIX,MAAM,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEjD;IAED,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/C;IAED,OAAO,CAAC,SAAS;IAWX,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAWrF;YAEa,cAAc;IAmCtB,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAY7D;IAEK,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAQzF;IAED,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB,CAGvD;IAED,gBAAgB,IAAI,cAAc,GAAG,SAAS,CAE7C;IAED,cAAc,IAAI,cAAc,GAAG,SAAS,CAE3C;IAED,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAGnC;IAED,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExC;YAEa,SAAS;IAavB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1C;YAEa,WAAW;IAyBnB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/C;IAEK,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BpD;IAED,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;YAIJ,YAAY;IAyD1B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;YAUX,mBAAmB;YA2BnB,YAAY;IAa1B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,SAAS;YAQH,sBAAsB;IAYpC,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,sBAAsB;YAYhB,KAAK;YAUL,iBAAiB;YAOjB,aAAa;YAMb,YAAY;IAS1B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5B;YAEa,SAAS;YAYT,cAAc;YAYd,mBAAmB;YASnB,aAAa;YAUb,gBAAgB;YAehB,mBAAmB;YAKnB,aAAa;YA2Bb,eAAe;YAYf,aAAa;YAMb,yBAAyB;IAmBvC,OAAO,CAAC,cAAc;YAOR,uBAAuB;IA0BrC,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,6BAA6B;YAOvB,oBAAoB;CAiBnC"}
1
+ {"version":3,"file":"provisioner.d.ts","sourceRoot":"","sources":["../../src/sandbox/provisioner.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,7 @@ export class DockerContainerManager {
23
23
  this.inflight = new Map();
24
24
  this.keyQueues = new Map();
25
25
  this.boostedKeys = new Set();
26
+ this.retained = new Map();
26
27
  this.overrideLimits = new Map();
27
28
  this.limits = options.limits;
28
29
  this.boostLimits = options.boostLimits;
@@ -73,11 +74,11 @@ export class DockerContainerManager {
73
74
  : await this.runtimeDrift(containerKey, containerName, mounts, status);
74
75
  if (drift) {
75
76
  log.logInfo(`Container ${containerName} is out of date (${drift}); replacing container`);
76
- const previousImage = drift === "image" ? await this.containerImage(containerName) : undefined;
77
+ const leftBehind = await this.imageLeftBehind(containerName);
77
78
  await this.replaceContainer(containerKey, containerName, mounts, options);
78
79
  log.logInfo(`Container ${containerName} replaced from image ${this.image}`);
79
- if (previousImage)
80
- await this.removeImageIfUnused(previousImage);
80
+ if (leftBehind)
81
+ await this.removeImageIfUnused(leftBehind);
81
82
  }
82
83
  else if (status === "stopped") {
83
84
  await this.run(["start", containerName]);
@@ -132,6 +133,24 @@ export class DockerContainerManager {
132
133
  if (state)
133
134
  state.lastUsed = Date.now();
134
135
  }
136
+ isRunning(containerKey) {
137
+ return this.state.get(containerKey)?.status === "running";
138
+ }
139
+ retain(containerKey) {
140
+ this.retained.set(containerKey, (this.retained.get(containerKey) ?? 0) + 1);
141
+ let released = false;
142
+ return () => {
143
+ if (released)
144
+ return;
145
+ released = true;
146
+ const remaining = (this.retained.get(containerKey) ?? 1) - 1;
147
+ if (remaining > 0)
148
+ this.retained.set(containerKey, remaining);
149
+ else
150
+ this.retained.delete(containerKey);
151
+ this.markUsed(containerKey);
152
+ };
153
+ }
135
154
  stop(containerKey) {
136
155
  return this.serialize(containerKey, () => this.stopInner(containerKey));
137
156
  }
@@ -173,6 +192,8 @@ export class DockerContainerManager {
173
192
  const now = Date.now();
174
193
  const toStop = [];
175
194
  for (const [containerKey, containerState] of this.state) {
195
+ if (this.retained.has(containerKey))
196
+ continue;
176
197
  if (containerState.status === "running" && now - containerState.lastUsed > maxIdleMs) {
177
198
  toStop.push(containerKey);
178
199
  }
@@ -398,17 +419,31 @@ export class DockerContainerManager {
398
419
  log.logWarning(`Could not pull sandbox image ${this.image}; offices keep the local image if there is one`, errorMessage(err));
399
420
  }
400
421
  }
401
- async containerImage(containerName) {
422
+ async imageLeftBehind(containerName) {
402
423
  const { stdout } = await this.run([
403
424
  "inspect",
404
425
  "-f",
405
426
  `{{.Config.Image}}\t{{index .Config.Labels "${DockerContainerManager.IMAGE_ID_LABEL_KEY}"}}`,
406
427
  containerName,
407
428
  ]);
408
- const [reference = "", imageId] = stdout.trim().split("\t");
429
+ const [reference = "", label] = stdout.trim().split("\t");
430
+ const imageId = this.normalizeDockerValue(label);
431
+ if (imageId && imageId === (await this.localImageId()))
432
+ return undefined;
409
433
  if (reference !== this.image && isPublishedSandboxImage(reference))
410
434
  return reference;
411
- return this.normalizeDockerValue(imageId);
435
+ if (imageId && (await this.isUnnamedImage(imageId)))
436
+ return imageId;
437
+ return undefined;
438
+ }
439
+ async isUnnamedImage(imageId) {
440
+ try {
441
+ const { stdout } = await this.run(["image", "inspect", "-f", "{{len .RepoTags}}", imageId]);
442
+ return stdout.trim() === "0";
443
+ }
444
+ catch {
445
+ return false;
446
+ }
412
447
  }
413
448
  async removeImageIfUnused(image) {
414
449
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"provisioner.js","sourceRoot":"","sources":["../../src/sandbox/provisioner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAkB1C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,OAAO,sBAAsB;aAIT,kBAAa,GAAG,oBAAoB,AAAvB,CAAwB;aACrC,qBAAgB,GAAG,qBAAqB,AAAxB,CAAyB;aACzC,uBAAkB,GAAG,gBAAgB,AAAnB,CAAoB;aACtC,8BAAyB,GAAG,uBAAuB,AAA1B,CAA2B;aACpD,8BAAyB,GAAG,uBAAuB,AAA1B,CAA2B;aACpD,sBAAiB,GAAG,eAAe,AAAlB,CAAmB;aACpC,uBAAkB,GAAG,gBAAgB,AAAnB,CAAoB;IAW9D,YACmB,KAAa,EAC9B,OAAO,GAAkC,EAAE;QAD1B,UAAK,GAAL,KAAK,CAAQ;QArBxB,UAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;QAC1C,aAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;QAC9C,cAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;QAWvC,gBAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,mBAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;QAUlE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,aAAa,CAAC;QAC1D,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC;IACvF,CAAC;IAED,IAAY,MAAM;QAChB,OAAO,IAAI,CAAC,gBAAgB,IAAI,eAAe,EAAE,CAAC;IACpD,CAAC;IAEO,GAAG,CAAC,IAAc;QACxB,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,YAAoB;QACvC,OAAO,iBAAiB,YAAY,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,YAAoB;QACrC,OAAO,qBAAqB,YAAY,EAAE,CAAC;IAC7C,CAAC;IAEO,SAAS,CAAI,YAAoB,EAAE,IAAsB;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC1C,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,OAAO;gBAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,OAAO,GAAqB,EAAE;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,EAAE,CAChD,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,OAAO,CAAC,CAC3C,CAAC,OAAO,CAAC,GAAG,EAAE;YACb,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,YAAoB,EAAE,OAAyB;QAC1E,MAAM,aAAa,GACjB,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;QAEvD,IAAI,CAAC;YACH,MAAM,KAAK,GACT,MAAM,KAAK,SAAS;gBAClB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC3E,IAAI,KAAK,EAAE,CAAC;gBACV,GAAG,CAAC,OAAO,CAAC,aAAa,aAAa,oBAAoB,KAAK,wBAAwB,CAAC,CAAC;gBACzF,MAAM,aAAa,GACjB,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC3E,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC1E,GAAG,CAAC,OAAO,CAAC,aAAa,aAAa,wBAAwB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;gBAC5E,IAAI,aAAa;oBAAE,MAAM,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;YACnE,CAAC;iBAAM,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;gBACzC,GAAG,CAAC,OAAO,CAAC,aAAa,aAAa,UAAU,CAAC,CAAC;YACpD,CAAC;iBAAM,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBACtE,GAAG,CAAC,OAAO,CAAC,aAAa,aAAa,UAAU,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC5D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,YAAoB;QAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACzC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,MAAsB;QAC1D,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED,cAAc,CAAC,YAAoB;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACnD,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;IACjE,CAAC;IAED,gBAAgB;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,QAAQ,CAAC,YAAoB;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,KAAK;YAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,YAAoB;QACvB,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC1E,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,YAAoB;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;YACtD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACtC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACzC,GAAG,CAAC,OAAO,CAAC,aAAa,aAAa,iBAAiB,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,4BAA4B,aAAa,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,MAAM,CAAC,YAAoB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,YAAoB;QAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,sBAAsB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAErE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC7C,aAAa,EACb,aAAa,aAAa,UAAU,EACpC,8BAA8B,aAAa,EAAE,CAC9C,CAAC;QACF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,aAAa,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;YAC/C,GAAG,CAAC,OAAO,CAAC,WAAW,WAAW,UAAU,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,4BAA4B,WAAW,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAChC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACxD,IAAI,cAAc,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,GAAG,cAAc,CAAC,QAAQ,GAAG,SAAS,EAAE,CAAC;gBACrF,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,aAAqB;QACnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;YAClC,aAAa;YACb,OAAO,EAAE,MAAM,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC;SAC3D,CAAC,CAAC,CACJ,CAAC;QAEF,KAAK,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;YACnD,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC;gBAAE,SAAS;YAC5E,MAAM,YAAY,GAAG,IAAI,CAAC,6BAA6B,CAAC,aAAa,CAAC,CAAC;YACvE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,GAAG,CAAC,UAAU,CAAC,0DAA0D,EAAE,aAAa,CAAC,CAAC;gBAC1F,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAoB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;QAC7F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;QAC1C,GAAG,CAAC,OAAO,CACT,cAAc,IAAI,CAAC,KAAK,CAAC,IAAI,gCAAgC,OAAO,aAAa,OAAO,GAAG,CAC5F,CAAC;IACJ,CAAC;IAEO,QAAQ,CAAC,YAAoB,EAAE,MAAuB,EAAE,aAAqB;QACnF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;IAChF,CAAC;IAEO,gBAAgB,CAAC,YAAoB;QAC3C,OAAO,CACL,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,aAAa;YAC3C,sBAAsB,CAAC,aAAa,CAAC,YAAY,CAAC,CACnD,CAAC;IACJ,CAAC;IAEO,SAAS,CAAC,MAAwB;QACxC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,UAAU,CAAC,KAAqB;QACtC,OAAO,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACzE,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,YAAoB,EACpB,aAAqB,EACrB,MAAwB,EACxB,OAAyB;QAEzB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC3D,GAAG,CAAC,OAAO,CAAC,sBAAsB,aAAa,eAAe,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG;YACb,SAAS;YACT,sBAAsB,CAAC,aAAa;YACpC,SAAS;YACT,sBAAsB,CAAC,gBAAgB;YACvC,SAAS;YACT,GAAG,sBAAsB,CAAC,kBAAkB,IAAI,YAAY,EAAE;SAC/D,CAAC;QACF,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CACT,SAAS,EACT,GAAG,sBAAsB,CAAC,yBAAyB,IAAI,OAAO,CAAC,cAAc,EAAE,CAChF,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CACT,SAAS,EACT,GAAG,sBAAsB,CAAC,yBAAyB,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CACrF,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,sBAAsB,CAAC,iBAAiB,IAAI,WAAW,EAAE,CAAC,CAAC;QACrF,MAAM,CAAC,IAAI,CACT,SAAS,EACT,GAAG,sBAAsB,CAAC,kBAAkB,IAAI,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,CAC7E,CAAC;QACF,MAAM,IAAI,CAAC,GAAG,CAAC;YACb,KAAK;YACL,IAAI;YACJ,QAAQ;YACR,aAAa;YACb,WAAW;YACX,WAAW;YACX,YAAY;YACZ,KAAK;YACL,gBAAgB;YAChB,mBAAmB;YACnB,cAAc;YACd,MAAM;YACN,OAAO;YACP,MAAM,IAAI,CAAC,QAAQ,EAAE;YACrB,GAAG,MAAM;YACT,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YAC7D,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,KAAK;YACV,OAAO;YACP,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAEO,eAAe,CAAC,YAAoB;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACvD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QAC5D,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjD,CAAC;IAEO,iBAAiB,CAAC,MAAkC;QAC1D,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,IAAI,MAAM,EAAE,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,YAAoB,EAAE,aAAqB;QAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;QAC7E,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACnC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,SAAS,EAAE,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,gDAAgD,aAAa,EAAE,EAC/D,YAAY,CAAC,GAAG,CAAC,CAClB,CAAC;YACF,qBAAqB,CAAC,GAAG,EAAE;gBACzB,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,mBAAmB;gBAC5B,SAAS,EAAE,uBAAuB;gBAClC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE;oBACP,WAAW,EAAE,KAAK;oBAClB,YAAY;oBACZ,aAAa;oBACb,aAAa,EAAE,SAAS,CAAC,MAAM;oBAC/B,KAAK,EAAE,KAAK;iBACb;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,YAAoB,EACpB,aAAqB,EACrB,MAAwB,EACxB,MAAuB;QAEvB,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;YAAE,OAAO,OAAO,CAAC;QAChG,IAAI,MAAM,IAAI,CAAC,sBAAsB,CAAC,aAAa,EAAE,MAAM,CAAC;YAAE,OAAO,eAAe,CAAC;QACrF,IAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,aAAa,CAAC;YAAE,OAAO,SAAS,CAAC;QAClF,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YAAE,OAAO,OAAO,CAAC;QACtF,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,iBAAiB,CAAC,KAAwB,EAAE,MAAwB;QAC1E,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IAEO,aAAa,CAAC,MAAwB;QAC5C,OAAO,MAAM;aACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;aACtC,KAAK,EAAE;aACP,QAAQ,EAAE,CAAC;IAChB,CAAC;IAEO,SAAS,CAAC,QAAkB,EAAE,MAAgB;QACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAClC,aAAqB,EACrB,MAAwB;QAExB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7C,OAAO,CACL,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,sBAAsB,CAAC,yBAAyB,CAAC,CAAC;YACnF,QAAQ,CACT,CAAC;IACJ,CAAC;IAEO,cAAc,CAAC,MAAwB;QAC7C,MAAM,OAAO,GAAG,MAAM;aACnB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACf,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,WAAW,EAAE,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC;SACvD,CAAC,CAAC;aACF,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACxB,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CACnF,CAAC;QACJ,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5E,CAAC;IAEO,sBAAsB,CAAC,MAAc;QAC3C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBAClB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzE,CAAC;YACD,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/F,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,aAAqB,EAAE,GAAW;QACpD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;YAChC,SAAS;YACT,IAAI;YACJ,2BAA2B,GAAG,KAAK;YACnC,aAAa;SACd,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,aAAqB;QACnD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC,CAAC;QACxF,OAAO,eAAe,CAAC,MAAM,EAAE,aAAa,CAAC;aAC1C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aAC/E,QAAQ,EAAE,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,aAAqB;QAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1C,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,sBAAsB,CAAC,kBAAkB,CAAC,CAAC,KAAK,OAAO,CAAC;IAClG,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrF,OAAO,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrC,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,CAAC,KAAK,aAAa,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,gCAAgC,IAAI,CAAC,KAAK,gDAAgD,EAC1F,YAAY,CAAC,GAAG,CAAC,CAClB,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,aAAqB;QAChD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;YAChC,SAAS;YACT,IAAI;YACJ,8CAA8C,sBAAsB,CAAC,kBAAkB,KAAK;YAC5F,aAAa;SACd,CAAC,CAAC;QACH,MAAM,CAAC,SAAS,GAAG,EAAE,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,SAAS,KAAK,IAAI,CAAC,KAAK,IAAI,uBAAuB,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QACrF,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,KAAa;QAC7C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAC/B,GAAG,CAAC,OAAO,CAAC,yBAAyB,KAAK,2BAA2B,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,MAAM,IAAI,CAAC,SAAS,CAAC;QACrB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QACxC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,6BAA6B,CAAC,CAAC;QAC/E,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,YAAoB,EACpB,aAAqB,EACrB,MAAwB,EACxB,OAAyB;QAEzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC7C,aAAa,EACb,aAAa,aAAa,0BAA0B,EACpD,8BAA8B,aAAa,kBAAkB,CAC9D,CAAC;QACF,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,aAAa,kBAAkB,CAAC,CAAC;QAC7F,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,YAAoB,EAAE,aAAqB;QAC3E,MAAM,QAAQ,GAAG,sBAAsB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAClE,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,CAAC,KAAK,QAAQ,CAAC;IAClG,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,YAAoB;QAC9C,MAAM,WAAW,GAAG,sBAAsB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QACrE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;YAChC,SAAS;YACT,IAAI;YACJ,UAAU;YACV,SAAS,WAAW,GAAG;YACvB,UAAU;YACV,WAAW;SACZ,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,OAAO,WAAW,CAAC;QAC1E,MAAM,IAAI,CAAC,GAAG,CAAC;YACb,SAAS;YACT,QAAQ;YACR,UAAU;YACV,QAAQ;YACR,SAAS;YACT,sBAAsB,CAAC,aAAa;YACpC,SAAS;YACT,sBAAsB,CAAC,gBAAgB;YACvC,SAAS;YACT,GAAG,sBAAsB,CAAC,kBAAkB,IAAI,YAAY,EAAE;YAC9D,WAAW;SACZ,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,aAAqB;QACjD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;YAChC,IAAI;YACJ,IAAI;YACJ,UAAU;YACV,SAAS,aAAa,GAAG;YACzB,UAAU;YACV,YAAY;SACb,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,aAAqB;QAC/C,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACnE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC,CAAC;QAC1F,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,CAAC;IAEO,KAAK,CAAC,yBAAyB;QACrC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;gBAChC,IAAI;gBACJ,IAAI;gBACJ,UAAU;gBACV,SAAS,sBAAsB,CAAC,aAAa,EAAE;gBAC/C,UAAU;gBACV,SAAS,sBAAsB,CAAC,gBAAgB,EAAE;gBAClD,UAAU;gBACV,YAAY;aACb,CAAC,CAAC;YACH,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,2CAA2C,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/E,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,MAAc;QACnC,OAAO,MAAM;aACV,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAEO,KAAK,CAAC,uBAAuB,CACnC,aAAqB;QAErB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;gBAChC,SAAS;gBACT,IAAI;gBACJ,4DAA4D;gBAC5D,aAAa;aACd,CAAC,CAAC;YACH,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxE,MAAM,OAAO,GAAG,UAAU,KAAK,MAAM,CAAC;YACtC,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC;YAClF,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC,GAAG,CACrE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CACxB,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,+BAA+B,aAAa,mBAAmB,EAC/D,YAAY,CAAC,GAAG,CAAC,CAClB,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,KAAc;QACzC,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,YAAY;YAAE,OAAO,SAAS,CAAC;QACvD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IAEO,6BAA6B,CAAC,aAAqB;QACzD,MAAM,MAAM,GAAG,sBAAsB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QACxD,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,aAAqB,EACrB,UAAkB,EAClB,UAAkB;QAElB,IAAI,CAAC;YACH,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC/D,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;YAC9C,CAAC;YACD,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AAED,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAExC,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,uBAAuB,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACzF,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,uBAAuB,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACzF,CAAC;AAQD,SAAS,eAAe,CAAC,GAAW,EAAE,aAAqB;IACzD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,aAAa,GAAG,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,KAAc,EAAE,EAAE;QACvC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,EAAE,CAAC;QACzD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QACpE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACxE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,sBAAsB,GAC1B,uEAAuE,CAAC;AAE1E,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;AACnD,CAAC;AAED,SAAS,YAAY,CAAC,OAA0B,EAAE,IAAY;IAC5D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport * as log from \"../log.js\";\nimport { isPublishedSandboxImage } from \"./published-image.js\";\nimport { reportUserFacingError } from \"../observability/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\ntype ContainerStatus = \"running\" | \"stopped\" | \"missing\";\ntype DriftReason = \"binds\" | \"mount-content\" | \"network\" | \"image\";\n\ninterface ContainerState {\n status: ContainerStatus;\n lastUsed: number;\n containerName: string;\n}\n\nimport type {\n ContainerMount,\n DockerContainerManagerOptions,\n ProvisionOptions,\n ResourceLimits,\n SandboxLimitStatus,\n} from \"../types.js\";\nimport { errorMessage, isRecord } from \"../unknown-values.js\";\nimport type { DockerExecFile } from \"./types.js\";\nimport { containerEngine } from \"./engine.js\";\n\nexport class DockerContainerManager {\n private state = new Map<string, ContainerState>();\n private inflight = new Map<string, Promise<string>>();\n private keyQueues = new Map<string, Promise<unknown>>();\n private static readonly MANAGED_LABEL = \"mikan.managed=true\";\n private static readonly IMAGE_MODE_LABEL = \"mikan.sandbox=image\";\n private static readonly VAULT_ID_LABEL_KEY = \"mikan.vault-id\";\n private static readonly CONVERSATION_ID_LABEL_KEY = \"mikan.conversation-id\";\n private static readonly MOUNT_SIGNATURE_LABEL_KEY = \"mikan.mount-signature\";\n private static readonly NETWORK_LABEL_KEY = \"mikan.network\";\n private static readonly IMAGE_ID_LABEL_KEY = \"mikan.image-id\";\n\n private readonly limits?: ResourceLimits;\n private readonly boostLimits?: ResourceLimits;\n private readonly boostedKeys = new Set<string>();\n private readonly overrideLimits = new Map<string, ResourceLimits>();\n private readonly execFileImpl: DockerExecFile;\n private readonly configuredEngine: string | undefined;\n private readonly timeZone: string;\n private imagePull?: Promise<void>;\n\n constructor(\n private readonly image: string,\n options: DockerContainerManagerOptions = {},\n ) {\n this.limits = options.limits;\n this.boostLimits = options.boostLimits;\n this.execFileImpl = options.execFileImpl ?? execFileAsync;\n this.configuredEngine = options.engine;\n this.timeZone = options.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;\n }\n\n private get engine(): string {\n return this.configuredEngine ?? containerEngine();\n }\n\n private run(args: string[]): Promise<{ stdout: string }> {\n return this.execFileImpl(this.engine, args);\n }\n\n static containerName(containerKey: string): string {\n return `mikan-sandbox-${containerKey}`;\n }\n\n static networkName(containerKey: string): string {\n return `mikan-sandbox-net-${containerKey}`;\n }\n\n private serialize<T>(containerKey: string, task: () => Promise<T>): Promise<T> {\n const previous = this.keyQueues.get(containerKey) ?? Promise.resolve();\n const next = previous.then(task, task);\n const settled = next.catch(() => undefined);\n this.keyQueues.set(containerKey, settled);\n void settled.then(() => {\n if (this.keyQueues.get(containerKey) === settled) this.keyQueues.delete(containerKey);\n });\n return next;\n }\n\n async provision(containerKey: string, options: ProvisionOptions = {}): Promise<string> {\n const existing = this.inflight.get(containerKey);\n if (existing) return existing;\n\n const pending = this.serialize(containerKey, () =>\n this.provisionInner(containerKey, options),\n ).finally(() => {\n this.inflight.delete(containerKey);\n });\n this.inflight.set(containerKey, pending);\n return pending;\n }\n\n private async provisionInner(containerKey: string, options: ProvisionOptions): Promise<string> {\n const containerName =\n options.containerName ?? DockerContainerManager.containerName(containerKey);\n const mounts = options.mounts ?? [];\n const status = await this.inspectStatus(containerName);\n\n try {\n const drift =\n status === \"missing\"\n ? undefined\n : await this.runtimeDrift(containerKey, containerName, mounts, status);\n if (drift) {\n log.logInfo(`Container ${containerName} is out of date (${drift}); replacing container`);\n const previousImage =\n drift === \"image\" ? await this.containerImage(containerName) : undefined;\n await this.replaceContainer(containerKey, containerName, mounts, options);\n log.logInfo(`Container ${containerName} replaced from image ${this.image}`);\n if (previousImage) await this.removeImageIfUnused(previousImage);\n } else if (status === \"stopped\") {\n await this.run([\"start\", containerName]);\n log.logInfo(`Container ${containerName} started`);\n } else if (status === \"missing\") {\n await this.runContainer(containerKey, containerName, mounts, options);\n log.logInfo(`Container ${containerName} created`);\n }\n } catch (err) {\n this.state.delete(containerKey);\n throw err;\n }\n\n this.setState(containerKey, \"running\", containerName);\n await this.applyResourceLimits(containerKey, containerName);\n return containerName;\n }\n\n async boost(containerKey: string): Promise<SandboxLimitStatus> {\n if (!this.boostLimits?.cpus && !this.boostLimits?.memory) {\n return this.getLimitStatus(containerKey);\n }\n\n this.overrideLimits.delete(containerKey);\n this.boostedKeys.add(containerKey);\n const state = this.state.get(containerKey);\n if (state?.status === \"running\") {\n await this.applyResourceLimits(containerKey, state.containerName);\n }\n return this.getLimitStatus(containerKey);\n }\n\n async setLimits(containerKey: string, limits: ResourceLimits): Promise<SandboxLimitStatus> {\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.set(containerKey, { ...this.limits, ...limits });\n const state = this.state.get(containerKey);\n if (state?.status === \"running\") {\n await this.applyResourceLimits(containerKey, state.containerName);\n }\n return this.getLimitStatus(containerKey);\n }\n\n getLimitStatus(containerKey: string): SandboxLimitStatus {\n const boosted = this.boostedKeys.has(containerKey);\n return { limits: this.effectiveLimits(containerKey), boosted };\n }\n\n getDefaultLimits(): ResourceLimits | undefined {\n return this.limits;\n }\n\n getBoostLimits(): ResourceLimits | undefined {\n return this.boostLimits;\n }\n\n markUsed(containerKey: string): void {\n const state = this.state.get(containerKey);\n if (state) state.lastUsed = Date.now();\n }\n\n stop(containerKey: string): Promise<void> {\n return this.serialize(containerKey, () => this.stopInner(containerKey));\n }\n\n private async stopInner(containerKey: string): Promise<void> {\n const containerName = this.getContainerName(containerKey);\n try {\n await this.run([\"stop\", containerName]);\n this.setState(containerKey, \"stopped\", containerName);\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.delete(containerKey);\n log.logInfo(`Container ${containerName} stopped (idle)`);\n } catch (err) {\n log.logWarning(`Failed to stop container ${containerName}`, errorMessage(err));\n }\n }\n\n remove(containerKey: string): Promise<void> {\n return this.serialize(containerKey, () => this.removeInner(containerKey));\n }\n\n private async removeInner(containerKey: string): Promise<void> {\n const containerName = this.getContainerName(containerKey);\n const networkName = DockerContainerManager.networkName(containerKey);\n\n const removed = await this.forceRemoveContainer(\n containerName,\n `Container ${containerName} removed`,\n `Failed to remove container ${containerName}`,\n );\n if (!removed) {\n throw new Error(`Failed to remove container ${containerName}`);\n }\n\n try {\n await this.run([\"network\", \"rm\", networkName]);\n log.logInfo(`Network ${networkName} removed`);\n } catch (err) {\n log.logWarning(`Failed to remove network ${networkName}`, errorMessage(err));\n }\n\n this.state.delete(containerKey);\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.delete(containerKey);\n }\n\n async stopIdle(maxIdleMs: number): Promise<void> {\n const now = Date.now();\n const toStop: string[] = [];\n for (const [containerKey, containerState] of this.state) {\n if (containerState.status === \"running\" && now - containerState.lastUsed > maxIdleMs) {\n toStop.push(containerKey);\n }\n }\n await Promise.all(toStop.map((containerKey) => this.stop(containerKey)));\n }\n\n async reconcile(workspaceRoot: string): Promise<void> {\n const names = await this.listContainerNamesByLabel();\n this.state.clear();\n\n const inspected = await Promise.all(\n names.map(async (containerName) => ({\n containerName,\n details: await this.inspectContainerDetails(containerName),\n })),\n );\n\n for (const { containerName, details } of inspected) {\n if (!details || !mountsWithin(details.bindSources, workspaceRoot)) continue;\n const containerKey = this.containerKeyFromContainerName(containerName);\n if (!containerKey) {\n log.logWarning(`Skipping unmanaged-style container without container key`, containerName);\n continue;\n }\n const status: ContainerStatus = details.running ? \"running\" : \"stopped\";\n const lastUsed = details.startedAtMs ?? Date.now();\n this.state.set(containerKey, { status, lastUsed, containerName });\n }\n\n const running = Array.from(this.state.values()).filter((s) => s.status === \"running\").length;\n const stopped = this.state.size - running;\n log.logInfo(\n `Reconciled ${this.state.size} managed containers (running=${running}, stopped=${stopped})`,\n );\n }\n\n private setState(containerKey: string, status: ContainerStatus, containerName: string): void {\n this.state.set(containerKey, { status, lastUsed: Date.now(), containerName });\n }\n\n private getContainerName(containerKey: string): string {\n return (\n this.state.get(containerKey)?.containerName ??\n DockerContainerManager.containerName(containerKey)\n );\n }\n\n private mountArgs(mounts: ContainerMount[]): string[] {\n return mounts.flatMap((mount) => [\"-v\", this.toBindSpec(mount)]);\n }\n\n private toBindSpec(mount: ContainerMount): string {\n return `${mount.source}:${mount.target}${mount.readOnly ? \":ro\" : \"\"}`;\n }\n\n private async runContainer(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n options: ProvisionOptions,\n ): Promise<void> {\n const networkName = await this.ensureNetwork(containerKey);\n log.logInfo(`Creating container ${containerName} from image ${this.image}`);\n const labels = [\n \"--label\",\n DockerContainerManager.MANAGED_LABEL,\n \"--label\",\n DockerContainerManager.IMAGE_MODE_LABEL,\n \"--label\",\n `${DockerContainerManager.VAULT_ID_LABEL_KEY}=${containerKey}`,\n ];\n if (options.conversationId) {\n labels.push(\n \"--label\",\n `${DockerContainerManager.CONVERSATION_ID_LABEL_KEY}=${options.conversationId}`,\n );\n }\n if (mounts.length > 0) {\n labels.push(\n \"--label\",\n `${DockerContainerManager.MOUNT_SIGNATURE_LABEL_KEY}=${this.mountSignature(mounts)}`,\n );\n }\n labels.push(\"--label\", `${DockerContainerManager.NETWORK_LABEL_KEY}=${networkName}`);\n labels.push(\n \"--label\",\n `${DockerContainerManager.IMAGE_ID_LABEL_KEY}=${await this.pulledImageId()}`,\n );\n await this.run([\n \"run\",\n \"-d\",\n \"--name\",\n containerName,\n \"--network\",\n networkName,\n \"--cap-drop\",\n \"ALL\",\n \"--security-opt\",\n \"no-new-privileges\",\n \"--pids-limit\",\n \"1024\",\n \"--env\",\n `TZ=${this.timeZone}`,\n ...labels,\n ...this.resourceLimitArgs(this.effectiveLimits(containerKey)),\n ...this.mountArgs(mounts),\n this.image,\n \"sleep\",\n \"infinity\",\n ]);\n }\n\n private effectiveLimits(containerKey: string): ResourceLimits | undefined {\n const override = this.overrideLimits.get(containerKey);\n if (override) return override;\n if (!this.boostedKeys.has(containerKey)) return this.limits;\n return { ...this.limits, ...this.boostLimits };\n }\n\n private resourceLimitArgs(limits: ResourceLimits | undefined): string[] {\n const args: string[] = [];\n if (limits?.cpus) args.push(...cpuQuotaArgs(limits.cpus));\n if (limits?.memory) {\n args.push(\"--memory\", limits.memory);\n args.push(\"--memory-swap\", limits.memory);\n }\n return args;\n }\n\n private async applyResourceLimits(containerKey: string, containerName: string): Promise<void> {\n const limitArgs = this.resourceLimitArgs(this.effectiveLimits(containerKey));\n if (limitArgs.length === 0) return;\n const args = [\"update\", ...limitArgs, containerName];\n try {\n await this.run(args);\n } catch (err) {\n log.logWarning(\n `Failed to apply resource limits to container ${containerName}`,\n errorMessage(err),\n );\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"apply_resource_limits\",\n severity: \"warning\",\n context: {\n sandboxType: \"oci\",\n containerKey,\n containerName,\n limitArgCount: limitArgs.length,\n fatal: false,\n },\n });\n }\n }\n\n private async runtimeDrift(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n status: ContainerStatus,\n ): Promise<DriftReason | undefined> {\n if (this.hasBindMountDrift(await this.inspectBindMounts(containerName), mounts)) return \"binds\";\n if (await this.hasMountSignatureDrift(containerName, mounts)) return \"mount-content\";\n if (await this.hasNetworkModeDrift(containerKey, containerName)) return \"network\";\n if (status === \"stopped\" && (await this.hasImageDrift(containerName))) return \"image\";\n return undefined;\n }\n\n private hasBindMountDrift(binds: readonly string[], mounts: ContainerMount[]): boolean {\n return !this.sameBinds(this.expectedBinds(mounts), [...binds]);\n }\n\n private expectedBinds(mounts: ContainerMount[]): string[] {\n return mounts\n .map((mount) => this.toBindSpec(mount))\n .slice()\n .toSorted();\n }\n\n private sameBinds(expected: string[], actual: string[]): boolean {\n if (expected.length !== actual.length) {\n return false;\n }\n\n return expected.every((bind, index) => bind === actual[index]);\n }\n\n private async hasMountSignatureDrift(\n containerName: string,\n mounts: ContainerMount[],\n ): Promise<boolean> {\n if (mounts.length === 0) return false;\n const expected = this.mountSignature(mounts);\n return (\n (await this.label(containerName, DockerContainerManager.MOUNT_SIGNATURE_LABEL_KEY)) !==\n expected\n );\n }\n\n private mountSignature(mounts: ContainerMount[]): string {\n const payload = mounts\n .map((mount) => ({\n source: mount.source,\n target: mount.target,\n fingerprint: this.mountSourceFingerprint(mount.source),\n }))\n .toSorted((left, right) =>\n `${left.target}\\0${left.source}`.localeCompare(`${right.target}\\0${right.source}`),\n );\n return createHash(\"sha256\").update(JSON.stringify(payload)).digest(\"hex\");\n }\n\n private mountSourceFingerprint(source: string): string {\n try {\n const stat = statSync(source);\n if (stat.isFile()) {\n return createHash(\"sha256\").update(readFileSync(source)).digest(\"hex\");\n }\n return `${stat.isDirectory() ? \"dir\" : \"other\"}:${stat.dev}:${stat.ino}:${stat.birthtimeMs}`;\n } catch {\n return \"missing\";\n }\n }\n\n private async label(containerName: string, key: string): Promise<string | undefined> {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{index .Config.Labels \"${key}\"}}`,\n containerName,\n ]);\n return this.normalizeDockerValue(stdout.trim());\n }\n\n private async inspectBindMounts(containerName: string): Promise<string[]> {\n const { stdout } = await this.run([\"inspect\", \"-f\", \"{{json .Mounts}}\", containerName]);\n return parseBindMounts(stdout, containerName)\n .map((mount) => `${mount.source}:${mount.target}${mount.readOnly ? \":ro\" : \"\"}`)\n .toSorted();\n }\n\n private async hasImageDrift(containerName: string): Promise<boolean> {\n const desired = await this.localImageId();\n if (!desired) return false;\n return (await this.label(containerName, DockerContainerManager.IMAGE_ID_LABEL_KEY)) !== desired;\n }\n\n private async localImageId(): Promise<string | undefined> {\n try {\n const { stdout } = await this.run([\"image\", \"inspect\", \"-f\", \"{{.Id}}\", this.image]);\n return this.normalizeDockerValue(stdout.trim());\n } catch {\n return undefined;\n }\n }\n\n prepareImage(): Promise<void> {\n this.imagePull ??= this.pullImage();\n return this.imagePull;\n }\n\n private async pullImage(): Promise<void> {\n try {\n await this.run([\"pull\", this.image]);\n log.logInfo(`Sandbox image ${this.image} is current`);\n } catch (err) {\n log.logWarning(\n `Could not pull sandbox image ${this.image}; offices keep the local image if there is one`,\n errorMessage(err),\n );\n }\n }\n\n private async containerImage(containerName: string): Promise<string | undefined> {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{.Config.Image}}\\t{{index .Config.Labels \"${DockerContainerManager.IMAGE_ID_LABEL_KEY}\"}}`,\n containerName,\n ]);\n const [reference = \"\", imageId] = stdout.trim().split(\"\\t\");\n if (reference !== this.image && isPublishedSandboxImage(reference)) return reference;\n return this.normalizeDockerValue(imageId);\n }\n\n private async removeImageIfUnused(image: string): Promise<void> {\n try {\n await this.run([\"rmi\", image]);\n log.logInfo(`Removed sandbox image ${image}, which no container uses`);\n } catch {\n return;\n }\n }\n\n private async pulledImageId(): Promise<string> {\n await this.imagePull;\n const local = await this.localImageId();\n if (local) return local;\n await this.run([\"pull\", this.image]);\n const pulled = await this.localImageId();\n if (!pulled) throw new Error(`Image ${this.image} has no ID after pulling it`);\n return pulled;\n }\n\n private async replaceContainer(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n options: ProvisionOptions,\n ): Promise<void> {\n const removed = await this.forceRemoveContainer(\n containerName,\n `Container ${containerName} removed for replacement`,\n `Failed to remove container ${containerName} for replacement`,\n );\n if (!removed) throw new Error(`Failed to remove container ${containerName} for replacement`);\n await this.runContainer(containerKey, containerName, mounts, options);\n }\n\n private async hasNetworkModeDrift(containerKey: string, containerName: string): Promise<boolean> {\n const expected = DockerContainerManager.networkName(containerKey);\n return (await this.label(containerName, DockerContainerManager.NETWORK_LABEL_KEY)) !== expected;\n }\n\n private async ensureNetwork(containerKey: string): Promise<string> {\n const networkName = DockerContainerManager.networkName(containerKey);\n const { stdout } = await this.run([\n \"network\",\n \"ls\",\n \"--filter\",\n `name=^${networkName}$`,\n \"--format\",\n \"{{.Name}}\",\n ]);\n if (this.parseNameLines(stdout).includes(networkName)) return networkName;\n await this.run([\n \"network\",\n \"create\",\n \"--driver\",\n \"bridge\",\n \"--label\",\n DockerContainerManager.MANAGED_LABEL,\n \"--label\",\n DockerContainerManager.IMAGE_MODE_LABEL,\n \"--label\",\n `${DockerContainerManager.VAULT_ID_LABEL_KEY}=${containerKey}`,\n networkName,\n ]);\n return networkName;\n }\n\n private async containerExists(containerName: string): Promise<boolean> {\n const { stdout } = await this.run([\n \"ps\",\n \"-a\",\n \"--filter\",\n `name=^${containerName}$`,\n \"--format\",\n \"{{.Names}}\",\n ]);\n return this.parseNameLines(stdout).includes(containerName);\n }\n\n private async inspectStatus(containerName: string): Promise<ContainerStatus> {\n if (!(await this.containerExists(containerName))) return \"missing\";\n const { stdout } = await this.run([\"inspect\", \"-f\", \"{{.State.Running}}\", containerName]);\n return stdout.trim() === \"true\" ? \"running\" : \"stopped\";\n }\n\n private async listContainerNamesByLabel(): Promise<string[]> {\n try {\n const { stdout } = await this.run([\n \"ps\",\n \"-a\",\n \"--filter\",\n `label=${DockerContainerManager.MANAGED_LABEL}`,\n \"--filter\",\n `label=${DockerContainerManager.IMAGE_MODE_LABEL}`,\n \"--format\",\n \"{{.Names}}\",\n ]);\n return this.parseNameLines(stdout);\n } catch (err) {\n log.logWarning(\"Failed to list labeled managed containers\", errorMessage(err));\n return [];\n }\n }\n\n private parseNameLines(stdout: string): string[] {\n return stdout\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n }\n\n private async inspectContainerDetails(\n containerName: string,\n ): Promise<{ running: boolean; startedAtMs?: number; bindSources: string[] } | undefined> {\n try {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{.State.Running}}\\t{{.State.StartedAt}}\\t{{json .Mounts}}`,\n containerName,\n ]);\n const [runningRaw, startedAtRaw, mountsRaw] = stdout.trim().split(\"\\t\");\n const running = runningRaw === \"true\";\n const startedAtMs = parseEngineTimestamp(this.normalizeDockerValue(startedAtRaw));\n const bindSources = parseBindMounts(mountsRaw ?? \"\", containerName).map(\n (mount) => mount.source,\n );\n return { running, startedAtMs, bindSources };\n } catch (err) {\n log.logWarning(\n `Failed to inspect container ${containerName} during reconcile`,\n errorMessage(err),\n );\n return undefined;\n }\n }\n\n private normalizeDockerValue(value?: string): string | undefined {\n if (!value || value === \"<no value>\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n\n private containerKeyFromContainerName(containerName: string): string | undefined {\n const prefix = DockerContainerManager.containerName(\"\");\n if (!containerName.startsWith(prefix)) return undefined;\n const containerKey = containerName.slice(prefix.length);\n return containerKey.length > 0 ? containerKey : undefined;\n }\n\n private async forceRemoveContainer(\n containerName: string,\n successLog: string,\n failureLog: string,\n ): Promise<boolean> {\n try {\n if (await this.containerExists(containerName)) {\n await this.run([\"kill\", containerName]).catch(() => undefined);\n await this.run([\"rm\", \"-f\", containerName]);\n }\n log.logInfo(successLog);\n return true;\n } catch (err) {\n log.logWarning(failureLog, errorMessage(err));\n return false;\n }\n }\n}\n\nconst CPU_PERIOD_MICROSECONDS = 100_000;\n\nfunction cpuQuotaArgs(cpus: string): string[] {\n const quota = Math.round(Number(cpus) * CPU_PERIOD_MICROSECONDS);\n if (!Number.isFinite(quota) || quota <= 0) throw new Error(`Invalid CPU limit: ${cpus}`);\n return [\"--cpu-period\", String(CPU_PERIOD_MICROSECONDS), \"--cpu-quota\", String(quota)];\n}\n\ninterface BindMount {\n source: string;\n target: string;\n readOnly: boolean;\n}\n\nfunction parseBindMounts(raw: string, containerName: string): BindMount[] {\n const payload = raw.trim();\n const parsed: unknown = JSON.parse(payload.length > 0 ? payload : \"null\");\n if (parsed === null) return [];\n if (!Array.isArray(parsed)) {\n throw new Error(`Unexpected mount payload for container \"${containerName}\"`);\n }\n return parsed.flatMap((entry: unknown) => {\n if (!isRecord(entry) || entry.Type !== \"bind\") return [];\n const { Source: source, Destination: target, RW: writable } = entry;\n if (typeof source !== \"string\" || typeof target !== \"string\") return [];\n return [{ source, target, readOnly: writable === false }];\n });\n}\n\nconst ENGINE_LOCAL_TIMESTAMP =\n /^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?) ([+-]\\d{2})(\\d{2})/;\n\nfunction parseEngineTimestamp(value: string | undefined): number | undefined {\n if (!value || value.startsWith(\"0001-\")) return undefined;\n const local = ENGINE_LOCAL_TIMESTAMP.exec(value);\n const iso = local ? `${local[1]}T${local[2]}${local[3]}:${local[4]}` : value;\n const parsed = Date.parse(iso);\n return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction mountsWithin(sources: readonly string[], root: string): boolean {\n return sources.some((source) => {\n const path = relative(root, source);\n return path !== \"\" && !path.startsWith(\"..\") && !isAbsolute(path);\n });\n}\n"]}
1
+ {"version":3,"file":"provisioner.js","sourceRoot":"","sources":["../../src/sandbox/provisioner.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport * as log from \"../log.js\";\nimport { isPublishedSandboxImage } from \"./published-image.js\";\nimport { reportUserFacingError } from \"../observability/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\ntype ContainerStatus = \"running\" | \"stopped\" | \"missing\";\ntype DriftReason = \"binds\" | \"mount-content\" | \"network\" | \"image\";\n\ninterface ContainerState {\n status: ContainerStatus;\n lastUsed: number;\n containerName: string;\n}\n\nimport type {\n ContainerMount,\n DockerContainerManagerOptions,\n ProvisionOptions,\n ResourceLimits,\n SandboxLimitStatus,\n} from \"../types.js\";\nimport { errorMessage, isRecord } from \"../unknown-values.js\";\nimport type { DockerExecFile } from \"./types.js\";\nimport { containerEngine } from \"./engine.js\";\n\nexport class DockerContainerManager {\n private state = new Map<string, ContainerState>();\n private inflight = new Map<string, Promise<string>>();\n private keyQueues = new Map<string, Promise<unknown>>();\n private static readonly MANAGED_LABEL = \"mikan.managed=true\";\n private static readonly IMAGE_MODE_LABEL = \"mikan.sandbox=image\";\n private static readonly VAULT_ID_LABEL_KEY = \"mikan.vault-id\";\n private static readonly CONVERSATION_ID_LABEL_KEY = \"mikan.conversation-id\";\n private static readonly MOUNT_SIGNATURE_LABEL_KEY = \"mikan.mount-signature\";\n private static readonly NETWORK_LABEL_KEY = \"mikan.network\";\n private static readonly IMAGE_ID_LABEL_KEY = \"mikan.image-id\";\n\n private readonly limits?: ResourceLimits;\n private readonly boostLimits?: ResourceLimits;\n private readonly boostedKeys = new Set<string>();\n private readonly retained = new Map<string, number>();\n private readonly overrideLimits = new Map<string, ResourceLimits>();\n private readonly execFileImpl: DockerExecFile;\n private readonly configuredEngine: string | undefined;\n private readonly timeZone: string;\n private imagePull?: Promise<void>;\n\n constructor(\n private readonly image: string,\n options: DockerContainerManagerOptions = {},\n ) {\n this.limits = options.limits;\n this.boostLimits = options.boostLimits;\n this.execFileImpl = options.execFileImpl ?? execFileAsync;\n this.configuredEngine = options.engine;\n this.timeZone = options.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;\n }\n\n get engine(): string {\n return this.configuredEngine ?? containerEngine();\n }\n\n private run(args: string[]): Promise<{ stdout: string }> {\n return this.execFileImpl(this.engine, args);\n }\n\n static containerName(containerKey: string): string {\n return `mikan-sandbox-${containerKey}`;\n }\n\n static networkName(containerKey: string): string {\n return `mikan-sandbox-net-${containerKey}`;\n }\n\n private serialize<T>(containerKey: string, task: () => Promise<T>): Promise<T> {\n const previous = this.keyQueues.get(containerKey) ?? Promise.resolve();\n const next = previous.then(task, task);\n const settled = next.catch(() => undefined);\n this.keyQueues.set(containerKey, settled);\n void settled.then(() => {\n if (this.keyQueues.get(containerKey) === settled) this.keyQueues.delete(containerKey);\n });\n return next;\n }\n\n async provision(containerKey: string, options: ProvisionOptions = {}): Promise<string> {\n const existing = this.inflight.get(containerKey);\n if (existing) return existing;\n\n const pending = this.serialize(containerKey, () =>\n this.provisionInner(containerKey, options),\n ).finally(() => {\n this.inflight.delete(containerKey);\n });\n this.inflight.set(containerKey, pending);\n return pending;\n }\n\n private async provisionInner(containerKey: string, options: ProvisionOptions): Promise<string> {\n const containerName =\n options.containerName ?? DockerContainerManager.containerName(containerKey);\n const mounts = options.mounts ?? [];\n const status = await this.inspectStatus(containerName);\n\n try {\n const drift =\n status === \"missing\"\n ? undefined\n : await this.runtimeDrift(containerKey, containerName, mounts, status);\n if (drift) {\n log.logInfo(`Container ${containerName} is out of date (${drift}); replacing container`);\n const leftBehind = await this.imageLeftBehind(containerName);\n await this.replaceContainer(containerKey, containerName, mounts, options);\n log.logInfo(`Container ${containerName} replaced from image ${this.image}`);\n if (leftBehind) await this.removeImageIfUnused(leftBehind);\n } else if (status === \"stopped\") {\n await this.run([\"start\", containerName]);\n log.logInfo(`Container ${containerName} started`);\n } else if (status === \"missing\") {\n await this.runContainer(containerKey, containerName, mounts, options);\n log.logInfo(`Container ${containerName} created`);\n }\n } catch (err) {\n this.state.delete(containerKey);\n throw err;\n }\n\n this.setState(containerKey, \"running\", containerName);\n await this.applyResourceLimits(containerKey, containerName);\n return containerName;\n }\n\n async boost(containerKey: string): Promise<SandboxLimitStatus> {\n if (!this.boostLimits?.cpus && !this.boostLimits?.memory) {\n return this.getLimitStatus(containerKey);\n }\n\n this.overrideLimits.delete(containerKey);\n this.boostedKeys.add(containerKey);\n const state = this.state.get(containerKey);\n if (state?.status === \"running\") {\n await this.applyResourceLimits(containerKey, state.containerName);\n }\n return this.getLimitStatus(containerKey);\n }\n\n async setLimits(containerKey: string, limits: ResourceLimits): Promise<SandboxLimitStatus> {\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.set(containerKey, { ...this.limits, ...limits });\n const state = this.state.get(containerKey);\n if (state?.status === \"running\") {\n await this.applyResourceLimits(containerKey, state.containerName);\n }\n return this.getLimitStatus(containerKey);\n }\n\n getLimitStatus(containerKey: string): SandboxLimitStatus {\n const boosted = this.boostedKeys.has(containerKey);\n return { limits: this.effectiveLimits(containerKey), boosted };\n }\n\n getDefaultLimits(): ResourceLimits | undefined {\n return this.limits;\n }\n\n getBoostLimits(): ResourceLimits | undefined {\n return this.boostLimits;\n }\n\n markUsed(containerKey: string): void {\n const state = this.state.get(containerKey);\n if (state) state.lastUsed = Date.now();\n }\n\n isRunning(containerKey: string): boolean {\n return this.state.get(containerKey)?.status === \"running\";\n }\n\n retain(containerKey: string): () => void {\n this.retained.set(containerKey, (this.retained.get(containerKey) ?? 0) + 1);\n let released = false;\n return () => {\n if (released) return;\n released = true;\n const remaining = (this.retained.get(containerKey) ?? 1) - 1;\n if (remaining > 0) this.retained.set(containerKey, remaining);\n else this.retained.delete(containerKey);\n this.markUsed(containerKey);\n };\n }\n\n stop(containerKey: string): Promise<void> {\n return this.serialize(containerKey, () => this.stopInner(containerKey));\n }\n\n private async stopInner(containerKey: string): Promise<void> {\n const containerName = this.getContainerName(containerKey);\n try {\n await this.run([\"stop\", containerName]);\n this.setState(containerKey, \"stopped\", containerName);\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.delete(containerKey);\n log.logInfo(`Container ${containerName} stopped (idle)`);\n } catch (err) {\n log.logWarning(`Failed to stop container ${containerName}`, errorMessage(err));\n }\n }\n\n remove(containerKey: string): Promise<void> {\n return this.serialize(containerKey, () => this.removeInner(containerKey));\n }\n\n private async removeInner(containerKey: string): Promise<void> {\n const containerName = this.getContainerName(containerKey);\n const networkName = DockerContainerManager.networkName(containerKey);\n\n const removed = await this.forceRemoveContainer(\n containerName,\n `Container ${containerName} removed`,\n `Failed to remove container ${containerName}`,\n );\n if (!removed) {\n throw new Error(`Failed to remove container ${containerName}`);\n }\n\n try {\n await this.run([\"network\", \"rm\", networkName]);\n log.logInfo(`Network ${networkName} removed`);\n } catch (err) {\n log.logWarning(`Failed to remove network ${networkName}`, errorMessage(err));\n }\n\n this.state.delete(containerKey);\n this.boostedKeys.delete(containerKey);\n this.overrideLimits.delete(containerKey);\n }\n\n async stopIdle(maxIdleMs: number): Promise<void> {\n const now = Date.now();\n const toStop: string[] = [];\n for (const [containerKey, containerState] of this.state) {\n if (this.retained.has(containerKey)) continue;\n if (containerState.status === \"running\" && now - containerState.lastUsed > maxIdleMs) {\n toStop.push(containerKey);\n }\n }\n await Promise.all(toStop.map((containerKey) => this.stop(containerKey)));\n }\n\n async reconcile(workspaceRoot: string): Promise<void> {\n const names = await this.listContainerNamesByLabel();\n this.state.clear();\n\n const inspected = await Promise.all(\n names.map(async (containerName) => ({\n containerName,\n details: await this.inspectContainerDetails(containerName),\n })),\n );\n\n for (const { containerName, details } of inspected) {\n if (!details || !mountsWithin(details.bindSources, workspaceRoot)) continue;\n const containerKey = this.containerKeyFromContainerName(containerName);\n if (!containerKey) {\n log.logWarning(`Skipping unmanaged-style container without container key`, containerName);\n continue;\n }\n const status: ContainerStatus = details.running ? \"running\" : \"stopped\";\n const lastUsed = details.startedAtMs ?? Date.now();\n this.state.set(containerKey, { status, lastUsed, containerName });\n }\n\n const running = Array.from(this.state.values()).filter((s) => s.status === \"running\").length;\n const stopped = this.state.size - running;\n log.logInfo(\n `Reconciled ${this.state.size} managed containers (running=${running}, stopped=${stopped})`,\n );\n }\n\n private setState(containerKey: string, status: ContainerStatus, containerName: string): void {\n this.state.set(containerKey, { status, lastUsed: Date.now(), containerName });\n }\n\n private getContainerName(containerKey: string): string {\n return (\n this.state.get(containerKey)?.containerName ??\n DockerContainerManager.containerName(containerKey)\n );\n }\n\n private mountArgs(mounts: ContainerMount[]): string[] {\n return mounts.flatMap((mount) => [\"-v\", this.toBindSpec(mount)]);\n }\n\n private toBindSpec(mount: ContainerMount): string {\n return `${mount.source}:${mount.target}${mount.readOnly ? \":ro\" : \"\"}`;\n }\n\n private async runContainer(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n options: ProvisionOptions,\n ): Promise<void> {\n const networkName = await this.ensureNetwork(containerKey);\n log.logInfo(`Creating container ${containerName} from image ${this.image}`);\n const labels = [\n \"--label\",\n DockerContainerManager.MANAGED_LABEL,\n \"--label\",\n DockerContainerManager.IMAGE_MODE_LABEL,\n \"--label\",\n `${DockerContainerManager.VAULT_ID_LABEL_KEY}=${containerKey}`,\n ];\n if (options.conversationId) {\n labels.push(\n \"--label\",\n `${DockerContainerManager.CONVERSATION_ID_LABEL_KEY}=${options.conversationId}`,\n );\n }\n if (mounts.length > 0) {\n labels.push(\n \"--label\",\n `${DockerContainerManager.MOUNT_SIGNATURE_LABEL_KEY}=${this.mountSignature(mounts)}`,\n );\n }\n labels.push(\"--label\", `${DockerContainerManager.NETWORK_LABEL_KEY}=${networkName}`);\n labels.push(\n \"--label\",\n `${DockerContainerManager.IMAGE_ID_LABEL_KEY}=${await this.pulledImageId()}`,\n );\n await this.run([\n \"run\",\n \"-d\",\n \"--name\",\n containerName,\n \"--network\",\n networkName,\n \"--cap-drop\",\n \"ALL\",\n \"--security-opt\",\n \"no-new-privileges\",\n \"--pids-limit\",\n \"1024\",\n \"--env\",\n `TZ=${this.timeZone}`,\n ...labels,\n ...this.resourceLimitArgs(this.effectiveLimits(containerKey)),\n ...this.mountArgs(mounts),\n this.image,\n \"sleep\",\n \"infinity\",\n ]);\n }\n\n private effectiveLimits(containerKey: string): ResourceLimits | undefined {\n const override = this.overrideLimits.get(containerKey);\n if (override) return override;\n if (!this.boostedKeys.has(containerKey)) return this.limits;\n return { ...this.limits, ...this.boostLimits };\n }\n\n private resourceLimitArgs(limits: ResourceLimits | undefined): string[] {\n const args: string[] = [];\n if (limits?.cpus) args.push(...cpuQuotaArgs(limits.cpus));\n if (limits?.memory) {\n args.push(\"--memory\", limits.memory);\n args.push(\"--memory-swap\", limits.memory);\n }\n return args;\n }\n\n private async applyResourceLimits(containerKey: string, containerName: string): Promise<void> {\n const limitArgs = this.resourceLimitArgs(this.effectiveLimits(containerKey));\n if (limitArgs.length === 0) return;\n const args = [\"update\", ...limitArgs, containerName];\n try {\n await this.run(args);\n } catch (err) {\n log.logWarning(\n `Failed to apply resource limits to container ${containerName}`,\n errorMessage(err),\n );\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"apply_resource_limits\",\n severity: \"warning\",\n context: {\n sandboxType: \"oci\",\n containerKey,\n containerName,\n limitArgCount: limitArgs.length,\n fatal: false,\n },\n });\n }\n }\n\n private async runtimeDrift(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n status: ContainerStatus,\n ): Promise<DriftReason | undefined> {\n if (this.hasBindMountDrift(await this.inspectBindMounts(containerName), mounts)) return \"binds\";\n if (await this.hasMountSignatureDrift(containerName, mounts)) return \"mount-content\";\n if (await this.hasNetworkModeDrift(containerKey, containerName)) return \"network\";\n if (status === \"stopped\" && (await this.hasImageDrift(containerName))) return \"image\";\n return undefined;\n }\n\n private hasBindMountDrift(binds: readonly string[], mounts: ContainerMount[]): boolean {\n return !this.sameBinds(this.expectedBinds(mounts), [...binds]);\n }\n\n private expectedBinds(mounts: ContainerMount[]): string[] {\n return mounts\n .map((mount) => this.toBindSpec(mount))\n .slice()\n .toSorted();\n }\n\n private sameBinds(expected: string[], actual: string[]): boolean {\n if (expected.length !== actual.length) {\n return false;\n }\n\n return expected.every((bind, index) => bind === actual[index]);\n }\n\n private async hasMountSignatureDrift(\n containerName: string,\n mounts: ContainerMount[],\n ): Promise<boolean> {\n if (mounts.length === 0) return false;\n const expected = this.mountSignature(mounts);\n return (\n (await this.label(containerName, DockerContainerManager.MOUNT_SIGNATURE_LABEL_KEY)) !==\n expected\n );\n }\n\n private mountSignature(mounts: ContainerMount[]): string {\n const payload = mounts\n .map((mount) => ({\n source: mount.source,\n target: mount.target,\n fingerprint: this.mountSourceFingerprint(mount.source),\n }))\n .toSorted((left, right) =>\n `${left.target}\\0${left.source}`.localeCompare(`${right.target}\\0${right.source}`),\n );\n return createHash(\"sha256\").update(JSON.stringify(payload)).digest(\"hex\");\n }\n\n private mountSourceFingerprint(source: string): string {\n try {\n const stat = statSync(source);\n if (stat.isFile()) {\n return createHash(\"sha256\").update(readFileSync(source)).digest(\"hex\");\n }\n return `${stat.isDirectory() ? \"dir\" : \"other\"}:${stat.dev}:${stat.ino}:${stat.birthtimeMs}`;\n } catch {\n return \"missing\";\n }\n }\n\n private async label(containerName: string, key: string): Promise<string | undefined> {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{index .Config.Labels \"${key}\"}}`,\n containerName,\n ]);\n return this.normalizeDockerValue(stdout.trim());\n }\n\n private async inspectBindMounts(containerName: string): Promise<string[]> {\n const { stdout } = await this.run([\"inspect\", \"-f\", \"{{json .Mounts}}\", containerName]);\n return parseBindMounts(stdout, containerName)\n .map((mount) => `${mount.source}:${mount.target}${mount.readOnly ? \":ro\" : \"\"}`)\n .toSorted();\n }\n\n private async hasImageDrift(containerName: string): Promise<boolean> {\n const desired = await this.localImageId();\n if (!desired) return false;\n return (await this.label(containerName, DockerContainerManager.IMAGE_ID_LABEL_KEY)) !== desired;\n }\n\n private async localImageId(): Promise<string | undefined> {\n try {\n const { stdout } = await this.run([\"image\", \"inspect\", \"-f\", \"{{.Id}}\", this.image]);\n return this.normalizeDockerValue(stdout.trim());\n } catch {\n return undefined;\n }\n }\n\n prepareImage(): Promise<void> {\n this.imagePull ??= this.pullImage();\n return this.imagePull;\n }\n\n private async pullImage(): Promise<void> {\n try {\n await this.run([\"pull\", this.image]);\n log.logInfo(`Sandbox image ${this.image} is current`);\n } catch (err) {\n log.logWarning(\n `Could not pull sandbox image ${this.image}; offices keep the local image if there is one`,\n errorMessage(err),\n );\n }\n }\n\n private async imageLeftBehind(containerName: string): Promise<string | undefined> {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{.Config.Image}}\\t{{index .Config.Labels \"${DockerContainerManager.IMAGE_ID_LABEL_KEY}\"}}`,\n containerName,\n ]);\n const [reference = \"\", label] = stdout.trim().split(\"\\t\");\n const imageId = this.normalizeDockerValue(label);\n if (imageId && imageId === (await this.localImageId())) return undefined;\n if (reference !== this.image && isPublishedSandboxImage(reference)) return reference;\n if (imageId && (await this.isUnnamedImage(imageId))) return imageId;\n return undefined;\n }\n\n private async isUnnamedImage(imageId: string): Promise<boolean> {\n try {\n const { stdout } = await this.run([\"image\", \"inspect\", \"-f\", \"{{len .RepoTags}}\", imageId]);\n return stdout.trim() === \"0\";\n } catch {\n return false;\n }\n }\n\n private async removeImageIfUnused(image: string): Promise<void> {\n try {\n await this.run([\"rmi\", image]);\n log.logInfo(`Removed sandbox image ${image}, which no container uses`);\n } catch {\n return;\n }\n }\n\n private async pulledImageId(): Promise<string> {\n await this.imagePull;\n const local = await this.localImageId();\n if (local) return local;\n await this.run([\"pull\", this.image]);\n const pulled = await this.localImageId();\n if (!pulled) throw new Error(`Image ${this.image} has no ID after pulling it`);\n return pulled;\n }\n\n private async replaceContainer(\n containerKey: string,\n containerName: string,\n mounts: ContainerMount[],\n options: ProvisionOptions,\n ): Promise<void> {\n const removed = await this.forceRemoveContainer(\n containerName,\n `Container ${containerName} removed for replacement`,\n `Failed to remove container ${containerName} for replacement`,\n );\n if (!removed) throw new Error(`Failed to remove container ${containerName} for replacement`);\n await this.runContainer(containerKey, containerName, mounts, options);\n }\n\n private async hasNetworkModeDrift(containerKey: string, containerName: string): Promise<boolean> {\n const expected = DockerContainerManager.networkName(containerKey);\n return (await this.label(containerName, DockerContainerManager.NETWORK_LABEL_KEY)) !== expected;\n }\n\n private async ensureNetwork(containerKey: string): Promise<string> {\n const networkName = DockerContainerManager.networkName(containerKey);\n const { stdout } = await this.run([\n \"network\",\n \"ls\",\n \"--filter\",\n `name=^${networkName}$`,\n \"--format\",\n \"{{.Name}}\",\n ]);\n if (this.parseNameLines(stdout).includes(networkName)) return networkName;\n await this.run([\n \"network\",\n \"create\",\n \"--driver\",\n \"bridge\",\n \"--label\",\n DockerContainerManager.MANAGED_LABEL,\n \"--label\",\n DockerContainerManager.IMAGE_MODE_LABEL,\n \"--label\",\n `${DockerContainerManager.VAULT_ID_LABEL_KEY}=${containerKey}`,\n networkName,\n ]);\n return networkName;\n }\n\n private async containerExists(containerName: string): Promise<boolean> {\n const { stdout } = await this.run([\n \"ps\",\n \"-a\",\n \"--filter\",\n `name=^${containerName}$`,\n \"--format\",\n \"{{.Names}}\",\n ]);\n return this.parseNameLines(stdout).includes(containerName);\n }\n\n private async inspectStatus(containerName: string): Promise<ContainerStatus> {\n if (!(await this.containerExists(containerName))) return \"missing\";\n const { stdout } = await this.run([\"inspect\", \"-f\", \"{{.State.Running}}\", containerName]);\n return stdout.trim() === \"true\" ? \"running\" : \"stopped\";\n }\n\n private async listContainerNamesByLabel(): Promise<string[]> {\n try {\n const { stdout } = await this.run([\n \"ps\",\n \"-a\",\n \"--filter\",\n `label=${DockerContainerManager.MANAGED_LABEL}`,\n \"--filter\",\n `label=${DockerContainerManager.IMAGE_MODE_LABEL}`,\n \"--format\",\n \"{{.Names}}\",\n ]);\n return this.parseNameLines(stdout);\n } catch (err) {\n log.logWarning(\"Failed to list labeled managed containers\", errorMessage(err));\n return [];\n }\n }\n\n private parseNameLines(stdout: string): string[] {\n return stdout\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n }\n\n private async inspectContainerDetails(\n containerName: string,\n ): Promise<{ running: boolean; startedAtMs?: number; bindSources: string[] } | undefined> {\n try {\n const { stdout } = await this.run([\n \"inspect\",\n \"-f\",\n `{{.State.Running}}\\t{{.State.StartedAt}}\\t{{json .Mounts}}`,\n containerName,\n ]);\n const [runningRaw, startedAtRaw, mountsRaw] = stdout.trim().split(\"\\t\");\n const running = runningRaw === \"true\";\n const startedAtMs = parseEngineTimestamp(this.normalizeDockerValue(startedAtRaw));\n const bindSources = parseBindMounts(mountsRaw ?? \"\", containerName).map(\n (mount) => mount.source,\n );\n return { running, startedAtMs, bindSources };\n } catch (err) {\n log.logWarning(\n `Failed to inspect container ${containerName} during reconcile`,\n errorMessage(err),\n );\n return undefined;\n }\n }\n\n private normalizeDockerValue(value?: string): string | undefined {\n if (!value || value === \"<no value>\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n\n private containerKeyFromContainerName(containerName: string): string | undefined {\n const prefix = DockerContainerManager.containerName(\"\");\n if (!containerName.startsWith(prefix)) return undefined;\n const containerKey = containerName.slice(prefix.length);\n return containerKey.length > 0 ? containerKey : undefined;\n }\n\n private async forceRemoveContainer(\n containerName: string,\n successLog: string,\n failureLog: string,\n ): Promise<boolean> {\n try {\n if (await this.containerExists(containerName)) {\n await this.run([\"kill\", containerName]).catch(() => undefined);\n await this.run([\"rm\", \"-f\", containerName]);\n }\n log.logInfo(successLog);\n return true;\n } catch (err) {\n log.logWarning(failureLog, errorMessage(err));\n return false;\n }\n }\n}\n\nconst CPU_PERIOD_MICROSECONDS = 100_000;\n\nfunction cpuQuotaArgs(cpus: string): string[] {\n const quota = Math.round(Number(cpus) * CPU_PERIOD_MICROSECONDS);\n if (!Number.isFinite(quota) || quota <= 0) throw new Error(`Invalid CPU limit: ${cpus}`);\n return [\"--cpu-period\", String(CPU_PERIOD_MICROSECONDS), \"--cpu-quota\", String(quota)];\n}\n\ninterface BindMount {\n source: string;\n target: string;\n readOnly: boolean;\n}\n\nfunction parseBindMounts(raw: string, containerName: string): BindMount[] {\n const payload = raw.trim();\n const parsed: unknown = JSON.parse(payload.length > 0 ? payload : \"null\");\n if (parsed === null) return [];\n if (!Array.isArray(parsed)) {\n throw new Error(`Unexpected mount payload for container \"${containerName}\"`);\n }\n return parsed.flatMap((entry: unknown) => {\n if (!isRecord(entry) || entry.Type !== \"bind\") return [];\n const { Source: source, Destination: target, RW: writable } = entry;\n if (typeof source !== \"string\" || typeof target !== \"string\") return [];\n return [{ source, target, readOnly: writable === false }];\n });\n}\n\nconst ENGINE_LOCAL_TIMESTAMP =\n /^(\\d{4}-\\d{2}-\\d{2}) (\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?) ([+-]\\d{2})(\\d{2})/;\n\nfunction parseEngineTimestamp(value: string | undefined): number | undefined {\n if (!value || value.startsWith(\"0001-\")) return undefined;\n const local = ENGINE_LOCAL_TIMESTAMP.exec(value);\n const iso = local ? `${local[1]}T${local[2]}${local[3]}:${local[4]}` : value;\n const parsed = Date.parse(iso);\n return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction mountsWithin(sources: readonly string[], root: string): boolean {\n return sources.some((source) => {\n const path = relative(root, source);\n return path !== \"\" && !path.startsWith(\"..\") && !isAbsolute(path);\n });\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { Readable, Writable } from "node:stream";
1
2
  import type { ExecutionEnv } from "@earendil-works/pi-durable/env";
2
3
  import type { OfficeAddress } from "../types.js";
3
4
  export type SandboxConfig = HostSandboxConfig | ContainerSandboxConfig | OciSandboxConfig;
@@ -49,5 +50,23 @@ export interface SandboxAdapter<TConfig extends SandboxConfig = SandboxConfig> {
49
50
  validate?(config: TConfig): Promise<void>;
50
51
  createEnv?(config: TConfig, options: SandboxEnvOptions): ExecutionEnv;
51
52
  }
53
+ export type BrowserOwner = "agent" | "user";
54
+ export interface DesktopStatus {
55
+ display?: string;
56
+ control: BrowserOwner;
57
+ }
58
+ export type DesktopStart = "ready" | "outdated-image" | "stopped";
59
+ export interface DesktopProcess {
60
+ stdin: Writable | null;
61
+ stdout: Readable | null;
62
+ kill(): unknown;
63
+ once(event: "exit" | "error", listener: () => void): unknown;
64
+ }
65
+ export interface DesktopStream {
66
+ input: Writable;
67
+ output: Readable;
68
+ process: Pick<DesktopProcess, "once">;
69
+ close(): void;
70
+ }
52
71
  export {};
53
72
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,sBAAsB,GAAG,gBAAgB,CAAC;AAE1F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;CACrD;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE3F,MAAM,WAAW,6BAA6B;IAC5C,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,UAAU,4BAA4B;IACpC,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa;IAC3E,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,WAAW,EAAE,6BAA6B,CAAC;IAC3C,SAAS,EAAE,4BAA4B,CAAC;IACxC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,SAAS,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,YAAY,CAAC;CACvE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ExecutionEnv } from \"@earendil-works/pi-durable/env\";\nimport type { OfficeAddress } from \"../types.js\";\n\nexport type SandboxConfig = HostSandboxConfig | ContainerSandboxConfig | OciSandboxConfig;\n\nexport interface HostSandboxConfig {\n type: \"host\";\n}\n\nexport interface ContainerSandboxConfig {\n type: \"container\";\n container: string;\n}\n\nexport interface OciSandboxConfig {\n type: \"oci\";\n image: string;\n}\n\nexport interface SandboxEnvOptions {\n cwd: string;\n env?: Record<string, string>;\n ensureReady?: () => Promise<void>;\n markUsed?: () => void;\n}\n\nexport interface ContainerExecutionEnvOptions extends SandboxEnvOptions {\n container: string;\n engine?: string;\n}\n\nexport interface RuntimePathContext {\n hostWorkspaceRoot: string;\n runtimeWorkspaceRoot: string;\n runtimeToHostPath?: (runtimePath: string) => string;\n}\n\nexport type DockerExecFile = (file: string, args: string[]) => Promise<{ stdout: string }>;\n\nexport interface SandboxCredentialCapabilities {\n env: boolean;\n fileMounts: boolean;\n}\n\nexport interface CredentialScope {\n userId: string;\n address: OfficeAddress;\n}\n\ninterface SandboxWorkspaceCapabilities {\n managedProjection: boolean;\n}\n\nexport interface SandboxAdapter<TConfig extends SandboxConfig = SandboxConfig> {\n type: TConfig[\"type\"];\n credentials: SandboxCredentialCapabilities;\n workspace: SandboxWorkspaceCapabilities;\n parse(value: string): TConfig | undefined;\n validate?(config: TConfig): Promise<void>;\n createEnv?(config: TConfig, options: SandboxEnvOptions): ExecutionEnv;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Readable, Writable } from \"node:stream\";\nimport type { ExecutionEnv } from \"@earendil-works/pi-durable/env\";\nimport type { OfficeAddress } from \"../types.js\";\n\nexport type SandboxConfig = HostSandboxConfig | ContainerSandboxConfig | OciSandboxConfig;\n\nexport interface HostSandboxConfig {\n type: \"host\";\n}\n\nexport interface ContainerSandboxConfig {\n type: \"container\";\n container: string;\n}\n\nexport interface OciSandboxConfig {\n type: \"oci\";\n image: string;\n}\n\nexport interface SandboxEnvOptions {\n cwd: string;\n env?: Record<string, string>;\n ensureReady?: () => Promise<void>;\n markUsed?: () => void;\n}\n\nexport interface ContainerExecutionEnvOptions extends SandboxEnvOptions {\n container: string;\n engine?: string;\n}\n\nexport interface RuntimePathContext {\n hostWorkspaceRoot: string;\n runtimeWorkspaceRoot: string;\n runtimeToHostPath?: (runtimePath: string) => string;\n}\n\nexport type DockerExecFile = (file: string, args: string[]) => Promise<{ stdout: string }>;\n\nexport interface SandboxCredentialCapabilities {\n env: boolean;\n fileMounts: boolean;\n}\n\nexport interface CredentialScope {\n userId: string;\n address: OfficeAddress;\n}\n\ninterface SandboxWorkspaceCapabilities {\n managedProjection: boolean;\n}\n\nexport interface SandboxAdapter<TConfig extends SandboxConfig = SandboxConfig> {\n type: TConfig[\"type\"];\n credentials: SandboxCredentialCapabilities;\n workspace: SandboxWorkspaceCapabilities;\n parse(value: string): TConfig | undefined;\n validate?(config: TConfig): Promise<void>;\n createEnv?(config: TConfig, options: SandboxEnvOptions): ExecutionEnv;\n}\n\nexport type BrowserOwner = \"agent\" | \"user\";\n\nexport interface DesktopStatus {\n display?: string;\n control: BrowserOwner;\n}\n\nexport type DesktopStart = \"ready\" | \"outdated-image\" | \"stopped\";\n\nexport interface DesktopProcess {\n stdin: Writable | null;\n stdout: Readable | null;\n kill(): unknown;\n once(event: \"exit\" | \"error\", listener: () => void): unknown;\n}\n\nexport interface DesktopStream {\n input: Writable;\n output: Readable;\n process: Pick<DesktopProcess, \"once\">;\n close(): void;\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -5,7 +5,7 @@ import type { McpServerConfig } from "./harness/types.js";
5
5
  import type { EventScheduleSink } from "./events/index.js";
6
6
  import type { Office } from "./office/types.js";
7
7
  import type { DockerContainerManager } from "./sandbox/provisioner.js";
8
- import type { DockerExecFile, SandboxConfig } from "./sandbox/types.js";
8
+ import type { DesktopStart, DockerExecFile, SandboxConfig } from "./sandbox/types.js";
9
9
  import type { ChatHistorySync } from "./sessions/chat-history-sync.js";
10
10
  import type { ResolvedSessionScope } from "./sessions/types.js";
11
11
  import type { PlatformToolPackFactory } from "./harness/tools/types.js";
@@ -383,6 +383,11 @@ export interface CreateRunnerOptions {
383
383
  tokenStore: SessionViewTokenStoreLike;
384
384
  portalBaseUrl?: string;
385
385
  };
386
+ desktop?: {
387
+ tokenStore: DesktopTokenStoreLike;
388
+ portalBaseUrl?: string;
389
+ open: OpenDesktop;
390
+ };
386
391
  platformToolPackFactories?: readonly PlatformToolPackFactory[];
387
392
  models: MikanModels;
388
393
  runEvents?: RunEventPublisher;
@@ -400,5 +405,16 @@ export interface SessionViewTokenStoreLike {
400
405
  token: string;
401
406
  };
402
407
  }
408
+ export interface DesktopTokenCreateOptions {
409
+ platform: PlatformName;
410
+ platformUserId: string;
411
+ office: Office;
412
+ }
413
+ export type OpenDesktop = (actor: ActorContext) => Promise<DesktopStart>;
414
+ export interface DesktopTokenStoreLike {
415
+ create(options: DesktopTokenCreateOptions): {
416
+ token: string;
417
+ };
418
+ }
403
419
  export {};
404
420
  //# sourceMappingURL=types.d.ts.map