agy-worker-mcp 0.3.1
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/CHANGELOG.md +141 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/commands/agy-ceiling.md +31 -0
- package/dist/broker/blockers.d.ts +86 -0
- package/dist/broker/blockers.d.ts.map +1 -0
- package/dist/broker/blockers.js +390 -0
- package/dist/broker/blockers.js.map +1 -0
- package/dist/broker/outcome.d.ts +85 -0
- package/dist/broker/outcome.d.ts.map +1 -0
- package/dist/broker/outcome.js +147 -0
- package/dist/broker/outcome.js.map +1 -0
- package/dist/broker/reconcile.d.ts +74 -0
- package/dist/broker/reconcile.d.ts.map +1 -0
- package/dist/broker/reconcile.js +415 -0
- package/dist/broker/reconcile.js.map +1 -0
- package/dist/broker/result.d.ts +88 -0
- package/dist/broker/result.d.ts.map +1 -0
- package/dist/broker/result.js +234 -0
- package/dist/broker/result.js.map +1 -0
- package/dist/broker/verify.d.ts +52 -0
- package/dist/broker/verify.d.ts.map +1 -0
- package/dist/broker/verify.js +174 -0
- package/dist/broker/verify.js.map +1 -0
- package/dist/contract/errors.d.ts +119 -0
- package/dist/contract/errors.d.ts.map +1 -0
- package/dist/contract/errors.js +99 -0
- package/dist/contract/errors.js.map +1 -0
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +10 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/paths.d.ts +139 -0
- package/dist/contract/paths.d.ts.map +1 -0
- package/dist/contract/paths.js +359 -0
- package/dist/contract/paths.js.map +1 -0
- package/dist/contract/schema.sql +64 -0
- package/dist/contract/types.d.ts +1113 -0
- package/dist/contract/types.d.ts.map +1 -0
- package/dist/contract/types.js +114 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/events/cursor.d.ts +65 -0
- package/dist/events/cursor.d.ts.map +1 -0
- package/dist/events/cursor.js +286 -0
- package/dist/events/cursor.js.map +1 -0
- package/dist/events/detect.d.ts +58 -0
- package/dist/events/detect.d.ts.map +1 -0
- package/dist/events/detect.js +183 -0
- package/dist/events/detect.js.map +1 -0
- package/dist/events/normalize.d.ts +30 -0
- package/dist/events/normalize.d.ts.map +1 -0
- package/dist/events/normalize.js +158 -0
- package/dist/events/normalize.js.map +1 -0
- package/dist/events/parse.d.ts +41 -0
- package/dist/events/parse.d.ts.map +1 -0
- package/dist/events/parse.js +89 -0
- package/dist/events/parse.js.map +1 -0
- package/dist/gate/bind.d.ts +28 -0
- package/dist/gate/bind.d.ts.map +1 -0
- package/dist/gate/bind.js +154 -0
- package/dist/gate/bind.js.map +1 -0
- package/dist/gate/gate.d.ts +139 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +488 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/hooks-file.d.ts +55 -0
- package/dist/gate/hooks-file.d.ts.map +1 -0
- package/dist/gate/hooks-file.js +104 -0
- package/dist/gate/hooks-file.js.map +1 -0
- package/dist/gate.d.ts +3 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +20 -0
- package/dist/gate.js.map +1 -0
- package/dist/policy/ceiling-review.d.ts +22 -0
- package/dist/policy/ceiling-review.d.ts.map +1 -0
- package/dist/policy/ceiling-review.js +170 -0
- package/dist/policy/ceiling-review.js.map +1 -0
- package/dist/policy/ceiling.d.ts +128 -0
- package/dist/policy/ceiling.d.ts.map +1 -0
- package/dist/policy/ceiling.js +273 -0
- package/dist/policy/ceiling.js.map +1 -0
- package/dist/policy/containment.d.ts +100 -0
- package/dist/policy/containment.d.ts.map +1 -0
- package/dist/policy/containment.js +1071 -0
- package/dist/policy/containment.js.map +1 -0
- package/dist/policy/hard-deny.d.ts +28 -0
- package/dist/policy/hard-deny.d.ts.map +1 -0
- package/dist/policy/hard-deny.js +78 -0
- package/dist/policy/hard-deny.js.map +1 -0
- package/dist/policy/profiles.d.ts +82 -0
- package/dist/policy/profiles.d.ts.map +1 -0
- package/dist/policy/profiles.js +317 -0
- package/dist/policy/profiles.js.map +1 -0
- package/dist/policy/rules.d.ts +138 -0
- package/dist/policy/rules.d.ts.map +1 -0
- package/dist/policy/rules.js +1180 -0
- package/dist/policy/rules.js.map +1 -0
- package/dist/policy/seatbelt.d.ts +32 -0
- package/dist/policy/seatbelt.d.ts.map +1 -0
- package/dist/policy/seatbelt.js +59 -0
- package/dist/policy/seatbelt.js.map +1 -0
- package/dist/policy/tools.d.ts +36 -0
- package/dist/policy/tools.d.ts.map +1 -0
- package/dist/policy/tools.js +94 -0
- package/dist/policy/tools.js.map +1 -0
- package/dist/runner/gate-watchdog.d.ts +93 -0
- package/dist/runner/gate-watchdog.d.ts.map +1 -0
- package/dist/runner/gate-watchdog.js +153 -0
- package/dist/runner/gate-watchdog.js.map +1 -0
- package/dist/runner/idle.d.ts +51 -0
- package/dist/runner/idle.d.ts.map +1 -0
- package/dist/runner/idle.js +81 -0
- package/dist/runner/idle.js.map +1 -0
- package/dist/runner/inbox.d.ts +56 -0
- package/dist/runner/inbox.d.ts.map +1 -0
- package/dist/runner/inbox.js +134 -0
- package/dist/runner/inbox.js.map +1 -0
- package/dist/runner/reap.d.ts +65 -0
- package/dist/runner/reap.d.ts.map +1 -0
- package/dist/runner/reap.js +168 -0
- package/dist/runner/reap.js.map +1 -0
- package/dist/runner/runner.d.ts +51 -0
- package/dist/runner/runner.d.ts.map +1 -0
- package/dist/runner/runner.js +289 -0
- package/dist/runner/runner.js.map +1 -0
- package/dist/runner/spawn.d.ts +98 -0
- package/dist/runner/spawn.d.ts.map +1 -0
- package/dist/runner/spawn.js +230 -0
- package/dist/runner/spawn.js.map +1 -0
- package/dist/runner/verify.d.ts +24 -0
- package/dist/runner/verify.d.ts.map +1 -0
- package/dist/runner/verify.js +108 -0
- package/dist/runner/verify.js.map +1 -0
- package/dist/runner.d.ts +3 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +15 -0
- package/dist/runner.js.map +1 -0
- package/dist/server/context.d.ts +41 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +59 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/instructions.d.ts +13 -0
- package/dist/server/instructions.d.ts.map +1 -0
- package/dist/server/instructions.js +121 -0
- package/dist/server/instructions.js.map +1 -0
- package/dist/server/server.d.ts +20 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +55 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/tools/cancel.d.ts +24 -0
- package/dist/server/tools/cancel.d.ts.map +1 -0
- package/dist/server/tools/cancel.js +59 -0
- package/dist/server/tools/cancel.js.map +1 -0
- package/dist/server/tools/capabilities.d.ts +36 -0
- package/dist/server/tools/capabilities.d.ts.map +1 -0
- package/dist/server/tools/capabilities.js +116 -0
- package/dist/server/tools/capabilities.js.map +1 -0
- package/dist/server/tools/ceiling.d.ts +31 -0
- package/dist/server/tools/ceiling.d.ts.map +1 -0
- package/dist/server/tools/ceiling.js +121 -0
- package/dist/server/tools/ceiling.js.map +1 -0
- package/dist/server/tools/index.d.ts +38 -0
- package/dist/server/tools/index.d.ts.map +1 -0
- package/dist/server/tools/index.js +115 -0
- package/dist/server/tools/index.js.map +1 -0
- package/dist/server/tools/listJobs.d.ts +30 -0
- package/dist/server/tools/listJobs.d.ts.map +1 -0
- package/dist/server/tools/listJobs.js +37 -0
- package/dist/server/tools/listJobs.js.map +1 -0
- package/dist/server/tools/logs.d.ts +31 -0
- package/dist/server/tools/logs.d.ts.map +1 -0
- package/dist/server/tools/logs.js +96 -0
- package/dist/server/tools/logs.js.map +1 -0
- package/dist/server/tools/result.d.ts +32 -0
- package/dist/server/tools/result.d.ts.map +1 -0
- package/dist/server/tools/result.js +95 -0
- package/dist/server/tools/result.js.map +1 -0
- package/dist/server/tools/send.d.ts +37 -0
- package/dist/server/tools/send.d.ts.map +1 -0
- package/dist/server/tools/send.js +71 -0
- package/dist/server/tools/send.js.map +1 -0
- package/dist/server/tools/sessions.d.ts +28 -0
- package/dist/server/tools/sessions.d.ts.map +1 -0
- package/dist/server/tools/sessions.js +54 -0
- package/dist/server/tools/sessions.js.map +1 -0
- package/dist/server/tools/start.d.ts +107 -0
- package/dist/server/tools/start.d.ts.map +1 -0
- package/dist/server/tools/start.js +482 -0
- package/dist/server/tools/start.js.map +1 -0
- package/dist/server/tools/wait.d.ts +29 -0
- package/dist/server/tools/wait.d.ts.map +1 -0
- package/dist/server/tools/wait.js +120 -0
- package/dist/server/tools/wait.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +17 -0
- package/dist/server.js.map +1 -0
- package/dist/setup/install.d.ts +52 -0
- package/dist/setup/install.d.ts.map +1 -0
- package/dist/setup/install.js +108 -0
- package/dist/setup/install.js.map +1 -0
- package/dist/setup.d.ts +3 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +24 -0
- package/dist/setup.js.map +1 -0
- package/dist/store/db.d.ts +49 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +101 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/jobs.d.ts +45 -0
- package/dist/store/jobs.d.ts.map +1 -0
- package/dist/store/jobs.js +150 -0
- package/dist/store/jobs.js.map +1 -0
- package/dist/store/locks.d.ts +60 -0
- package/dist/store/locks.d.ts.map +1 -0
- package/dist/store/locks.js +172 -0
- package/dist/store/locks.js.map +1 -0
- package/dist/store/sessions.d.ts +37 -0
- package/dist/store/sessions.d.ts.map +1 -0
- package/dist/store/sessions.js +117 -0
- package/dist/store/sessions.js.map +1 -0
- package/dist/trace/digest.d.ts +77 -0
- package/dist/trace/digest.d.ts.map +1 -0
- package/dist/trace/digest.js +481 -0
- package/dist/trace/digest.js.map +1 -0
- package/package.json +68 -0
- package/skills/agy-ceiling/SKILL.md +72 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured errors. READ-ONLY after Stage 1.
|
|
3
|
+
*
|
|
4
|
+
* Every error carries a machine-readable `detail` so the *calling agent* can
|
|
5
|
+
* repair itself without another round trip: which job holds the lock, which rule
|
|
6
|
+
* string to add, which enum values exist.
|
|
7
|
+
*/
|
|
8
|
+
/** Base for everything in this module. `instanceof` works across all subclasses. */
|
|
9
|
+
export class AgyWorkerError extends Error {
|
|
10
|
+
detail;
|
|
11
|
+
remedy;
|
|
12
|
+
constructor(message, detail, remedy) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = new.target.name;
|
|
15
|
+
this.detail = detail;
|
|
16
|
+
this.remedy = remedy;
|
|
17
|
+
Error.captureStackTrace?.(this, new.target);
|
|
18
|
+
}
|
|
19
|
+
toJSON() {
|
|
20
|
+
return {
|
|
21
|
+
error: this.code,
|
|
22
|
+
message: this.message,
|
|
23
|
+
detail: this.detail,
|
|
24
|
+
remedy: this.remedy,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function isAgyWorkerError(e) {
|
|
29
|
+
return e instanceof AgyWorkerError;
|
|
30
|
+
}
|
|
31
|
+
/** Normalizes anything thrown into an envelope so a tool handler never leaks a stack. */
|
|
32
|
+
export function toErrorEnvelope(e) {
|
|
33
|
+
if (isAgyWorkerError(e))
|
|
34
|
+
return e.toJSON();
|
|
35
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
36
|
+
return {
|
|
37
|
+
error: 'VALIDATION',
|
|
38
|
+
message,
|
|
39
|
+
detail: { unexpected: true },
|
|
40
|
+
remedy: 'This is an internal failure, not a usable input error. Retry once; if it repeats, report it.',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Losing a lock race is an error, never a silent serialization.
|
|
45
|
+
* The caller decides whether to wait on the holder or pick a different cwd.
|
|
46
|
+
*/
|
|
47
|
+
export class LockConflictError extends AgyWorkerError {
|
|
48
|
+
code = 'LOCK_CONFLICT';
|
|
49
|
+
constructor(detail, message) {
|
|
50
|
+
const holder = detail.holder_job_id;
|
|
51
|
+
super(message ??
|
|
52
|
+
(detail.reason === 'limit'
|
|
53
|
+
? `project concurrency limit reached (${detail.limit} running)`
|
|
54
|
+
: `${detail.scope} lock on "${detail.key}" is held by job ${holder}`), detail, detail.reason === 'limit'
|
|
55
|
+
? 'Wait for a running job to finish (agy_wait on one of running_job_ids), or cancel one with agy_cancel.'
|
|
56
|
+
: detail.scope === 'cwd_write'
|
|
57
|
+
? `One writing job per cwd at a time; holder is job ${holder}. For parallel work start each job in its own git worktree inside the project root (cwd), or agy_wait on the holder.`
|
|
58
|
+
: `Call agy_wait({ job_id: "${holder}" }) to take over the holder, agy_cancel to stop it, or start this job in a different cwd.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** A policy refusal, whether reported by the gate or replayed by the broker. */
|
|
62
|
+
export class PolicyDeniedError extends AgyWorkerError {
|
|
63
|
+
code = 'POLICY_DENIED';
|
|
64
|
+
constructor(detail, message) {
|
|
65
|
+
super(message ??
|
|
66
|
+
`${detail.tool}${detail.command ? ` (${detail.command})` : ''} denied by ${detail.policy} under profile "${detail.profile}"`, detail, detail.immutable
|
|
67
|
+
? `This rule cannot be lifted by a client request. Use a different approach, or a profile that permits it.`
|
|
68
|
+
: detail.required_rule
|
|
69
|
+
? `Retry with permissions.allow including ${JSON.stringify(detail.required_rule)}.`
|
|
70
|
+
: 'Narrow the requested action, or choose a profile whose ceiling covers it.');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Containment failure. Checked *after* realpath, never before (see docs/permissions.md). */
|
|
74
|
+
export class PathEscapeError extends AgyWorkerError {
|
|
75
|
+
code = 'PATH_ESCAPE';
|
|
76
|
+
constructor(detail, message) {
|
|
77
|
+
super(message ??
|
|
78
|
+
`path "${detail.input_path}" resolves to "${detail.resolved_path}", outside the allowed ${detail.kind} roots`, detail, `Use a path inside one of: ${detail.roots.join(', ')}. Symlinks are resolved before the check, so linking out does not work.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export class JobNotFoundError extends AgyWorkerError {
|
|
82
|
+
code = 'JOB_NOT_FOUND';
|
|
83
|
+
constructor(detail, message) {
|
|
84
|
+
super(message ?? `no job "${detail.job_id}" in project ${detail.project_root}`, detail, detail.known_recent.length
|
|
85
|
+
? `Recent job ids: ${detail.known_recent.join(', ')}. Use agy_list_jobs for the full list.`
|
|
86
|
+
: 'Use agy_list_jobs to see what exists in this project. Jobs are per-project and never visible across projects.');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export class ValidationError extends AgyWorkerError {
|
|
90
|
+
code = 'VALIDATION';
|
|
91
|
+
constructor(detail, message) {
|
|
92
|
+
super(message ?? `invalid ${detail.field}: expected ${detail.expected}`, detail, detail.allowed
|
|
93
|
+
? `Allowed values: ${detail.allowed.join(' | ')}.`
|
|
94
|
+
: detail.allowed_verbs
|
|
95
|
+
? `A rule looks like verb(pattern). Verbs: ${detail.allowed_verbs.join(' | ')}. Prefix the pattern with "regex:" to opt into regular expressions.`
|
|
96
|
+
: `Correct ${detail.field} and call again.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/contract/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwBH,oFAAoF;AACpF,MAAM,OAAgB,cAA4B,SAAQ,KAAK;IAEpD,MAAM,CAAG;IACT,MAAM,CAAQ;IAEvB,YAAsB,OAAe,EAAE,MAAS,EAAE,MAAc;QAC9D,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAA;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,KAAK,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7C,CAAC;IAED,MAAM;QACJ,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAA;IACH,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACzC,OAAO,CAAC,YAAY,cAAc,CAAA;AACpC,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,eAAe,CAAC,CAAU;IACxC,IAAI,gBAAgB,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,MAAM,EAAE,CAAA;IAC1C,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC1D,OAAO;QACL,KAAK,EAAE,YAAY;QACnB,OAAO;QACP,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;QAC5B,MAAM,EAAE,8FAA8F;KACvG,CAAA;AACH,CAAC;AAqBD;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,cAAkC;IAC9D,IAAI,GAAG,eAAwB,CAAA;IAExC,YAAY,MAA0B,EAAE,OAAgB;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAA;QACnC,KAAK,CACH,OAAO;YACL,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO;gBACxB,CAAC,CAAC,sCAAsC,MAAM,CAAC,KAAK,WAAW;gBAC/D,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,aAAa,MAAM,CAAC,GAAG,oBAAoB,MAAM,EAAE,CAAC,EACzE,MAAM,EACN,MAAM,CAAC,MAAM,KAAK,OAAO;YACvB,CAAC,CAAC,uGAAuG;YACzG,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,WAAW;gBAC5B,CAAC,CAAC,oDAAoD,MAAM,sHAAsH;gBAClL,CAAC,CAAC,4BAA4B,MAAM,4FAA4F,CACrI,CAAA;IACH,CAAC;CACF;AAuBD,gFAAgF;AAChF,MAAM,OAAO,iBAAkB,SAAQ,cAAkC;IAC9D,IAAI,GAAG,eAAwB,CAAA;IAExC,YAAY,MAA0B,EAAE,OAAgB;QACtD,KAAK,CACH,OAAO;YACL,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,cAAc,MAAM,CAAC,MAAM,mBAAmB,MAAM,CAAC,OAAO,GAAG,EAC9H,MAAM,EACN,MAAM,CAAC,SAAS;YACd,CAAC,CAAC,yGAAyG;YAC3G,CAAC,CAAC,MAAM,CAAC,aAAa;gBACpB,CAAC,CAAC,0CAA0C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG;gBACnF,CAAC,CAAC,2EAA2E,CAClF,CAAA;IACH,CAAC;CACF;AAiBD,6FAA6F;AAC7F,MAAM,OAAO,eAAgB,SAAQ,cAAgC;IAC1D,IAAI,GAAG,aAAsB,CAAA;IAEtC,YAAY,MAAwB,EAAE,OAAgB;QACpD,KAAK,CACH,OAAO;YACL,SAAS,MAAM,CAAC,UAAU,kBAAkB,MAAM,CAAC,aAAa,0BAA0B,MAAM,CAAC,IAAI,QAAQ,EAC/G,MAAM,EACN,6BAA6B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,yEAAyE,CAC9H,CAAA;IACH,CAAC;CACF;AAWD,MAAM,OAAO,gBAAiB,SAAQ,cAAiC;IAC5D,IAAI,GAAG,eAAwB,CAAA;IAExC,YAAY,MAAyB,EAAE,OAAgB;QACrD,KAAK,CACH,OAAO,IAAI,WAAW,MAAM,CAAC,MAAM,gBAAgB,MAAM,CAAC,YAAY,EAAE,EACxE,MAAM,EACN,MAAM,CAAC,YAAY,CAAC,MAAM;YACxB,CAAC,CAAC,mBAAmB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,wCAAwC;YAC3F,CAAC,CAAC,+GAA+G,CACpH,CAAA;IACH,CAAC;CACF;AAiBD,MAAM,OAAO,eAAgB,SAAQ,cAAgC;IAC1D,IAAI,GAAG,YAAqB,CAAA;IAErC,YAAY,MAAwB,EAAE,OAAgB;QACpD,KAAK,CACH,OAAO,IAAI,WAAW,MAAM,CAAC,KAAK,cAAc,MAAM,CAAC,QAAQ,EAAE,EACjE,MAAM,EACN,MAAM,CAAC,OAAO;YACZ,CAAC,CAAC,mBAAmB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG;YAClD,CAAC,CAAC,MAAM,CAAC,aAAa;gBACpB,CAAC,CAAC,2CAA2C,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,qEAAqE;gBAClJ,CAAC,CAAC,WAAW,MAAM,CAAC,KAAK,kBAAkB,CAChD,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frozen contract. Every other module imports from here (or from the three
|
|
3
|
+
* files directly); nothing else in `src/` may redefine these shapes.
|
|
4
|
+
*
|
|
5
|
+
* READ-ONLY after Stage 1 — see `contract_change_requests`.
|
|
6
|
+
*/
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './errors.js';
|
|
9
|
+
export * from './paths.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frozen contract. Every other module imports from here (or from the three
|
|
3
|
+
* files directly); nothing else in `src/` may redefine these shapes.
|
|
4
|
+
*
|
|
5
|
+
* READ-ONLY after Stage 1 — see `contract_change_requests`.
|
|
6
|
+
*/
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './errors.js';
|
|
9
|
+
export * from './paths.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project discovery, on-disk layout, and path containment. READ-ONLY after Stage 1.
|
|
3
|
+
*
|
|
4
|
+
* Layout — deliberately outside the repo so nothing has to be
|
|
5
|
+
* gitignored (see docs/operations.md):
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* ~/.agy-worker/projects/<sha256(canonical_root)[:16]>/
|
|
9
|
+
* project.json index.db
|
|
10
|
+
* jobs/<job-id>/{request,effective-config,state}.json
|
|
11
|
+
* events.ndjson stderr.log exit_code
|
|
12
|
+
* inbox.jsonl policy.json gate-log.jsonl
|
|
13
|
+
* agent-result.json broker-result.json verification.json
|
|
14
|
+
* verify.log verify.json
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export type ProjectRootSource = 'env' | 'git' | 'cwd';
|
|
18
|
+
export interface ProjectRootResolution {
|
|
19
|
+
root: string;
|
|
20
|
+
source: ProjectRootSource;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the project root.
|
|
24
|
+
*
|
|
25
|
+
* Precedence: `AGY_WORKER_PROJECT` (documented as an *override* in `docs/operations.md`) →
|
|
26
|
+
* nearest ancestor containing `.git` → the starting directory itself. The last
|
|
27
|
+
* branch ensures non-git directories are fully supported.
|
|
28
|
+
*
|
|
29
|
+
* The returned path is always canonical (symlinks resolved).
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveProjectRoot(startCwd?: string): ProjectRootResolution;
|
|
32
|
+
/** Convenience wrapper when the caller does not care where the root came from. */
|
|
33
|
+
export declare function projectRoot(startCwd?: string): string;
|
|
34
|
+
/** Walks up looking for `.git` (a directory *or* a worktree/submodule file). */
|
|
35
|
+
export declare function findGitRoot(startCanonical: string): string | null;
|
|
36
|
+
/** `~/.agy-worker`, or `AGY_WORKER_HOME` when set (tests always set it). */
|
|
37
|
+
export declare function stateHome(): string;
|
|
38
|
+
/** `sha256(canonical_root)` truncated to 16 hex chars — the per-project directory name. */
|
|
39
|
+
export declare function projectKey(canonicalRoot: string): string;
|
|
40
|
+
export interface ProjectPaths {
|
|
41
|
+
/** Canonical project root inside the user's filesystem. */
|
|
42
|
+
root: string;
|
|
43
|
+
key: string;
|
|
44
|
+
/** `<stateHome>/projects/<key>` */
|
|
45
|
+
dir: string;
|
|
46
|
+
projectJson: string;
|
|
47
|
+
db: string;
|
|
48
|
+
jobsDir: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function projectPaths(canonicalRoot: string): ProjectPaths;
|
|
51
|
+
/** Chmod SQLite db and WAL/SHM files to 0o600. */
|
|
52
|
+
export declare function chmodDbFiles(dbPath: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Creates the project directory tree and writes `project.json` (the reverse
|
|
55
|
+
* lookup from hash back to path). Idempotent and safe to race.
|
|
56
|
+
*/
|
|
57
|
+
export declare function ensureProjectDirs(paths: ProjectPaths): ProjectPaths;
|
|
58
|
+
export interface JobPaths {
|
|
59
|
+
jobId: string;
|
|
60
|
+
dir: string;
|
|
61
|
+
request: string;
|
|
62
|
+
effectiveConfig: string;
|
|
63
|
+
state: string;
|
|
64
|
+
/** agy stdout, redirected straight to this fd. Cursors are byte offsets into it. */
|
|
65
|
+
events: string;
|
|
66
|
+
stderr: string;
|
|
67
|
+
/** Written by the runner on exit. Its presence is what makes a job finalizable. */
|
|
68
|
+
exitCode: string;
|
|
69
|
+
inbox: string;
|
|
70
|
+
policy: string;
|
|
71
|
+
gateLog: string;
|
|
72
|
+
agentResult: string;
|
|
73
|
+
brokerResult: string;
|
|
74
|
+
verification: string;
|
|
75
|
+
/** stdout+stderr of `verify_command`, capped at 1 MiB (PR6 §6.2). */
|
|
76
|
+
verifyLog: string;
|
|
77
|
+
/** `VerifyRecord`, written once after `verify_command` exits (PR6 §6.2). */
|
|
78
|
+
verifyJson: string;
|
|
79
|
+
}
|
|
80
|
+
export declare function jobPaths(project: ProjectPaths, jobId: string): JobPaths;
|
|
81
|
+
export declare function ensureJobDirs(paths: JobPaths): JobPaths;
|
|
82
|
+
/** Sortable id: `<base36 ms>-<8 hex>`. Lexical order matches creation order. */
|
|
83
|
+
export declare function newJobId(now?: number): string;
|
|
84
|
+
/** Session ids are opaque; they never appear in a filesystem path. */
|
|
85
|
+
export declare function newSessionId(): string;
|
|
86
|
+
/**
|
|
87
|
+
* The DDL text. Resolved next to this module (`dist/contract/schema.sql` after a
|
|
88
|
+
* build, `src/contract/schema.sql` under vitest), with the source tree as fallback.
|
|
89
|
+
*/
|
|
90
|
+
export declare function loadSchemaSql(): string;
|
|
91
|
+
/** Installed package root (the directory holding `package.json`). */
|
|
92
|
+
export declare function packageRoot(): string;
|
|
93
|
+
/**
|
|
94
|
+
* Absolute path to one of the three entry points. The gate path is written into
|
|
95
|
+
* generated `hooks.json` files, so it must be stable and absolute.
|
|
96
|
+
*
|
|
97
|
+
* `ENV.GATE_BIN` overrides the `'gate'` case only — a test-only escape hatch
|
|
98
|
+
* (`ENV.GATE_BIN`'s own comment) so a test can point `agy_start` at a
|
|
99
|
+
* nonexistent gate binary and exercise its `existsSync` failure path without
|
|
100
|
+
* disturbing the real `dist/gate.js` every other test also depends on.
|
|
101
|
+
*/
|
|
102
|
+
export declare function binPath(which: 'server' | 'runner' | 'gate'): string;
|
|
103
|
+
/**
|
|
104
|
+
* Absolute, `..`-free, symlink-resolved path.
|
|
105
|
+
*
|
|
106
|
+
* When the path does not exist yet (a file the job is about to write) the deepest
|
|
107
|
+
* existing ancestor is resolved and the remaining segments are appended. That is
|
|
108
|
+
* what makes containment checks meaningful for not-yet-created files: the
|
|
109
|
+
* *directory* they would land in is what actually decides the answer.
|
|
110
|
+
*/
|
|
111
|
+
export declare function canonicalize(input: string): string;
|
|
112
|
+
/** True when `candidate` is `root` itself or lives beneath it. Both must be canonical. */
|
|
113
|
+
export declare function isWithin(candidate: string, root: string): boolean;
|
|
114
|
+
/** True when the path traverses a symlink anywhere below `root`. */
|
|
115
|
+
export declare function traversesSymlink(input: string): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Canonicalize then check containment; throw {@link PathEscapeError} on escape.
|
|
118
|
+
*
|
|
119
|
+
* ⚠ Order matters and is the whole point: resolving *after* the check would let a
|
|
120
|
+
* symlink inside the workspace point anywhere (see docs/permissions.md). Returns the
|
|
121
|
+
* canonical path so callers use the resolved form from here on.
|
|
122
|
+
*/
|
|
123
|
+
export declare function assertContained(input: string, roots: string[], kind: 'read' | 'write'): string;
|
|
124
|
+
/** Non-throwing form of {@link assertContained}. */
|
|
125
|
+
export declare function containedOrNull(input: string, roots: string[]): string | null;
|
|
126
|
+
/**
|
|
127
|
+
* Write via a sibling temp file plus `rename`, so a concurrent reader either sees
|
|
128
|
+
* the previous complete version or the new one — never a torn file. Several
|
|
129
|
+
* processes read `state.json` and `broker-result.json` without coordination.
|
|
130
|
+
*/
|
|
131
|
+
export declare function writeFileAtomic(target: string, data: string | Uint8Array): void;
|
|
132
|
+
export declare function writeJsonAtomic(target: string, value: unknown): void;
|
|
133
|
+
/** Returns null for a missing *or* unparsable file; a torn read is not fatal. */
|
|
134
|
+
export declare function readJsonIfExists<T>(target: string): T | null;
|
|
135
|
+
/** Appends one NDJSON line with a single `O_APPEND` write, which is atomic for small lines. */
|
|
136
|
+
export declare function appendJsonLine(target: string, value: unknown): void;
|
|
137
|
+
/** Current byte length, or 0 when the file does not exist yet. */
|
|
138
|
+
export declare function fileSize(target: string): number;
|
|
139
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/contract/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project discovery, on-disk layout, and path containment. READ-ONLY after Stage 1.
|
|
3
|
+
*
|
|
4
|
+
* Layout — deliberately outside the repo so nothing has to be
|
|
5
|
+
* gitignored (see docs/operations.md):
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* ~/.agy-worker/projects/<sha256(canonical_root)[:16]>/
|
|
9
|
+
* project.json index.db
|
|
10
|
+
* jobs/<job-id>/{request,effective-config,state}.json
|
|
11
|
+
* events.ndjson stderr.log exit_code
|
|
12
|
+
* inbox.jsonl policy.json gate-log.jsonl
|
|
13
|
+
* agent-result.json broker-result.json verification.json
|
|
14
|
+
* verify.log verify.json
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
18
|
+
import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, statSync, writeFileSync, writeSync, } from 'node:fs';
|
|
19
|
+
import { homedir } from 'node:os';
|
|
20
|
+
import { dirname, isAbsolute, join, parse as parsePath, relative, resolve, sep } from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
import { PathEscapeError } from './errors.js';
|
|
23
|
+
import { ENV } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the project root.
|
|
26
|
+
*
|
|
27
|
+
* Precedence: `AGY_WORKER_PROJECT` (documented as an *override* in `docs/operations.md`) →
|
|
28
|
+
* nearest ancestor containing `.git` → the starting directory itself. The last
|
|
29
|
+
* branch ensures non-git directories are fully supported.
|
|
30
|
+
*
|
|
31
|
+
* The returned path is always canonical (symlinks resolved).
|
|
32
|
+
*/
|
|
33
|
+
export function resolveProjectRoot(startCwd = process.cwd()) {
|
|
34
|
+
const override = process.env[ENV.PROJECT_ROOT];
|
|
35
|
+
if (override && override.trim()) {
|
|
36
|
+
return { root: canonicalize(resolve(override.trim())), source: 'env' };
|
|
37
|
+
}
|
|
38
|
+
const start = canonicalize(resolve(startCwd));
|
|
39
|
+
const gitRoot = findGitRoot(start);
|
|
40
|
+
if (gitRoot)
|
|
41
|
+
return { root: gitRoot, source: 'git' };
|
|
42
|
+
return { root: start, source: 'cwd' };
|
|
43
|
+
}
|
|
44
|
+
/** Convenience wrapper when the caller does not care where the root came from. */
|
|
45
|
+
export function projectRoot(startCwd) {
|
|
46
|
+
return resolveProjectRoot(startCwd).root;
|
|
47
|
+
}
|
|
48
|
+
/** Walks up looking for `.git` (a directory *or* a worktree/submodule file). */
|
|
49
|
+
export function findGitRoot(startCanonical) {
|
|
50
|
+
let dir = startCanonical;
|
|
51
|
+
for (;;) {
|
|
52
|
+
if (existsSync(join(dir, '.git')))
|
|
53
|
+
return dir;
|
|
54
|
+
const parent = dirname(dir);
|
|
55
|
+
if (parent === dir)
|
|
56
|
+
return null;
|
|
57
|
+
dir = parent;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
61
|
+
// State home and per-project directories
|
|
62
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
63
|
+
/** `~/.agy-worker`, or `AGY_WORKER_HOME` when set (tests always set it). */
|
|
64
|
+
export function stateHome() {
|
|
65
|
+
const override = process.env[ENV.STATE_HOME];
|
|
66
|
+
if (override && override.trim())
|
|
67
|
+
return resolve(override.trim());
|
|
68
|
+
return join(homedir(), '.agy-worker');
|
|
69
|
+
}
|
|
70
|
+
/** `sha256(canonical_root)` truncated to 16 hex chars — the per-project directory name. */
|
|
71
|
+
export function projectKey(canonicalRoot) {
|
|
72
|
+
return createHash('sha256').update(canonicalRoot).digest('hex').slice(0, 16);
|
|
73
|
+
}
|
|
74
|
+
export function projectPaths(canonicalRoot) {
|
|
75
|
+
const key = projectKey(canonicalRoot);
|
|
76
|
+
const dir = join(stateHome(), 'projects', key);
|
|
77
|
+
return {
|
|
78
|
+
root: canonicalRoot,
|
|
79
|
+
key,
|
|
80
|
+
dir,
|
|
81
|
+
projectJson: join(dir, 'project.json'),
|
|
82
|
+
db: join(dir, 'index.db'),
|
|
83
|
+
jobsDir: join(dir, 'jobs'),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Chmod SQLite db and WAL/SHM files to 0o600. */
|
|
87
|
+
export function chmodDbFiles(dbPath) {
|
|
88
|
+
for (const suffix of ['', '-wal', '-shm']) {
|
|
89
|
+
const p = `${dbPath}${suffix}`;
|
|
90
|
+
if (existsSync(p)) {
|
|
91
|
+
try {
|
|
92
|
+
chmodSync(p, 0o600);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// best-effort
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Creates the project directory tree and writes `project.json` (the reverse
|
|
102
|
+
* lookup from hash back to path). Idempotent and safe to race.
|
|
103
|
+
*/
|
|
104
|
+
export function ensureProjectDirs(paths) {
|
|
105
|
+
mkdirSync(paths.jobsDir, { recursive: true, mode: 0o700 });
|
|
106
|
+
try {
|
|
107
|
+
chmodSync(paths.dir, 0o700);
|
|
108
|
+
chmodSync(paths.jobsDir, 0o700);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// best-effort
|
|
112
|
+
}
|
|
113
|
+
if (!existsSync(paths.projectJson)) {
|
|
114
|
+
writeJsonAtomic(paths.projectJson, { root: paths.root, key: paths.key });
|
|
115
|
+
}
|
|
116
|
+
chmodDbFiles(paths.db);
|
|
117
|
+
return paths;
|
|
118
|
+
}
|
|
119
|
+
export function jobPaths(project, jobId) {
|
|
120
|
+
const dir = join(project.jobsDir, jobId);
|
|
121
|
+
return {
|
|
122
|
+
jobId,
|
|
123
|
+
dir,
|
|
124
|
+
request: join(dir, 'request.json'),
|
|
125
|
+
effectiveConfig: join(dir, 'effective-config.json'),
|
|
126
|
+
state: join(dir, 'state.json'),
|
|
127
|
+
events: join(dir, 'events.ndjson'),
|
|
128
|
+
stderr: join(dir, 'stderr.log'),
|
|
129
|
+
exitCode: join(dir, 'exit_code'),
|
|
130
|
+
inbox: join(dir, 'inbox.jsonl'),
|
|
131
|
+
policy: join(dir, 'policy.json'),
|
|
132
|
+
gateLog: join(dir, 'gate-log.jsonl'),
|
|
133
|
+
agentResult: join(dir, 'agent-result.json'),
|
|
134
|
+
brokerResult: join(dir, 'broker-result.json'),
|
|
135
|
+
verification: join(dir, 'verification.json'),
|
|
136
|
+
verifyLog: join(dir, 'verify.log'),
|
|
137
|
+
verifyJson: join(dir, 'verify.json'),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export function ensureJobDirs(paths) {
|
|
141
|
+
mkdirSync(paths.dir, { recursive: true, mode: 0o700 });
|
|
142
|
+
try {
|
|
143
|
+
chmodSync(paths.dir, 0o700);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// best-effort
|
|
147
|
+
}
|
|
148
|
+
chmodDbFiles(join(paths.dir, '..', '..', 'index.db'));
|
|
149
|
+
return paths;
|
|
150
|
+
}
|
|
151
|
+
/** Sortable id: `<base36 ms>-<8 hex>`. Lexical order matches creation order. */
|
|
152
|
+
export function newJobId(now = Date.now()) {
|
|
153
|
+
return `${now.toString(36)}-${randomUUID().replace(/-/g, '').slice(0, 8)}`;
|
|
154
|
+
}
|
|
155
|
+
/** Session ids are opaque; they never appear in a filesystem path. */
|
|
156
|
+
export function newSessionId() {
|
|
157
|
+
return randomUUID();
|
|
158
|
+
}
|
|
159
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
160
|
+
// Package-relative resources
|
|
161
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
162
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
163
|
+
/**
|
|
164
|
+
* The DDL text. Resolved next to this module (`dist/contract/schema.sql` after a
|
|
165
|
+
* build, `src/contract/schema.sql` under vitest), with the source tree as fallback.
|
|
166
|
+
*/
|
|
167
|
+
export function loadSchemaSql() {
|
|
168
|
+
const candidates = [
|
|
169
|
+
join(HERE, 'schema.sql'),
|
|
170
|
+
join(HERE, '..', '..', 'src', 'contract', 'schema.sql'),
|
|
171
|
+
];
|
|
172
|
+
for (const c of candidates) {
|
|
173
|
+
if (existsSync(c))
|
|
174
|
+
return readFileSync(c, 'utf8');
|
|
175
|
+
}
|
|
176
|
+
throw new Error(`schema.sql not found; looked in: ${candidates.join(', ')}`);
|
|
177
|
+
}
|
|
178
|
+
/** Installed package root (the directory holding `package.json`). */
|
|
179
|
+
export function packageRoot() {
|
|
180
|
+
let dir = HERE;
|
|
181
|
+
for (;;) {
|
|
182
|
+
if (existsSync(join(dir, 'package.json')))
|
|
183
|
+
return dir;
|
|
184
|
+
const parent = dirname(dir);
|
|
185
|
+
if (parent === dir)
|
|
186
|
+
return HERE;
|
|
187
|
+
dir = parent;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Absolute path to one of the three entry points. The gate path is written into
|
|
192
|
+
* generated `hooks.json` files, so it must be stable and absolute.
|
|
193
|
+
*
|
|
194
|
+
* `ENV.GATE_BIN` overrides the `'gate'` case only — a test-only escape hatch
|
|
195
|
+
* (`ENV.GATE_BIN`'s own comment) so a test can point `agy_start` at a
|
|
196
|
+
* nonexistent gate binary and exercise its `existsSync` failure path without
|
|
197
|
+
* disturbing the real `dist/gate.js` every other test also depends on.
|
|
198
|
+
*/
|
|
199
|
+
export function binPath(which) {
|
|
200
|
+
if (which === 'gate') {
|
|
201
|
+
const override = process.env[ENV.GATE_BIN];
|
|
202
|
+
if (override && override.trim())
|
|
203
|
+
return override.trim();
|
|
204
|
+
}
|
|
205
|
+
const root = packageRoot();
|
|
206
|
+
const dist = join(root, 'dist', `${which}.js`);
|
|
207
|
+
if (existsSync(dist))
|
|
208
|
+
return dist;
|
|
209
|
+
return join(root, 'src', `${which}.ts`);
|
|
210
|
+
}
|
|
211
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
212
|
+
// Canonicalization and containment
|
|
213
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
214
|
+
/**
|
|
215
|
+
* Absolute, `..`-free, symlink-resolved path.
|
|
216
|
+
*
|
|
217
|
+
* When the path does not exist yet (a file the job is about to write) the deepest
|
|
218
|
+
* existing ancestor is resolved and the remaining segments are appended. That is
|
|
219
|
+
* what makes containment checks meaningful for not-yet-created files: the
|
|
220
|
+
* *directory* they would land in is what actually decides the answer.
|
|
221
|
+
*/
|
|
222
|
+
export function canonicalize(input) {
|
|
223
|
+
const abs = isAbsolute(input) ? resolve(input) : resolve(process.cwd(), input);
|
|
224
|
+
try {
|
|
225
|
+
return realpathSync.native(abs);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// fall through to the partial-resolution path
|
|
229
|
+
}
|
|
230
|
+
const rootOf = parsePath(abs).root;
|
|
231
|
+
const tail = [];
|
|
232
|
+
let dir = abs;
|
|
233
|
+
for (;;) {
|
|
234
|
+
const parent = dirname(dir);
|
|
235
|
+
tail.unshift(dir.slice(parent === rootOf ? parent.length : parent.length + 1));
|
|
236
|
+
dir = parent;
|
|
237
|
+
if (dir === rootOf)
|
|
238
|
+
break;
|
|
239
|
+
try {
|
|
240
|
+
return join(realpathSync.native(dir), ...tail);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
return join(realpathSync.native(rootOf), ...tail);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return abs;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/** True when `candidate` is `root` itself or lives beneath it. Both must be canonical. */
|
|
254
|
+
export function isWithin(candidate, root) {
|
|
255
|
+
if (candidate === root)
|
|
256
|
+
return true;
|
|
257
|
+
const rel = relative(root, candidate);
|
|
258
|
+
return rel !== '' && !rel.startsWith('..' + sep) && rel !== '..' && !isAbsolute(rel);
|
|
259
|
+
}
|
|
260
|
+
/** True when the path traverses a symlink anywhere below `root`. */
|
|
261
|
+
export function traversesSymlink(input) {
|
|
262
|
+
const abs = isAbsolute(input) ? resolve(input) : resolve(process.cwd(), input);
|
|
263
|
+
return canonicalize(abs) !== abs;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Canonicalize then check containment; throw {@link PathEscapeError} on escape.
|
|
267
|
+
*
|
|
268
|
+
* ⚠ Order matters and is the whole point: resolving *after* the check would let a
|
|
269
|
+
* symlink inside the workspace point anywhere (see docs/permissions.md). Returns the
|
|
270
|
+
* canonical path so callers use the resolved form from here on.
|
|
271
|
+
*/
|
|
272
|
+
export function assertContained(input, roots, kind) {
|
|
273
|
+
const resolved = canonicalize(input);
|
|
274
|
+
const canonicalRoots = roots.map(canonicalize);
|
|
275
|
+
for (const root of canonicalRoots) {
|
|
276
|
+
if (isWithin(resolved, root))
|
|
277
|
+
return resolved;
|
|
278
|
+
}
|
|
279
|
+
const abs = isAbsolute(input) ? resolve(input) : resolve(process.cwd(), input);
|
|
280
|
+
throw new PathEscapeError({
|
|
281
|
+
input_path: input,
|
|
282
|
+
resolved_path: resolved,
|
|
283
|
+
kind,
|
|
284
|
+
roots: canonicalRoots,
|
|
285
|
+
via_symlink: resolved !== abs,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/** Non-throwing form of {@link assertContained}. */
|
|
289
|
+
export function containedOrNull(input, roots) {
|
|
290
|
+
const resolved = canonicalize(input);
|
|
291
|
+
for (const root of roots) {
|
|
292
|
+
if (isWithin(resolved, canonicalize(root)))
|
|
293
|
+
return resolved;
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
298
|
+
// Atomic file helpers
|
|
299
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
300
|
+
/**
|
|
301
|
+
* Write via a sibling temp file plus `rename`, so a concurrent reader either sees
|
|
302
|
+
* the previous complete version or the new one — never a torn file. Several
|
|
303
|
+
* processes read `state.json` and `broker-result.json` without coordination.
|
|
304
|
+
*/
|
|
305
|
+
export function writeFileAtomic(target, data) {
|
|
306
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
307
|
+
const tmp = `${target}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
308
|
+
const fd = openSync(tmp, 'wx', 0o600);
|
|
309
|
+
try {
|
|
310
|
+
if (typeof data === 'string')
|
|
311
|
+
writeSync(fd, data);
|
|
312
|
+
else
|
|
313
|
+
writeSync(fd, data);
|
|
314
|
+
fsyncSync(fd);
|
|
315
|
+
}
|
|
316
|
+
finally {
|
|
317
|
+
closeSync(fd);
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
chmodSync(tmp, 0o600);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// best-effort
|
|
324
|
+
}
|
|
325
|
+
renameSync(tmp, target);
|
|
326
|
+
}
|
|
327
|
+
export function writeJsonAtomic(target, value) {
|
|
328
|
+
writeFileAtomic(target, JSON.stringify(value, null, 2) + '\n');
|
|
329
|
+
}
|
|
330
|
+
/** Returns null for a missing *or* unparsable file; a torn read is not fatal. */
|
|
331
|
+
export function readJsonIfExists(target) {
|
|
332
|
+
try {
|
|
333
|
+
return JSON.parse(readFileSync(target, 'utf8'));
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/** Appends one NDJSON line with a single `O_APPEND` write, which is atomic for small lines. */
|
|
340
|
+
export function appendJsonLine(target, value) {
|
|
341
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
342
|
+
writeFileSync(target, JSON.stringify(value) + '\n', { flag: 'a', mode: 0o600 });
|
|
343
|
+
try {
|
|
344
|
+
chmodSync(target, 0o600);
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// best-effort
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** Current byte length, or 0 when the file does not exist yet. */
|
|
351
|
+
export function fileSize(target) {
|
|
352
|
+
try {
|
|
353
|
+
return statSync(target).size;
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/contract/paths.ts"],"names":[],"mappings":"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"}
|