@acpus/runtime 0.1.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.
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/artifacts.d.ts +30 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +97 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/client.d.ts +54 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +159 -0
- package/dist/client.js.map +1 -0
- package/dist/evaluator.d.ts +37 -0
- package/dist/evaluator.d.ts.map +1 -0
- package/dist/evaluator.js +101 -0
- package/dist/evaluator.js.map +1 -0
- package/dist/executors/agent.d.ts +74 -0
- package/dist/executors/agent.d.ts.map +1 -0
- package/dist/executors/agent.js +401 -0
- package/dist/executors/agent.js.map +1 -0
- package/dist/executors/mock-program.d.ts +24 -0
- package/dist/executors/mock-program.d.ts.map +1 -0
- package/dist/executors/mock-program.js +79 -0
- package/dist/executors/mock-program.js.map +1 -0
- package/dist/executors/program.d.ts +21 -0
- package/dist/executors/program.d.ts.map +1 -0
- package/dist/executors/program.js +178 -0
- package/dist/executors/program.js.map +1 -0
- package/dist/executors/types.d.ts +26 -0
- package/dist/executors/types.d.ts.map +1 -0
- package/dist/executors/types.js +2 -0
- package/dist/executors/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter.d.ts +186 -0
- package/dist/interpreter.d.ts.map +1 -0
- package/dist/interpreter.js +1500 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/keys.d.ts +36 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +59 -0
- package/dist/keys.js.map +1 -0
- package/dist/state-machine.d.ts +27 -0
- package/dist/state-machine.d.ts.map +1 -0
- package/dist/state-machine.js +87 -0
- package/dist/state-machine.js.map +1 -0
- package/dist/store.d.ts +46 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +260 -0
- package/dist/store.js.map +1 -0
- package/dist/supervisor-app.d.ts +27 -0
- package/dist/supervisor-app.d.ts.map +1 -0
- package/dist/supervisor-app.js +548 -0
- package/dist/supervisor-app.js.map +1 -0
- package/dist/supervisor-discovery.d.ts +17 -0
- package/dist/supervisor-discovery.d.ts.map +1 -0
- package/dist/supervisor-discovery.js +186 -0
- package/dist/supervisor-discovery.js.map +1 -0
- package/dist/supervisor-entry.d.ts +11 -0
- package/dist/supervisor-entry.d.ts.map +1 -0
- package/dist/supervisor-entry.js +50 -0
- package/dist/supervisor-entry.js.map +1 -0
- package/dist/supervisor-lock.d.ts +26 -0
- package/dist/supervisor-lock.d.ts.map +1 -0
- package/dist/supervisor-lock.js +49 -0
- package/dist/supervisor-lock.js.map +1 -0
- package/dist/supervisor-runner.d.ts +11 -0
- package/dist/supervisor-runner.d.ts.map +1 -0
- package/dist/supervisor-runner.js +128 -0
- package/dist/supervisor-runner.js.map +1 -0
- package/dist/types.d.ts +230 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validate-input.d.ts +27 -0
- package/dist/validate-input.d.ts.map +1 -0
- package/dist/validate-input.js +56 -0
- package/dist/validate-input.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor discovery and lazy ensure.
|
|
3
|
+
*
|
|
4
|
+
* `ensureWorkspaceSupervisor()` is the single entry point for CLI commands
|
|
5
|
+
* that need a running supervisor. It reads metadata, health-checks an existing
|
|
6
|
+
* supervisor, and spawns a new one if none is alive — with a lock to
|
|
7
|
+
* serialize concurrent ensure calls.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, rmSync, existsSync, openSync, closeSync } from "node:fs";
|
|
10
|
+
import { join, resolve } from "node:path";
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { acquireSupervisorLock } from "./supervisor-lock.js";
|
|
14
|
+
const SUPERVISOR_METADATA_FILE = "supervisor.json";
|
|
15
|
+
/**
|
|
16
|
+
* Ensure a Run Supervisor is running for the given workspace.
|
|
17
|
+
* Returns its metadata on success, throws on failure.
|
|
18
|
+
*/
|
|
19
|
+
export async function ensureWorkspaceSupervisor(workspace, options) {
|
|
20
|
+
const absWorkspace = resolve(workspace);
|
|
21
|
+
const stateDir = join(absWorkspace, ".acpus", "state");
|
|
22
|
+
const metadataPath = join(stateDir, SUPERVISOR_METADATA_FILE);
|
|
23
|
+
// 1. Try existing metadata
|
|
24
|
+
const existing = tryReadMetadata(metadataPath);
|
|
25
|
+
if (existing) {
|
|
26
|
+
const validated = await validateExistingSupervisor(existing, absWorkspace);
|
|
27
|
+
if (validated)
|
|
28
|
+
return validated;
|
|
29
|
+
// Stale — clean up
|
|
30
|
+
try {
|
|
31
|
+
rmSync(metadataPath);
|
|
32
|
+
}
|
|
33
|
+
catch { /* ignore */ }
|
|
34
|
+
}
|
|
35
|
+
// 2. Acquire lock
|
|
36
|
+
const release = await acquireSupervisorLock(stateDir);
|
|
37
|
+
// 3. Re-check metadata (another process may have started supervisor while we waited)
|
|
38
|
+
try {
|
|
39
|
+
const afterLock = tryReadMetadata(metadataPath);
|
|
40
|
+
if (afterLock) {
|
|
41
|
+
const validated = await validateExistingSupervisor(afterLock, absWorkspace);
|
|
42
|
+
if (validated) {
|
|
43
|
+
await release();
|
|
44
|
+
return validated;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
rmSync(metadataPath);
|
|
48
|
+
}
|
|
49
|
+
catch { /* ignore */ }
|
|
50
|
+
}
|
|
51
|
+
// 4. Spawn supervisor
|
|
52
|
+
const metadata = await spawnSupervisor(absWorkspace, stateDir, options?.idleTimeoutMs);
|
|
53
|
+
return metadata;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
await release();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function tryReadMetadata(path) {
|
|
60
|
+
if (!existsSync(path))
|
|
61
|
+
return undefined;
|
|
62
|
+
try {
|
|
63
|
+
const raw = readFileSync(path, "utf8");
|
|
64
|
+
return JSON.parse(raw);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function validateExistingSupervisor(meta, expectedWorkspace) {
|
|
71
|
+
// Validate schema version
|
|
72
|
+
if (meta.schemaVersion !== 1)
|
|
73
|
+
return undefined;
|
|
74
|
+
// Validate workspace matches
|
|
75
|
+
if (resolve(meta.workspace) !== resolve(expectedWorkspace))
|
|
76
|
+
return undefined;
|
|
77
|
+
// Validate endpoint is localhost
|
|
78
|
+
if (!meta.endpoint.startsWith("http://127.0.0.1:"))
|
|
79
|
+
return undefined;
|
|
80
|
+
// Health check
|
|
81
|
+
try {
|
|
82
|
+
const res = await fetch(`${meta.endpoint}/health`);
|
|
83
|
+
if (!res.ok)
|
|
84
|
+
return undefined;
|
|
85
|
+
const health = await res.json();
|
|
86
|
+
if (!health.ok)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (health.pid !== meta.pid)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (health.endpoint !== meta.endpoint)
|
|
91
|
+
return undefined;
|
|
92
|
+
return meta;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function spawnSupervisor(workspace, stateDir, idleTimeoutMs) {
|
|
99
|
+
const metadataPath = join(stateDir, SUPERVISOR_METADATA_FILE);
|
|
100
|
+
// Resolve entry script path and command
|
|
101
|
+
const entry = resolveEntryPath();
|
|
102
|
+
const args = [...entry.args, "--state-dir", stateDir, "--workspace", workspace];
|
|
103
|
+
if (idleTimeoutMs !== undefined) {
|
|
104
|
+
args.push("--idle-timeout", String(idleTimeoutMs));
|
|
105
|
+
}
|
|
106
|
+
// Redirect stdout/stderr to supervisor.log
|
|
107
|
+
const logPath = join(stateDir, "supervisor.log");
|
|
108
|
+
let logFd;
|
|
109
|
+
try {
|
|
110
|
+
logFd = openSync(logPath, "a");
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// If we can't open the log, use 'ignore'
|
|
114
|
+
}
|
|
115
|
+
// Build a filtered environment: pass through everything except known
|
|
116
|
+
// sensitive keys that the supervisor child has no business inheriting.
|
|
117
|
+
const SENSITIVE_PREFIXES = [
|
|
118
|
+
"AWS_", "GCP_", "GOOGLE_", "AZURE_", "VAULT_", "KUBERNETES_",
|
|
119
|
+
"DOCKER_", "SSH_", "GPG_", "PGPASS"
|
|
120
|
+
];
|
|
121
|
+
const filteredEnv = {};
|
|
122
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
123
|
+
if (value === undefined)
|
|
124
|
+
continue;
|
|
125
|
+
if (SENSITIVE_PREFIXES.some((p) => key.startsWith(p)))
|
|
126
|
+
continue;
|
|
127
|
+
filteredEnv[key] = value;
|
|
128
|
+
}
|
|
129
|
+
const child = spawn(entry.cmd, args, {
|
|
130
|
+
detached: true,
|
|
131
|
+
stdio: ["ignore", logFd ?? "ignore", logFd ?? "ignore"],
|
|
132
|
+
env: filteredEnv
|
|
133
|
+
});
|
|
134
|
+
child.unref();
|
|
135
|
+
// Close our copy of the log fd (child inherited it)
|
|
136
|
+
if (logFd !== undefined) {
|
|
137
|
+
try {
|
|
138
|
+
closeSync(logFd);
|
|
139
|
+
}
|
|
140
|
+
catch { /* ignore */ }
|
|
141
|
+
}
|
|
142
|
+
// Wait for supervisor.json to appear (poll every 100ms up to 15s)
|
|
143
|
+
const maxWaitMs = 15_000;
|
|
144
|
+
const start = Date.now();
|
|
145
|
+
try {
|
|
146
|
+
while (Date.now() - start < maxWaitMs) {
|
|
147
|
+
const meta = tryReadMetadata(metadataPath);
|
|
148
|
+
if (meta) {
|
|
149
|
+
// Health check the endpoint
|
|
150
|
+
try {
|
|
151
|
+
const res = await fetch(`${meta.endpoint}/health`);
|
|
152
|
+
if (res.ok)
|
|
153
|
+
return meta;
|
|
154
|
+
}
|
|
155
|
+
catch { /* ignore */ }
|
|
156
|
+
}
|
|
157
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
158
|
+
}
|
|
159
|
+
throw new Error(`Supervisor failed to start within ${maxWaitMs / 1000}s`);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
// Kill the orphaned child process if we timed out or failed
|
|
163
|
+
try {
|
|
164
|
+
child.kill("SIGKILL");
|
|
165
|
+
}
|
|
166
|
+
catch { /* ignore */ }
|
|
167
|
+
throw err;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Resolve the entry script path and command for spawning the supervisor.
|
|
172
|
+
* If running via tsx, use tsx to run the TypeScript source.
|
|
173
|
+
* If running as built JS, use node to run the compiled JS.
|
|
174
|
+
*/
|
|
175
|
+
function resolveEntryPath() {
|
|
176
|
+
const runtimeDir = fileURLToPath(new URL(".", import.meta.url));
|
|
177
|
+
const tsEntry = join(runtimeDir, "supervisor-entry.ts");
|
|
178
|
+
// If the TS source exists, we're in development mode (running from source via tsx)
|
|
179
|
+
if (existsSync(tsEntry)) {
|
|
180
|
+
return { cmd: "npx", args: ["tsx", tsEntry] };
|
|
181
|
+
}
|
|
182
|
+
// Production: use the compiled JS
|
|
183
|
+
const jsEntry = join(runtimeDir, "supervisor-entry.js");
|
|
184
|
+
return { cmd: "node", args: [jsEntry] };
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=supervisor-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-discovery.js","sourceRoot":"","sources":["../src/supervisor-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor entry point — minimal CLI for spawning as a child process.
|
|
3
|
+
*
|
|
4
|
+
* This is the target of `ensureWorkspaceSupervisor()`. It accepts only
|
|
5
|
+
* --state-dir (required), --workspace (required), and --idle-timeout (optional), then starts
|
|
6
|
+
* the Run Supervisor and blocks until shutdown.
|
|
7
|
+
*
|
|
8
|
+
* No Commander, no argument parsing beyond these two flags.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=supervisor-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-entry.d.ts","sourceRoot":"","sources":["../src/supervisor-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor entry point — minimal CLI for spawning as a child process.
|
|
3
|
+
*
|
|
4
|
+
* This is the target of `ensureWorkspaceSupervisor()`. It accepts only
|
|
5
|
+
* --state-dir (required), --workspace (required), and --idle-timeout (optional), then starts
|
|
6
|
+
* the Run Supervisor and blocks until shutdown.
|
|
7
|
+
*
|
|
8
|
+
* No Commander, no argument parsing beyond these two flags.
|
|
9
|
+
*/
|
|
10
|
+
import { resolve, join } from "node:path";
|
|
11
|
+
import { openSync } from "node:fs";
|
|
12
|
+
import { startRunSupervisor } from "./supervisor-runner.js";
|
|
13
|
+
function parseArgs(args) {
|
|
14
|
+
let stateDir;
|
|
15
|
+
let workspace;
|
|
16
|
+
let idleTimeoutMs;
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
if (args[i] === "--state-dir" && args[i + 1]) {
|
|
19
|
+
stateDir = args[++i];
|
|
20
|
+
}
|
|
21
|
+
else if (args[i] === "--workspace" && args[i + 1]) {
|
|
22
|
+
workspace = args[++i];
|
|
23
|
+
}
|
|
24
|
+
else if (args[i] === "--idle-timeout" && args[i + 1]) {
|
|
25
|
+
idleTimeoutMs = parseInt(args[++i], 10);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (!stateDir) {
|
|
29
|
+
console.error("--state-dir is required");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
if (!workspace) {
|
|
33
|
+
console.error("--workspace is required");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
return { stateDir: resolve(stateDir), workspace: resolve(workspace), idleTimeoutMs };
|
|
37
|
+
}
|
|
38
|
+
// Redirect stdout/stderr to supervisor.log
|
|
39
|
+
const logPath = join(resolve(parseArgs(process.argv.slice(2)).stateDir), "supervisor.log");
|
|
40
|
+
const logFd = openSync(logPath, "a");
|
|
41
|
+
const { stateDir, workspace, idleTimeoutMs } = parseArgs(process.argv.slice(2));
|
|
42
|
+
startRunSupervisor({
|
|
43
|
+
stateDir,
|
|
44
|
+
workspace,
|
|
45
|
+
idleTimeoutMs
|
|
46
|
+
}).catch((err) => {
|
|
47
|
+
console.error("Supervisor failed to start:", err);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=supervisor-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-entry.js","sourceRoot":"","sources":["../src/supervisor-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,SAAS,SAAS,CAAC,IAAc;IAC/B,IAAI,QAA4B,CAAC;IACjC,IAAI,SAA6B,CAAC;IAClC,IAAI,aAAiC,CAAC;IAEtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7C,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACpD,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,gBAAgB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvD,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;AACvF,CAAC;AAED,2CAA2C;AAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAC3F,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAErC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,kBAAkB,CAAC;IACjB,QAAQ;IACR,SAAS;IACT,aAAa;CACd,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor lock management using proper-lockfile.
|
|
3
|
+
*
|
|
4
|
+
* Provides a single entry point `acquireSupervisorLock()` that wraps
|
|
5
|
+
* `proper-lockfile.lock()` with the correct configuration for
|
|
6
|
+
* serializing concurrent `ensureWorkspaceSupervisor()` calls.
|
|
7
|
+
*
|
|
8
|
+
* The lock targets the Workspace state directory and creates a
|
|
9
|
+
* `supervisor.lock` directory as the lock marker.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Acquire the supervisor lock for the given state directory.
|
|
13
|
+
*
|
|
14
|
+
* Returns a release callback that must be called when the lock is
|
|
15
|
+
* no longer needed (typically after the supervisor has been spawned
|
|
16
|
+
* and its metadata is confirmed).
|
|
17
|
+
*
|
|
18
|
+
* Configuration:
|
|
19
|
+
* - `stale: 20_000` — locks older than 20s are considered stale
|
|
20
|
+
* (max spawn time is ~15s, giving 5s margin)
|
|
21
|
+
* - `update: 2_000` — mtime updated every 2s while lock is held
|
|
22
|
+
* - `retries: 30 × 500ms` — total wait up to 15s for competing processes
|
|
23
|
+
* - `onCompromised: 'warn'` — log but don't throw if lock is tampered
|
|
24
|
+
*/
|
|
25
|
+
export declare function acquireSupervisorLock(stateDir: string): Promise<() => Promise<void>>;
|
|
26
|
+
//# sourceMappingURL=supervisor-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-lock.d.ts","sourceRoot":"","sources":["../src/supervisor-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAsB9B"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervisor lock management using proper-lockfile.
|
|
3
|
+
*
|
|
4
|
+
* Provides a single entry point `acquireSupervisorLock()` that wraps
|
|
5
|
+
* `proper-lockfile.lock()` with the correct configuration for
|
|
6
|
+
* serializing concurrent `ensureWorkspaceSupervisor()` calls.
|
|
7
|
+
*
|
|
8
|
+
* The lock targets the Workspace state directory and creates a
|
|
9
|
+
* `supervisor.lock` directory as the lock marker.
|
|
10
|
+
*/
|
|
11
|
+
import lockfile from "proper-lockfile";
|
|
12
|
+
import { mkdirSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
const LOCK_NAME = "supervisor.lock";
|
|
15
|
+
/**
|
|
16
|
+
* Acquire the supervisor lock for the given state directory.
|
|
17
|
+
*
|
|
18
|
+
* Returns a release callback that must be called when the lock is
|
|
19
|
+
* no longer needed (typically after the supervisor has been spawned
|
|
20
|
+
* and its metadata is confirmed).
|
|
21
|
+
*
|
|
22
|
+
* Configuration:
|
|
23
|
+
* - `stale: 20_000` — locks older than 20s are considered stale
|
|
24
|
+
* (max spawn time is ~15s, giving 5s margin)
|
|
25
|
+
* - `update: 2_000` — mtime updated every 2s while lock is held
|
|
26
|
+
* - `retries: 30 × 500ms` — total wait up to 15s for competing processes
|
|
27
|
+
* - `onCompromised: 'warn'` — log but don't throw if lock is tampered
|
|
28
|
+
*/
|
|
29
|
+
export async function acquireSupervisorLock(stateDir) {
|
|
30
|
+
// Ensure state directory exists
|
|
31
|
+
mkdirSync(stateDir, { recursive: true });
|
|
32
|
+
const lockPath = join(stateDir, LOCK_NAME);
|
|
33
|
+
const release = await lockfile.lock(stateDir, {
|
|
34
|
+
stale: 20_000,
|
|
35
|
+
update: 2_000,
|
|
36
|
+
retries: {
|
|
37
|
+
retries: 30,
|
|
38
|
+
minTimeout: 500,
|
|
39
|
+
maxTimeout: 500,
|
|
40
|
+
},
|
|
41
|
+
// lockfilePath must be an absolute path pointing inside the locked directory
|
|
42
|
+
lockfilePath: lockPath,
|
|
43
|
+
onCompromised: (err) => {
|
|
44
|
+
console.warn(`Supervisor lock compromised: ${err.message}`);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
return release;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=supervisor-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-lock.js","sourceRoot":"","sources":["../src/supervisor-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB;IAEhB,gCAAgC;IAChC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC5C,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB;QACD,6EAA6E;QAC7E,YAAY,EAAE,QAAQ;QACtB,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE;YACrB,OAAO,CAAC,IAAI,CAAC,gCAAgC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SupervisorConfig, SupervisorMetadata } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Start the acpus Run Supervisor process.
|
|
4
|
+
*
|
|
5
|
+
* Binds to a random port (127.0.0.1:0), writes supervisor.json for discovery,
|
|
6
|
+
* handles graceful shutdown, startup recovery, and idle timeout.
|
|
7
|
+
*
|
|
8
|
+
* Returns the bound metadata so the caller (supervisor-entry) can signal readiness.
|
|
9
|
+
*/
|
|
10
|
+
export declare function startRunSupervisor(config?: SupervisorConfig): Promise<SupervisorMetadata>;
|
|
11
|
+
//# sourceMappingURL=supervisor-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-runner.d.ts","sourceRoot":"","sources":["../src/supervisor-runner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKvE;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,gBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8HnG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { createSupervisorApp } from "./supervisor-app.js";
|
|
2
|
+
import { RunStore } from "./store.js";
|
|
3
|
+
import { AgentExecutor } from "./executors/agent.js";
|
|
4
|
+
import { ProgramExecutor } from "./executors/program.js";
|
|
5
|
+
import { writeFileSync, mkdirSync, rmSync, existsSync } from "node:fs";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { serve } from "@hono/node-server";
|
|
8
|
+
/**
|
|
9
|
+
* Start the acpus Run Supervisor process.
|
|
10
|
+
*
|
|
11
|
+
* Binds to a random port (127.0.0.1:0), writes supervisor.json for discovery,
|
|
12
|
+
* handles graceful shutdown, startup recovery, and idle timeout.
|
|
13
|
+
*
|
|
14
|
+
* Returns the bound metadata so the caller (supervisor-entry) can signal readiness.
|
|
15
|
+
*/
|
|
16
|
+
export async function startRunSupervisor(config = {}) {
|
|
17
|
+
const host = config.host ?? "127.0.0.1";
|
|
18
|
+
const port = config.port ?? 0; // 0 = random port
|
|
19
|
+
const workspace = resolve(config.workspace ?? process.cwd());
|
|
20
|
+
const stateDir = config.stateDir ?? join(workspace, ".acpus", "state");
|
|
21
|
+
config = { ...config, stateDir, workspace }; // Write computed paths back for createSupervisorApp.
|
|
22
|
+
const idleTimeoutMs = config.idleTimeoutMs ?? 5 * 60 * 1000; // 5 min default
|
|
23
|
+
const metadataFile = join(stateDir, "supervisor.json");
|
|
24
|
+
// Ensure state directory exists
|
|
25
|
+
mkdirSync(stateDir, { recursive: true });
|
|
26
|
+
const store = new RunStore(join(stateDir, "runs"));
|
|
27
|
+
const agentExecutor = new AgentExecutor();
|
|
28
|
+
const programExecutor = new ProgramExecutor();
|
|
29
|
+
// Startup recovery: reset orphaned running nodes to pending, set Run to paused.
|
|
30
|
+
// Only Runs with status "running" are recovered (crash, no graceful shutdown).
|
|
31
|
+
// After a graceful shutdown, paused nodes remain paused and the Run stays paused.
|
|
32
|
+
// The operator uses `acpus runs resume <runId>` to continue.
|
|
33
|
+
for (const runId of store.listRunIds()) {
|
|
34
|
+
const meta = store.readRunMeta(runId);
|
|
35
|
+
if (meta?.status === "running") {
|
|
36
|
+
let anyReset = false;
|
|
37
|
+
for (const nodeState of store.listNodeStates(runId)) {
|
|
38
|
+
// A node persisted as `running` or `awaiting` has no live execution or
|
|
39
|
+
// approval resolver after a crash, so reset it to `pending` so the
|
|
40
|
+
// resumed Run re-executes it (an awaiting Approval Gate re-awaits).
|
|
41
|
+
if (nodeState.state === "running" || nodeState.state === "awaiting") {
|
|
42
|
+
nodeState.state = "pending";
|
|
43
|
+
store.writeNodeState(runId, nodeState);
|
|
44
|
+
anyReset = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (anyReset) {
|
|
48
|
+
meta.status = "paused";
|
|
49
|
+
meta.updatedAt = new Date().toISOString();
|
|
50
|
+
store.writeRunMeta(runId, meta);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const { app, getLastActiveAt, runningCount, setHealthOverrides } = createSupervisorApp(config, store, agentExecutor, programExecutor);
|
|
55
|
+
// Start the HTTP server on random port
|
|
56
|
+
let httpServer;
|
|
57
|
+
const startedAt = new Date().toISOString();
|
|
58
|
+
let boundPort = 0;
|
|
59
|
+
await new Promise((resolve) => {
|
|
60
|
+
httpServer = serve({ fetch: app.fetch, port, hostname: host }, (info) => {
|
|
61
|
+
boundPort = info.port;
|
|
62
|
+
console.log(`acpus supervisor listening on ${info.address}:${info.port}`);
|
|
63
|
+
resolve();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
const endpoint = `http://127.0.0.1:${boundPort}`;
|
|
67
|
+
// Write supervisor metadata for discovery
|
|
68
|
+
const metadata = {
|
|
69
|
+
schemaVersion: 1,
|
|
70
|
+
workspace,
|
|
71
|
+
pid: process.pid,
|
|
72
|
+
endpoint,
|
|
73
|
+
startedAt,
|
|
74
|
+
version: "0.1.0"
|
|
75
|
+
};
|
|
76
|
+
writeFileSync(metadataFile, JSON.stringify(metadata, null, 2), "utf8");
|
|
77
|
+
// Push health overrides so GET /health reports the correct endpoint/startedAt
|
|
78
|
+
setHealthOverrides({ startedAt, endpoint });
|
|
79
|
+
// ─── Idle shutdown ───────────────────────────────────────────────
|
|
80
|
+
const idleCheckInterval = setInterval(() => {
|
|
81
|
+
if (Date.now() - getLastActiveAt() > idleTimeoutMs && runningCount() === 0) {
|
|
82
|
+
console.log("Supervisor idle timeout — shutting down.");
|
|
83
|
+
shutdown();
|
|
84
|
+
}
|
|
85
|
+
}, 30_000);
|
|
86
|
+
// ─── Graceful shutdown ───────────────────────────────────────────
|
|
87
|
+
let shuttingDown = false;
|
|
88
|
+
function shutdown() {
|
|
89
|
+
if (shuttingDown)
|
|
90
|
+
return;
|
|
91
|
+
shuttingDown = true;
|
|
92
|
+
console.log("Shutting down supervisor...");
|
|
93
|
+
clearInterval(idleCheckInterval);
|
|
94
|
+
// Save all running nodes as paused, set Run metadata to paused
|
|
95
|
+
for (const runId of store.listRunIds()) {
|
|
96
|
+
const meta = store.readRunMeta(runId);
|
|
97
|
+
if (meta?.status === "running") {
|
|
98
|
+
for (const nodeState of store.listNodeStates(runId)) {
|
|
99
|
+
if (nodeState.state === "running") {
|
|
100
|
+
nodeState.state = "paused";
|
|
101
|
+
store.writeNodeState(runId, nodeState);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
meta.status = "paused";
|
|
105
|
+
meta.updatedAt = new Date().toISOString();
|
|
106
|
+
store.writeRunMeta(runId, meta);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Remove metadata file
|
|
110
|
+
try {
|
|
111
|
+
if (existsSync(metadataFile))
|
|
112
|
+
rmSync(metadataFile);
|
|
113
|
+
}
|
|
114
|
+
catch { /* ignore */ }
|
|
115
|
+
// Close the HTTP server gracefully, then exit
|
|
116
|
+
if (httpServer) {
|
|
117
|
+
httpServer.close(() => process.exit(0));
|
|
118
|
+
setTimeout(() => process.exit(0), 5000);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
process.on("SIGINT", shutdown);
|
|
125
|
+
process.on("SIGTERM", shutdown);
|
|
126
|
+
return metadata;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=supervisor-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-runner.js","sourceRoot":"","sources":["../src/supervisor-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,SAA2B,EAAE;IACpE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,kBAAkB;IACjD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,qDAAqD;IAClG,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,gBAAgB;IAC7E,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAEvD,gCAAgC;IAChC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;IAC1C,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAE9C,gFAAgF;IAChF,+EAA+E;IAC/E,kFAAkF;IAClF,6DAA6D;IAC7D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,IAAI,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpD,uEAAuE;gBACvE,mEAAmE;gBACnE,oEAAoE;gBACpE,IAAI,SAAS,CAAC,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;oBACpE,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC;oBAC5B,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACvC,QAAQ,GAAG,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACvB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC1C,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,mBAAmB,CACpF,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,eAAe,CAC9C,CAAC;IAEF,uCAAuC;IACvC,IAAI,UAAgD,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,UAAU,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;YACtE,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1E,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,oBAAoB,SAAS,EAAE,CAAC;IAEjD,0CAA0C;IAC1C,MAAM,QAAQ,GAAuB;QACnC,aAAa,EAAE,CAAC;QAChB,SAAS;QACT,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ;QACR,SAAS;QACT,OAAO,EAAE,OAAO;KACjB,CAAC;IACF,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEvE,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE5C,oEAAoE;IAEpE,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;QACzC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,aAAa,IAAI,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;YACxD,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,oEAAoE;IAEpE,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,SAAS,QAAQ;QACf,IAAI,YAAY;YAAE,OAAO;QACzB,YAAY,GAAG,IAAI,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAE3C,aAAa,CAAC,iBAAiB,CAAC,CAAC;QAEjC,+DAA+D;QAC/D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,IAAI,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;oBACpD,IAAI,SAAS,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;wBAClC,SAAS,CAAC,KAAK,GAAG,QAAQ,CAAC;wBAC3B,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;oBACzC,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACvB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC1C,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC;YAAC,IAAI,UAAU,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAElF,8CAA8C;QAC9C,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|