@synap-core/cli 1.12.2 → 1.13.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 +25 -8
- package/dist/build-info.json +2 -2
- package/dist/commands/agents.d.ts +0 -1
- package/dist/commands/agents.js +1 -1
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.js +2 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/automation.js +46 -41
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/box.d.ts +42 -0
- package/dist/commands/box.js +89 -0
- package/dist/commands/box.js.map +1 -0
- package/dist/commands/bridge-setup.js +3 -1
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/capability.d.ts +1 -1
- package/dist/commands/capability.js +57 -34
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/close-questions.d.ts +27 -0
- package/dist/commands/close-questions.js +49 -0
- package/dist/commands/close-questions.js.map +1 -0
- package/dist/commands/close-questions.test.d.ts +1 -0
- package/dist/commands/close-questions.test.js +52 -0
- package/dist/commands/close-questions.test.js.map +1 -0
- package/dist/commands/connect.d.ts +1 -3
- package/dist/commands/connect.js +2 -2
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +72 -43
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.js +12 -4
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.js +2 -1
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +108 -13
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/hooks.d.ts +19 -0
- package/dist/commands/hooks.js +70 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/import.d.ts +25 -0
- package/dist/commands/import.js +98 -12
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.js +59 -19
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/knowledge.js +4 -2
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/lens.js +2 -1
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.js +1 -1
- package/dist/commands/market-authoring.js.map +1 -1
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/observe.category.test.d.ts +1 -0
- package/dist/commands/observe.category.test.js +59 -0
- package/dist/commands/observe.category.test.js.map +1 -0
- package/dist/commands/observe.d.ts +3 -0
- package/dist/commands/observe.js +7 -5
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/observe.title.test.d.ts +1 -0
- package/dist/commands/observe.title.test.js +37 -0
- package/dist/commands/observe.title.test.js.map +1 -0
- package/dist/commands/playbook.js +9 -0
- package/dist/commands/playbook.js.map +1 -1
- package/dist/commands/pods.d.ts +6 -1
- package/dist/commands/pods.js +32 -15
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proton-setup.js +3 -1
- package/dist/commands/proton-setup.js.map +1 -1
- package/dist/commands/session-feed-wait.d.ts +48 -0
- package/dist/commands/session-feed-wait.js +261 -0
- package/dist/commands/session-feed-wait.js.map +1 -0
- package/dist/commands/session-post.d.ts +40 -0
- package/dist/commands/session-post.js +96 -0
- package/dist/commands/session-post.js.map +1 -0
- package/dist/commands/session-wait.d.ts +9 -4
- package/dist/commands/session-wait.js +20 -5
- package/dist/commands/session-wait.js.map +1 -1
- package/dist/commands/sessions.d.ts +2 -0
- package/dist/commands/sessions.js +23 -0
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skills-commands.d.ts +2 -0
- package/dist/commands/skills-commands.js +9 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills-commands.test.d.ts +1 -0
- package/dist/commands/skills-commands.test.js +57 -0
- package/dist/commands/skills-commands.test.js.map +1 -0
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/template.d.ts +42 -0
- package/dist/commands/template.js +191 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/tracks.d.ts +67 -6
- package/dist/commands/tracks.js +268 -16
- package/dist/commands/tracks.js.map +1 -1
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.js +17 -0
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker-accounts.d.ts +149 -0
- package/dist/commands/worker-accounts.js +339 -0
- package/dist/commands/worker-accounts.js.map +1 -0
- package/dist/commands/worker-accounts.test.d.ts +1 -0
- package/dist/commands/worker-accounts.test.js +224 -0
- package/dist/commands/worker-accounts.test.js.map +1 -0
- package/dist/commands/worker.d.ts +219 -10
- package/dist/commands/worker.js +749 -117
- package/dist/commands/worker.js.map +1 -1
- package/dist/commands/worker.test.js +321 -10
- package/dist/commands/worker.test.js.map +1 -1
- package/dist/index.js +164 -27
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-door.d.ts +1 -3
- package/dist/lib/agent-door.js +10 -7
- package/dist/lib/agent-door.js.map +1 -1
- package/dist/lib/auth.d.ts +3 -2
- package/dist/lib/auth.js +3 -3
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/box/egress.d.ts +82 -0
- package/dist/lib/box/egress.js +264 -0
- package/dist/lib/box/egress.js.map +1 -0
- package/dist/lib/box/evidence.d.ts +86 -0
- package/dist/lib/box/evidence.js +121 -0
- package/dist/lib/box/evidence.js.map +1 -0
- package/dist/lib/box/job-server.d.ts +72 -0
- package/dist/lib/box/job-server.js +246 -0
- package/dist/lib/box/job-server.js.map +1 -0
- package/dist/lib/box/provisioner.d.ts +83 -0
- package/dist/lib/box/provisioner.js +312 -0
- package/dist/lib/box/provisioner.js.map +1 -0
- package/dist/lib/box/proxmox.d.ts +112 -0
- package/dist/lib/box/proxmox.js +211 -0
- package/dist/lib/box/proxmox.js.map +1 -0
- package/dist/lib/box/wire.d.ts +98 -0
- package/dist/lib/box/wire.js +70 -0
- package/dist/lib/box/wire.js.map +1 -0
- package/dist/lib/browser-auth.d.ts +35 -0
- package/dist/lib/browser-auth.js +170 -0
- package/dist/lib/browser-auth.js.map +1 -0
- package/dist/lib/client-header.test.d.ts +1 -0
- package/dist/lib/client-header.test.js +85 -0
- package/dist/lib/client-header.test.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +24 -9
- package/dist/lib/conversation-headers.js +40 -3
- package/dist/lib/conversation-headers.js.map +1 -1
- package/dist/lib/credential-class.d.ts +28 -1
- package/dist/lib/credential-class.js +28 -6
- package/dist/lib/credential-class.js.map +1 -1
- package/dist/lib/exporter-coverage.d.ts +1 -1
- package/dist/lib/exporter-coverage.js +1 -1
- package/dist/lib/goal-words.d.ts +38 -0
- package/dist/lib/goal-words.js +112 -0
- package/dist/lib/goal-words.js.map +1 -0
- package/dist/lib/hub-client.d.ts +28 -7
- package/dist/lib/hub-client.js +75 -34
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/init-handoff.d.ts +8 -0
- package/dist/lib/init-handoff.js +9 -2
- package/dist/lib/init-handoff.js.map +1 -1
- package/dist/lib/key-source.d.ts +3 -1
- package/dist/lib/key-source.js +7 -4
- package/dist/lib/key-source.js.map +1 -1
- package/dist/lib/knowledge-title.d.ts +3 -2
- package/dist/lib/knowledge-title.js +3 -2
- package/dist/lib/knowledge-title.js.map +1 -1
- package/dist/lib/mcp-bridge.d.ts +7 -0
- package/dist/lib/mcp-bridge.js +34 -1
- package/dist/lib/mcp-bridge.js.map +1 -1
- package/dist/lib/mcp-bridge.test.js +31 -3
- package/dist/lib/mcp-bridge.test.js.map +1 -1
- package/dist/lib/openclaw.d.ts +32 -0
- package/dist/lib/openclaw.js +165 -0
- package/dist/lib/openclaw.js.map +1 -0
- package/dist/lib/pod-moved.d.ts +70 -0
- package/dist/lib/pod-moved.js +146 -0
- package/dist/lib/pod-moved.js.map +1 -0
- package/dist/lib/pod-reach.d.ts +39 -0
- package/dist/lib/pod-reach.js +117 -0
- package/dist/lib/pod-reach.js.map +1 -0
- package/dist/lib/pod-reach.test.d.ts +1 -0
- package/dist/lib/pod-reach.test.js +67 -0
- package/dist/lib/pod-reach.test.js.map +1 -0
- package/dist/lib/pod.d.ts +8 -0
- package/dist/lib/pod.js +12 -3
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
- package/dist/lib/register-claude-code-mcp.test.js +78 -0
- package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
- package/dist/lib/review-credential.js +3 -1
- package/dist/lib/review-credential.js.map +1 -1
- package/dist/lib/seed.d.ts +13 -0
- package/dist/lib/seed.js +135 -0
- package/dist/lib/seed.js.map +1 -0
- package/dist/lib/session-feed.d.ts +185 -0
- package/dist/lib/session-feed.js +257 -0
- package/dist/lib/session-feed.js.map +1 -0
- package/dist/lib/targets.d.ts +21 -3
- package/dist/lib/targets.js +52 -107
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/wake-hook-settings.d.ts +57 -0
- package/dist/lib/wake-hook-settings.js +153 -0
- package/dist/lib/wake-hook-settings.js.map +1 -0
- package/dist/lib/wake-state.d.ts +65 -0
- package/dist/lib/wake-state.js +122 -0
- package/dist/lib/wake-state.js.map +1 -0
- package/package.json +5 -2
- package/skills/README.md +1 -1
- package/skills/agent-os/SKILL.md +8 -8
- package/skills/synap/SKILL.md +141 -84
- package/skills/synap/code-skills.md +70 -0
- package/skills/synap/concepts.md +28 -20
- package/skills/synap/creative-loop.md +1 -1
- package/skills/synap/document-embeds.md +3 -1
- package/skills/synap/focus-sessions.md +16 -7
- package/skills/synap/from-intent.md +32 -16
- package/skills/synap/governance-rules.md +1 -1
- package/skills/synap/lenses.md +4 -4
- package/skills/synap/linking.md +2 -2
- package/skills/synap/mental-model.md +1 -1
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/quick-reference.md +2 -1
- package/skills/synap/reflexes.md +6 -6
- package/skills/synap/viewframe-cells.md +1 -1
- package/skills/synap/work-model.md +24 -10
- package/skills/synap/workspace-design.md +5 -5
- package/skills/synap/writes.md +16 -9
- package/skills/synap-app/SKILL.md +148 -66
- package/skills/synap-app/creating-the-base-app.md +12 -7
- package/skills/synap-app/governance.md +27 -16
- package/skills/synap-app/install-commands.md +18 -9
- package/skills/synap-app/overview.md +16 -9
- package/skills/synap-app/using-the-sdk.md +75 -25
- package/skills/synap-schema/SKILL.md +21 -21
- package/skills/synap-schema/intent-vocabulary-ssot.md +21 -21
- package/templates/box/runner.py +206 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/lib/box/evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the box talks to: a small HTTP server on the provisioner's bridge
|
|
3
|
+
* address. The box holds no token: its identity IS its address on the isolated
|
|
4
|
+
* bridge (the provisioner assigned it), so a request is answered only for the
|
|
5
|
+
* run that address was given to.
|
|
6
|
+
*
|
|
7
|
+
* GET /job the script, its packages, parameters and wall clock
|
|
8
|
+
* POST /phase {"phase":"run"}: packages are in, egress narrows to the
|
|
9
|
+
* declared hosts (one way: never back to setup)
|
|
10
|
+
* POST /log a chunk of the run's stdout+stderr
|
|
11
|
+
* PUT /out/<path> one /out file, streamed to staging under the caps
|
|
12
|
+
* POST /done {"exitCode", "installedPackages"}
|
|
13
|
+
*/
|
|
14
|
+
import http from "node:http";
|
|
15
|
+
import type { BlockedEgress, BoxPhase, EgressPolicy } from "./egress.js";
|
|
16
|
+
import { LogCapture, type InstalledPackage } from "./evidence.js";
|
|
17
|
+
import type { LeasedRun } from "./wire.js";
|
|
18
|
+
/** BOX-CONTRACT v1: at most 20 files per run. */
|
|
19
|
+
export declare const MAX_OUT_FILES = 20;
|
|
20
|
+
export interface StagedFile {
|
|
21
|
+
path: string;
|
|
22
|
+
size: number;
|
|
23
|
+
sha256: string;
|
|
24
|
+
}
|
|
25
|
+
export interface BoxReport {
|
|
26
|
+
/** null when the runner sent no integer exit code (the runner's fault, read as INFRA). */
|
|
27
|
+
exitCode: number | null;
|
|
28
|
+
installedPackages: InstalledPackage[];
|
|
29
|
+
}
|
|
30
|
+
export interface ActiveBox {
|
|
31
|
+
run: LeasedRun;
|
|
32
|
+
phase: BoxPhase;
|
|
33
|
+
log: LogCapture;
|
|
34
|
+
blocked: BlockedEgress[];
|
|
35
|
+
outDir: string;
|
|
36
|
+
outBytes: number;
|
|
37
|
+
outFiles: StagedFile[];
|
|
38
|
+
/** The runner asked for its job (the box booted and reached the provisioner). */
|
|
39
|
+
jobFetched: boolean;
|
|
40
|
+
/** Resolves when the runner reports done. */
|
|
41
|
+
done: Promise<BoxReport>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A safe relative path for an /out file, or null. Each segment is decoded
|
|
45
|
+
* once; no empty, `.`, `..`, NUL or separator inside a segment.
|
|
46
|
+
*/
|
|
47
|
+
export declare function safeOutPath(urlPath: string): string | null;
|
|
48
|
+
/** The job document the box runner reads. */
|
|
49
|
+
export declare function jobFor(run: LeasedRun): Record<string, unknown>;
|
|
50
|
+
type Entry = ActiveBox & {
|
|
51
|
+
finish: (r: BoxReport) => void;
|
|
52
|
+
};
|
|
53
|
+
/** `job`: the box booted and asked for its job; `run`: its packages are in, the script starts. */
|
|
54
|
+
export type BoxEvent = "job" | "run";
|
|
55
|
+
export declare class BoxRegistry {
|
|
56
|
+
private readonly stagingRoot;
|
|
57
|
+
private boxes;
|
|
58
|
+
/** Called once per box and event (the provisioner sets it per run: its clocks hang on it). */
|
|
59
|
+
onEvent: (run: LeasedRun, event: BoxEvent) => void;
|
|
60
|
+
constructor(stagingRoot: string);
|
|
61
|
+
register(ip: string, run: LeasedRun): ActiveBox;
|
|
62
|
+
/** Forget the box and drop its staged files. */
|
|
63
|
+
unregister(ip: string): void;
|
|
64
|
+
get(ip: string): Entry | undefined;
|
|
65
|
+
policyFor(ip: string): EgressPolicy | null;
|
|
66
|
+
recordBlock(ip: string, block: BlockedEgress): void;
|
|
67
|
+
markJobFetched(ip: string): void;
|
|
68
|
+
enterRunPhase(ip: string): void;
|
|
69
|
+
}
|
|
70
|
+
export declare function parseReport(raw: unknown): BoxReport;
|
|
71
|
+
export declare function createJobServer(registry: BoxRegistry): http.Server;
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the box talks to: a small HTTP server on the provisioner's bridge
|
|
3
|
+
* address. The box holds no token: its identity IS its address on the isolated
|
|
4
|
+
* bridge (the provisioner assigned it), so a request is answered only for the
|
|
5
|
+
* run that address was given to.
|
|
6
|
+
*
|
|
7
|
+
* GET /job the script, its packages, parameters and wall clock
|
|
8
|
+
* POST /phase {"phase":"run"}: packages are in, egress narrows to the
|
|
9
|
+
* declared hosts (one way: never back to setup)
|
|
10
|
+
* POST /log a chunk of the run's stdout+stderr
|
|
11
|
+
* PUT /out/<path> one /out file, streamed to staging under the caps
|
|
12
|
+
* POST /done {"exitCode", "installedPackages"}
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
import fs from "node:fs";
|
|
16
|
+
import http from "node:http";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { LogCapture } from "./evidence.js";
|
|
19
|
+
/** BOX-CONTRACT v1: at most 20 files per run. */
|
|
20
|
+
export const MAX_OUT_FILES = 20;
|
|
21
|
+
const MAX_BODY_BYTES = 1024 * 1024;
|
|
22
|
+
/**
|
|
23
|
+
* A safe relative path for an /out file, or null. Each segment is decoded
|
|
24
|
+
* once; no empty, `.`, `..`, NUL or separator inside a segment.
|
|
25
|
+
*/
|
|
26
|
+
export function safeOutPath(urlPath) {
|
|
27
|
+
const raw = urlPath.replace(/^\/out\//, "");
|
|
28
|
+
// 500 = the pod's finish `files[].path` limit.
|
|
29
|
+
if (!raw || raw.length > 500)
|
|
30
|
+
return null;
|
|
31
|
+
const segments = [];
|
|
32
|
+
for (const enc of raw.split("/")) {
|
|
33
|
+
let seg;
|
|
34
|
+
try {
|
|
35
|
+
seg = decodeURIComponent(enc);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (!seg || seg === "." || seg === ".." || /[\0/\\]/.test(seg) || seg.length > 255)
|
|
41
|
+
return null;
|
|
42
|
+
segments.push(seg);
|
|
43
|
+
}
|
|
44
|
+
return segments.length <= 16 ? segments.join("/") : null;
|
|
45
|
+
}
|
|
46
|
+
/** The job document the box runner reads. */
|
|
47
|
+
export function jobFor(run) {
|
|
48
|
+
const s = run.script;
|
|
49
|
+
return {
|
|
50
|
+
runId: run.id,
|
|
51
|
+
language: s.language,
|
|
52
|
+
entrypoint: s.entrypoint,
|
|
53
|
+
code: s.code,
|
|
54
|
+
packages: s.packages,
|
|
55
|
+
parameters: run.parameters ?? null,
|
|
56
|
+
wallSeconds: s.limits.wallSeconds,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export class BoxRegistry {
|
|
60
|
+
stagingRoot;
|
|
61
|
+
boxes = new Map();
|
|
62
|
+
/** Called once per box and event (the provisioner sets it per run: its clocks hang on it). */
|
|
63
|
+
onEvent = () => { };
|
|
64
|
+
constructor(stagingRoot) {
|
|
65
|
+
this.stagingRoot = stagingRoot;
|
|
66
|
+
}
|
|
67
|
+
register(ip, run) {
|
|
68
|
+
let finish;
|
|
69
|
+
const done = new Promise((r) => (finish = r));
|
|
70
|
+
const outDir = path.join(this.stagingRoot, run.id);
|
|
71
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
72
|
+
fs.mkdirSync(outDir, { recursive: true, mode: 0o700 });
|
|
73
|
+
const box = {
|
|
74
|
+
run,
|
|
75
|
+
phase: "setup",
|
|
76
|
+
log: new LogCapture(),
|
|
77
|
+
blocked: [],
|
|
78
|
+
outDir,
|
|
79
|
+
outBytes: 0,
|
|
80
|
+
outFiles: [],
|
|
81
|
+
jobFetched: false,
|
|
82
|
+
done,
|
|
83
|
+
finish,
|
|
84
|
+
};
|
|
85
|
+
this.boxes.set(ip, box);
|
|
86
|
+
return box;
|
|
87
|
+
}
|
|
88
|
+
/** Forget the box and drop its staged files. */
|
|
89
|
+
unregister(ip) {
|
|
90
|
+
const box = this.boxes.get(ip);
|
|
91
|
+
this.boxes.delete(ip);
|
|
92
|
+
if (box)
|
|
93
|
+
fs.rmSync(box.outDir, { recursive: true, force: true });
|
|
94
|
+
}
|
|
95
|
+
get(ip) {
|
|
96
|
+
return this.boxes.get(ip);
|
|
97
|
+
}
|
|
98
|
+
policyFor(ip) {
|
|
99
|
+
const b = this.boxes.get(ip);
|
|
100
|
+
return b ? { phase: b.phase, runHosts: b.run.script.hosts } : null;
|
|
101
|
+
}
|
|
102
|
+
recordBlock(ip, block) {
|
|
103
|
+
this.boxes.get(ip)?.blocked.push(block);
|
|
104
|
+
}
|
|
105
|
+
markJobFetched(ip) {
|
|
106
|
+
const b = this.boxes.get(ip);
|
|
107
|
+
if (!b || b.jobFetched)
|
|
108
|
+
return;
|
|
109
|
+
b.jobFetched = true;
|
|
110
|
+
this.onEvent(b.run, "job");
|
|
111
|
+
}
|
|
112
|
+
enterRunPhase(ip) {
|
|
113
|
+
const b = this.boxes.get(ip);
|
|
114
|
+
if (!b || b.phase === "run")
|
|
115
|
+
return;
|
|
116
|
+
b.phase = "run";
|
|
117
|
+
this.onEvent(b.run, "run");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function readBody(req, cap = MAX_BODY_BYTES) {
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
const chunks = [];
|
|
123
|
+
let n = 0;
|
|
124
|
+
req.on("data", (c) => {
|
|
125
|
+
n += c.length;
|
|
126
|
+
if (n > cap) {
|
|
127
|
+
reject(new Error("body too large"));
|
|
128
|
+
req.destroy();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
chunks.push(c);
|
|
132
|
+
});
|
|
133
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
134
|
+
req.on("error", reject);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function json(res, status, body) {
|
|
138
|
+
if (status === 204) {
|
|
139
|
+
res.writeHead(204).end();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
res.writeHead(status, { "content-type": "application/json" }).end(JSON.stringify(body));
|
|
143
|
+
}
|
|
144
|
+
export function parseReport(raw) {
|
|
145
|
+
const body = (raw && typeof raw === "object" ? raw : {});
|
|
146
|
+
const exitCode = typeof body.exitCode === "number" && Number.isInteger(body.exitCode) ? body.exitCode : null;
|
|
147
|
+
const installedPackages = Array.isArray(body.installedPackages)
|
|
148
|
+
? body.installedPackages
|
|
149
|
+
.filter((p) => p && typeof p.name === "string" && typeof p.version === "string" && p.name && p.version)
|
|
150
|
+
.slice(0, 2000)
|
|
151
|
+
.map((p) => ({
|
|
152
|
+
name: p.name,
|
|
153
|
+
version: p.version,
|
|
154
|
+
manager: p.manager === "npm" ? "npm" : "pip",
|
|
155
|
+
}))
|
|
156
|
+
: [];
|
|
157
|
+
return { exitCode, installedPackages };
|
|
158
|
+
}
|
|
159
|
+
export function createJobServer(registry) {
|
|
160
|
+
return http.createServer(async (req, res) => {
|
|
161
|
+
const ip = (req.socket.remoteAddress ?? "").replace(/^::ffff:/, "");
|
|
162
|
+
const box = registry.get(ip);
|
|
163
|
+
if (!box)
|
|
164
|
+
return json(res, 403, { error: "not a running box" });
|
|
165
|
+
const url = new URL(req.url ?? "/", "http://box");
|
|
166
|
+
try {
|
|
167
|
+
if (req.method === "GET" && url.pathname === "/job") {
|
|
168
|
+
registry.markJobFetched(ip);
|
|
169
|
+
return json(res, 200, jobFor(box.run));
|
|
170
|
+
}
|
|
171
|
+
if (req.method === "POST" && url.pathname === "/phase") {
|
|
172
|
+
const body = JSON.parse((await readBody(req)).toString("utf8") || "{}");
|
|
173
|
+
if (body.phase !== "run")
|
|
174
|
+
return json(res, 400, { error: "the only move is to the run phase" });
|
|
175
|
+
registry.enterRunPhase(ip);
|
|
176
|
+
return json(res, 200, { phase: "run" });
|
|
177
|
+
}
|
|
178
|
+
if (req.method === "POST" && url.pathname === "/log") {
|
|
179
|
+
req.on("data", (c) => box.log.append(c));
|
|
180
|
+
req.on("end", () => json(res, 204));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (req.method === "PUT" && url.pathname.startsWith("/out/")) {
|
|
184
|
+
const rel = safeOutPath(url.pathname);
|
|
185
|
+
if (!rel)
|
|
186
|
+
return json(res, 400, { error: "bad out path" });
|
|
187
|
+
if (box.outFiles.length >= MAX_OUT_FILES)
|
|
188
|
+
return json(res, 413, { error: `more than ${MAX_OUT_FILES} files` });
|
|
189
|
+
const cap = box.run.script.limits.outMb * 1024 * 1024;
|
|
190
|
+
const dest = path.join(box.outDir, rel);
|
|
191
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
192
|
+
const hash = createHash("sha256");
|
|
193
|
+
const file = fs.createWriteStream(dest, { mode: 0o600 });
|
|
194
|
+
let size = 0;
|
|
195
|
+
let over = false;
|
|
196
|
+
// Over the cap or cut off mid-upload: no partial file is kept, and the
|
|
197
|
+
// answer goes out only once it is gone.
|
|
198
|
+
const abort = (status, error) => {
|
|
199
|
+
if (over)
|
|
200
|
+
return;
|
|
201
|
+
over = true;
|
|
202
|
+
file.destroy();
|
|
203
|
+
file.once("close", () => {
|
|
204
|
+
fs.rmSync(dest, { force: true });
|
|
205
|
+
if (!res.headersSent)
|
|
206
|
+
json(res, status, { error });
|
|
207
|
+
req.destroy();
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
req.on("data", (c) => {
|
|
211
|
+
if (over)
|
|
212
|
+
return;
|
|
213
|
+
size += c.length;
|
|
214
|
+
if (box.outBytes + size > cap)
|
|
215
|
+
return abort(413, `/out exceeds ${box.run.script.limits.outMb} MB`);
|
|
216
|
+
hash.update(c);
|
|
217
|
+
file.write(c);
|
|
218
|
+
});
|
|
219
|
+
req.on("end", () => {
|
|
220
|
+
if (over)
|
|
221
|
+
return;
|
|
222
|
+
file.end(() => {
|
|
223
|
+
box.outBytes += size;
|
|
224
|
+
box.outFiles.push({ path: rel, size, sha256: hash.digest("hex") });
|
|
225
|
+
json(res, 201, { path: rel, size });
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
req.on("close", () => {
|
|
229
|
+
if (!req.complete)
|
|
230
|
+
abort(400, "upload cut off");
|
|
231
|
+
});
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (req.method === "POST" && url.pathname === "/done") {
|
|
235
|
+
box.finish(parseReport(JSON.parse((await readBody(req)).toString("utf8"))));
|
|
236
|
+
return json(res, 200, { ok: true });
|
|
237
|
+
}
|
|
238
|
+
return json(res, 404, { error: "no such door" });
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
if (!res.headersSent)
|
|
242
|
+
json(res, 400, { error: err.message });
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=job-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job-server.js","sourceRoot":"","sources":["../../../src/lib/box/job-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The provisioner's loop: one box per run, one run at a time (phase 0).
|
|
3
|
+
*
|
|
4
|
+
* guards ok? ─no─▶ wait (the run keeps its turn: nothing is leased)
|
|
5
|
+
* lease ─▶ clone + start a box ─▶ the box fetches its job, installs, runs
|
|
6
|
+
* ─▶ done | a clock ran out | Stop | lease lost | provisioner stopping
|
|
7
|
+
* destroy the box, ALWAYS ─▶ upload /out ─▶ finish with the evidence
|
|
8
|
+
*
|
|
9
|
+
* Three clocks, one after the other: BOOT (the box must ask for its job, else
|
|
10
|
+
* INFRA: it never started), SETUP (the declared packages must install, else
|
|
11
|
+
* timeout), and the script's own wall clock from the moment it starts.
|
|
12
|
+
*
|
|
13
|
+
* A lost lease (404/409) ends the work without a finish: the pod already gave
|
|
14
|
+
* the run up. A reaper destroys every tagged box no run holds, at start and
|
|
15
|
+
* after every run, so a crash never leaves a box behind for long.
|
|
16
|
+
*/
|
|
17
|
+
import type { BoxRegistry } from "./job-server.js";
|
|
18
|
+
import type { BoxBackend, HostReading } from "./proxmox.js";
|
|
19
|
+
import { type BoxHub, type BoxLimits, type FinishBody, type LeasedRun } from "./wire.js";
|
|
20
|
+
export interface HostGuards {
|
|
21
|
+
/** Wait unless the host has at least this much MemAvailable. */
|
|
22
|
+
minMemAvailableMb: number;
|
|
23
|
+
/** Wait while the box storage (thin pool data) is fuller than this. */
|
|
24
|
+
maxStorageUsedPct: number;
|
|
25
|
+
/** Wait while the thin pool's metadata is fuller than this. */
|
|
26
|
+
maxMetaUsedPct: number;
|
|
27
|
+
}
|
|
28
|
+
/** Phase 0 on the founder's host: swap is full, so the margin is RAM only. */
|
|
29
|
+
export declare const DEFAULT_GUARDS: HostGuards;
|
|
30
|
+
/**
|
|
31
|
+
* BOX-CONTRACT "Phase 0 caps". The pod enforces them when a run is queued; the
|
|
32
|
+
* provisioner re-applies them because the host is the person's, not the pod's.
|
|
33
|
+
*/
|
|
34
|
+
export declare const PHASE0_CAPS: BoxLimits;
|
|
35
|
+
/** A box that has not asked for its job by then did not start: INFRA, not the script's verdict. */
|
|
36
|
+
export declare const BOOT_SECONDS = 180;
|
|
37
|
+
/** The declared packages must be installed by then; past it the run timed out in setup. */
|
|
38
|
+
export declare const SETUP_SECONDS = 900;
|
|
39
|
+
/** Limits cut to the phase 0 caps, and the names of the ones that were cut. */
|
|
40
|
+
export declare function clampLimits(l: BoxLimits): {
|
|
41
|
+
limits: BoxLimits;
|
|
42
|
+
clamped: string[];
|
|
43
|
+
};
|
|
44
|
+
export declare function checkGuards(r: HostReading, g: HostGuards): {
|
|
45
|
+
ok: true;
|
|
46
|
+
} | {
|
|
47
|
+
ok: false;
|
|
48
|
+
reason: string;
|
|
49
|
+
};
|
|
50
|
+
export interface ProvisionerDeps {
|
|
51
|
+
hub: BoxHub;
|
|
52
|
+
backend: BoxBackend;
|
|
53
|
+
registry: BoxRegistry;
|
|
54
|
+
log: (line: string) => void;
|
|
55
|
+
now?: () => number;
|
|
56
|
+
/** Destroy attempts before leaving a box to the reaper. */
|
|
57
|
+
destroyAttempts?: number;
|
|
58
|
+
/** The provisioner is stopping: end the current run (box destroyed, finish INFRA). */
|
|
59
|
+
signal?: AbortSignal;
|
|
60
|
+
/** Clock overrides (tests). */
|
|
61
|
+
bootMs?: number;
|
|
62
|
+
setupMs?: number;
|
|
63
|
+
}
|
|
64
|
+
export declare function mimeOf(file: string): string;
|
|
65
|
+
/** Destroy every tagged box no run holds. Returns the VMIDs destroyed. */
|
|
66
|
+
export declare function reap(backend: BoxBackend, held: ReadonlySet<number>, log: (l: string) => void): Promise<number[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Work one leased run to its end (BOX-CONTRACT v2). Returns the finish body sent, or null when
|
|
69
|
+
* the lease was lost (no finish is sent then).
|
|
70
|
+
*/
|
|
71
|
+
export declare function runOne(leasedRun: LeasedRun, deps: ProvisionerDeps): Promise<FinishBody | null>;
|
|
72
|
+
export interface ServeOptions {
|
|
73
|
+
guards: HostGuards;
|
|
74
|
+
/** Wait between empty leases. */
|
|
75
|
+
idleMs: number;
|
|
76
|
+
/** Wait between guard readings while the host is short. */
|
|
77
|
+
guardWaitMs: number;
|
|
78
|
+
once?: boolean;
|
|
79
|
+
signal?: AbortSignal;
|
|
80
|
+
sleep?: (ms: number) => Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
/** Lease and work runs until the signal aborts (or one pass with `once`). */
|
|
83
|
+
export declare function serve(deps: ProvisionerDeps, opts: ServeOptions): Promise<void>;
|