harnery 0.37.0 → 0.38.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/dist/commander.d.ts +9 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +7 -2
- package/dist/commands/admission.d.ts +21 -0
- package/dist/commands/admission.d.ts.map +1 -0
- package/dist/commands/admission.js +565 -0
- package/dist/commands/agents.d.ts +7 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +61 -1
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +48 -2
- package/dist/commands/browse-ai.d.ts +2 -2
- package/dist/commands/browse-ai.d.ts.map +1 -1
- package/dist/commands/browse-ai.js +6 -4
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +349 -21
- package/dist/commands/fetch.js +1 -0
- package/dist/commands/qa-record.d.ts +144 -0
- package/dist/commands/qa-record.d.ts.map +1 -0
- package/dist/commands/qa-record.js +0 -0
- package/dist/commands/qa-run.d.ts +7 -3
- package/dist/commands/qa-run.d.ts.map +1 -1
- package/dist/commands/qa-run.js +268 -13
- package/dist/commands/qa-status.d.ts +71 -0
- package/dist/commands/qa-status.d.ts.map +1 -0
- package/dist/commands/qa-status.js +490 -0
- package/dist/commands/qa-verify.d.ts +40 -0
- package/dist/commands/qa-verify.d.ts.map +1 -0
- package/dist/commands/qa-verify.js +180 -0
- package/dist/commands/review-pack.d.ts +4 -0
- package/dist/commands/review-pack.d.ts.map +1 -0
- package/dist/commands/review-pack.js +1001 -0
- package/dist/core/agents/qa-signal.d.ts +111 -0
- package/dist/core/agents/qa-signal.d.ts.map +1 -0
- package/dist/core/agents/qa-signal.js +231 -0
- package/dist/core/agents/session-name-display.d.ts +20 -5
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +67 -7
- package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +11 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +17 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +5 -0
- package/dist/core/artifacts/constants.d.ts +1 -1
- package/dist/core/artifacts/constants.js +1 -1
- package/dist/core/artifacts/index.d.ts +57 -6
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +265 -10
- package/dist/core/config.d.ts +8 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +16 -0
- package/dist/core/diagnostics/bundle.d.ts +16 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +101 -7
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +10 -0
- package/dist/core/events/v3/coordination-view.d.ts +3 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +69 -8
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +9 -2
- package/dist/core/events/v3/producers/recorder.d.ts +23 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +264 -18
- package/dist/core/hooks/cli.js +120 -27
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +10 -3
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +4 -1
- package/dist/core/qa-artifacts.d.ts +20 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -0
- package/dist/core/qa-artifacts.js +110 -0
- package/dist/core/resources/contract.d.ts +6 -0
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/sampler.d.ts +7 -0
- package/dist/core/resources/sampler.d.ts.map +1 -1
- package/dist/core/resources/sampler.js +106 -5
- package/dist/lib/admission.d.ts +71 -0
- package/dist/lib/admission.d.ts.map +1 -0
- package/dist/lib/admission.js +264 -0
- package/dist/lib/agent-browser/client.d.ts +1 -1
- package/dist/lib/agent-browser/client.d.ts.map +1 -1
- package/dist/lib/agent-browser/client.js +1 -5
- package/dist/lib/browser/capture-fidelity.d.ts +39 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -0
- package/dist/lib/browser/capture-fidelity.js +84 -0
- package/dist/lib/browser/client.d.ts +41 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +167 -9
- package/dist/lib/browser/critique.d.ts +38 -1
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +34 -6
- package/dist/lib/browser/index.d.ts +4 -2
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/browser/page-review-judge.d.ts +64 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -0
- package/dist/lib/browser/page-review-judge.js +270 -0
- package/dist/lib/browser/page-review-pack.d.ts +613 -0
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -0
- package/dist/lib/browser/page-review-pack.js +1751 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +214 -10
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run-contracts.js +136 -1
- package/dist/lib/browser/qa-run.d.ts +100 -10
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +768 -169
- package/dist/lib/browser/request-diagnostics.d.ts +13 -0
- package/dist/lib/browser/request-diagnostics.d.ts.map +1 -0
- package/dist/lib/browser/request-diagnostics.js +18 -0
- package/dist/lib/browser/tiling.d.ts +19 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +28 -0
- package/dist/lib/cookies/client.d.ts +9 -0
- package/dist/lib/cookies/client.d.ts.map +1 -1
- package/dist/lib/cookies/client.js +197 -44
- package/dist/lib/cookies/extra.d.ts +18 -0
- package/dist/lib/cookies/extra.d.ts.map +1 -0
- package/dist/lib/cookies/extra.js +14 -0
- package/dist/lib/cookies/index.d.ts +2 -1
- package/dist/lib/cookies/index.d.ts.map +1 -1
- package/dist/lib/cookies/index.js +2 -1
- package/dist/lib/durable-job.d.ts +124 -0
- package/dist/lib/durable-job.d.ts.map +1 -0
- package/dist/lib/durable-job.js +296 -0
- package/dist/lib/http/client.d.ts +7 -1
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +5 -2
- package/package.json +8 -2
- package/src/commander.ts +50 -2
- package/src/commands/admission.ts +699 -0
- package/src/commands/agents.ts +87 -1
- package/src/commands/artifacts.ts +97 -21
- package/src/commands/browse-ai.ts +10 -5
- package/src/commands/browse.ts +481 -20
- package/src/commands/fetch.ts +1 -0
- package/src/commands/qa-record.ts +682 -0
- package/src/commands/qa-run.ts +335 -16
- package/src/commands/qa-status.ts +608 -0
- package/src/commands/qa-verify.ts +238 -0
- package/src/commands/review-pack.ts +1281 -0
- package/src/core/agents/qa-signal.ts +261 -0
- package/src/core/agents/session-name-display.ts +78 -7
- package/src/core/agents/state/heartbeat-reader.ts +7 -0
- package/src/core/agents/state/heartbeat-writer.ts +23 -0
- package/src/core/agents/state/live-coordination-view.ts +1 -0
- package/src/core/agents/state/live-coordination-writer.ts +5 -0
- package/src/core/artifacts/constants.ts +1 -1
- package/src/core/artifacts/index.ts +370 -21
- package/src/core/config.ts +23 -0
- package/src/core/diagnostics/bundle.ts +119 -11
- package/src/core/events/v3/bootstrap.ts +10 -0
- package/src/core/events/v3/coordination-view.ts +100 -11
- package/src/core/events/v3/producers/intake.ts +9 -2
- package/src/core/events/v3/producers/recorder.ts +312 -18
- package/src/core/hooks/cli.ts +140 -32
- package/src/core/hooks/resolve/transcript.ts +10 -3
- package/src/core/hooks/session-name-presence.ts +6 -1
- package/src/core/qa-artifacts.ts +126 -0
- package/src/core/resources/contract.ts +7 -0
- package/src/core/resources/sampler.ts +138 -6
- package/src/lib/admission.ts +347 -0
- package/src/lib/agent-browser/client.ts +2 -10
- package/src/lib/browser/capture-fidelity.ts +98 -0
- package/src/lib/browser/client.ts +206 -10
- package/src/lib/browser/critique.ts +62 -7
- package/src/lib/browser/index.ts +36 -0
- package/src/lib/browser/page-review-judge.ts +360 -0
- package/src/lib/browser/page-review-pack.ts +2384 -0
- package/src/lib/browser/qa-run-contracts.ts +366 -3
- package/src/lib/browser/qa-run.ts +868 -190
- package/src/lib/browser/request-diagnostics.ts +27 -0
- package/src/lib/browser/tiling.ts +32 -0
- package/src/lib/cookies/client.ts +228 -42
- package/src/lib/cookies/extra.ts +28 -0
- package/src/lib/cookies/index.ts +2 -0
- package/src/lib/durable-job.ts +407 -0
- package/src/lib/http/client.ts +13 -1
- package/src/lib/instructions/templates.ts +5 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface FailedRequestCandidate {
|
|
2
|
+
url: string;
|
|
3
|
+
method: string;
|
|
4
|
+
failure: string;
|
|
5
|
+
resourceType: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Next.js may start a speculative React Server Component fetch and cancel it
|
|
9
|
+
* once the destination is no longer needed. Chromium reports that deliberate
|
|
10
|
+
* cancellation as net::ERR_ABORTED even though the rendered page is healthy.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isBenignNextRscAbort(request: FailedRequestCandidate): boolean;
|
|
13
|
+
//# sourceMappingURL=request-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-diagnostics.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/request-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAc7E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js may start a speculative React Server Component fetch and cancel it
|
|
3
|
+
* once the destination is no longer needed. Chromium reports that deliberate
|
|
4
|
+
* cancellation as net::ERR_ABORTED even though the rendered page is healthy.
|
|
5
|
+
*/
|
|
6
|
+
export function isBenignNextRscAbort(request) {
|
|
7
|
+
if (request.failure !== "net::ERR_ABORTED" ||
|
|
8
|
+
request.method !== "GET" ||
|
|
9
|
+
request.resourceType !== "fetch") {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
return new URL(request.url).searchParams.has("_rsc");
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -68,4 +68,23 @@ export declare function bandOversizedRect(rect: {
|
|
|
68
68
|
width: number;
|
|
69
69
|
height: number;
|
|
70
70
|
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Indices of bands past the kept prefix (`allBands[0..keptCount)`) that
|
|
73
|
+
* intersect any of `rects`. A tile cap keeps the top of a tall page and drops
|
|
74
|
+
* the rest; a deterministic gate that already found a defect below the cap
|
|
75
|
+
* still deserves a tile, so the caller cuts these bands as well and labels
|
|
76
|
+
* them as hit bands. Pure: the result is deduplicated, ascending, and holds
|
|
77
|
+
* at most `maxExtra` entries. Rects and bands share one pixel space.
|
|
78
|
+
*/
|
|
79
|
+
export declare function bandsCoveringRects(allBands: ReadonlyArray<{
|
|
80
|
+
x: number;
|
|
81
|
+
y: number;
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
}>, keptCount: number, rects: ReadonlyArray<{
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
width: number;
|
|
88
|
+
height: number;
|
|
89
|
+
}>, maxExtra?: number): number[];
|
|
71
90
|
//# sourceMappingURL=tiling.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiling.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/tiling.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;IACvC,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD,6DAA6D;AAC7D,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CActF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,WAAW,GAChB;IACD,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrF,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CA+CA;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5E,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,WAAW,GAChB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAU/E"}
|
|
1
|
+
{"version":3,"file":"tiling.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/tiling.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;IACvC,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD,6DAA6D;AAC7D,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CActF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,WAAW,GAChB;IACD,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrF,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CA+CA;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5E,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,WAAW,GAChB,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAU/E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAChF,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,aAAa,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7E,QAAQ,SAAK,GACZ,MAAM,EAAE,CAiBV"}
|
|
@@ -116,3 +116,31 @@ export function bandOversizedRect(rect, atoms, opts) {
|
|
|
116
116
|
height: r.height,
|
|
117
117
|
}));
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Indices of bands past the kept prefix (`allBands[0..keptCount)`) that
|
|
121
|
+
* intersect any of `rects`. A tile cap keeps the top of a tall page and drops
|
|
122
|
+
* the rest; a deterministic gate that already found a defect below the cap
|
|
123
|
+
* still deserves a tile, so the caller cuts these bands as well and labels
|
|
124
|
+
* them as hit bands. Pure: the result is deduplicated, ascending, and holds
|
|
125
|
+
* at most `maxExtra` entries. Rects and bands share one pixel space.
|
|
126
|
+
*/
|
|
127
|
+
export function bandsCoveringRects(allBands, keptCount, rects, maxExtra = 50) {
|
|
128
|
+
const out = [];
|
|
129
|
+
if (rects.length === 0 || maxExtra <= 0)
|
|
130
|
+
return out;
|
|
131
|
+
for (let index = Math.max(0, keptCount); index < allBands.length; index++) {
|
|
132
|
+
if (out.length >= maxExtra)
|
|
133
|
+
break;
|
|
134
|
+
const band = allBands[index];
|
|
135
|
+
if (!band)
|
|
136
|
+
continue;
|
|
137
|
+
const hit = rects.some((rect) => {
|
|
138
|
+
const x1 = rect.x + Math.max(rect.width, 1);
|
|
139
|
+
const y1 = rect.y + Math.max(rect.height, 1);
|
|
140
|
+
return (band.x < x1 && band.x + band.width > rect.x && band.y < y1 && band.y + band.height > rect.y);
|
|
141
|
+
});
|
|
142
|
+
if (hit)
|
|
143
|
+
out.push(index);
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
@@ -52,6 +52,10 @@ export interface InfoResult {
|
|
|
52
52
|
exportedAt?: string;
|
|
53
53
|
exportedFrom?: string;
|
|
54
54
|
}
|
|
55
|
+
export declare class CookieStoreParseError extends Error {
|
|
56
|
+
readonly path: string;
|
|
57
|
+
constructor(path: string, cause: unknown);
|
|
58
|
+
}
|
|
55
59
|
export declare class CookieJar {
|
|
56
60
|
readonly path: string;
|
|
57
61
|
private readonly source;
|
|
@@ -63,6 +67,9 @@ export declare class CookieJar {
|
|
|
63
67
|
* (constructor-provided source). Creates the parent directory if needed.
|
|
64
68
|
*/
|
|
65
69
|
save(store: CookieStore): void;
|
|
70
|
+
private saveUnlocked;
|
|
71
|
+
private stamp;
|
|
72
|
+
private update;
|
|
66
73
|
/**
|
|
67
74
|
* Read + filter helper. Drops expired cookies. Optional domain filter
|
|
68
75
|
* uses the same `domainMatches` logic Playwright/CDP do (leading dot
|
|
@@ -76,6 +83,8 @@ export declare class CookieJar {
|
|
|
76
83
|
* Returns the saved store.
|
|
77
84
|
*/
|
|
78
85
|
set(cookie: Cookie): CookieStore;
|
|
86
|
+
/** Merge cookies and origins in one interprocess-coordinated update. */
|
|
87
|
+
merge(cookies: Cookie[], origins?: OriginEntry[]): CookieStore;
|
|
79
88
|
/**
|
|
80
89
|
* Clear cookies. Pass `{ all: true }` to wipe everything (including
|
|
81
90
|
* origins/localStorage), or `{ domain: "..." }` to drop matching cookies
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,139 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
export class CookieStoreParseError extends Error {
|
|
5
|
+
path;
|
|
6
|
+
constructor(path, cause) {
|
|
7
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
8
|
+
super(`Cookie-store parse failed at "${path}" after a stable read: ${detail}. ` +
|
|
9
|
+
"The original cookie-store file was left unchanged.", { cause });
|
|
10
|
+
this.name = "CookieStoreParseError";
|
|
11
|
+
this.path = path;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const LOCK_WAIT_MS = 10_000;
|
|
15
|
+
const LOCK_POLL_MS = 10;
|
|
16
|
+
const STABLE_READ_ATTEMPTS = 5;
|
|
17
|
+
const STABLE_READ_POLL_MS = 10;
|
|
18
|
+
const sleepBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
19
|
+
function sleepSync(ms) {
|
|
20
|
+
Atomics.wait(sleepBuffer, 0, 0, ms);
|
|
21
|
+
}
|
|
22
|
+
function isErrorCode(error, code) {
|
|
23
|
+
return error.code === code;
|
|
24
|
+
}
|
|
25
|
+
function snapshot(path) {
|
|
26
|
+
const stat = statSync(path);
|
|
27
|
+
return {
|
|
28
|
+
dev: stat.dev,
|
|
29
|
+
ino: stat.ino,
|
|
30
|
+
size: stat.size,
|
|
31
|
+
mtimeMs: stat.mtimeMs,
|
|
32
|
+
ctimeMs: stat.ctimeMs,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function sameSnapshot(left, right) {
|
|
36
|
+
return (left.dev === right.dev &&
|
|
37
|
+
left.ino === right.ino &&
|
|
38
|
+
left.size === right.size &&
|
|
39
|
+
left.mtimeMs === right.mtimeMs &&
|
|
40
|
+
left.ctimeMs === right.ctimeMs);
|
|
41
|
+
}
|
|
42
|
+
function readStableFile(path) {
|
|
43
|
+
for (let attempt = 1; attempt <= STABLE_READ_ATTEMPTS; attempt++) {
|
|
44
|
+
let before;
|
|
45
|
+
try {
|
|
46
|
+
before = snapshot(path);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (isErrorCode(error, "ENOENT"))
|
|
50
|
+
return undefined;
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const raw = readFileSync(path, "utf8");
|
|
55
|
+
const after = snapshot(path);
|
|
56
|
+
if (sameSnapshot(before, after))
|
|
57
|
+
return raw;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (!isErrorCode(error, "ENOENT"))
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
if (attempt < STABLE_READ_ATTEMPTS)
|
|
64
|
+
sleepSync(STABLE_READ_POLL_MS);
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Cookie-store read failed at "${path}": the file did not remain stable across ` +
|
|
67
|
+
`${STABLE_READ_ATTEMPTS} attempts. The original cookie-store file was left unchanged.`);
|
|
68
|
+
}
|
|
69
|
+
function atomicWrite(path, contents) {
|
|
70
|
+
const dir = dirname(path);
|
|
71
|
+
mkdirSync(dir, { recursive: true });
|
|
72
|
+
const temporary = join(dir, `.${basename(path)}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`);
|
|
73
|
+
try {
|
|
74
|
+
writeFileSync(temporary, contents, { mode: 0o600 });
|
|
75
|
+
renameSync(temporary, path);
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
try {
|
|
79
|
+
unlinkSync(temporary);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// A successful rename already removed the temporary path. A failed
|
|
83
|
+
// cleanup must not hide the original write error.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function withStoreLock(path, operation) {
|
|
88
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
89
|
+
const lockPath = `${path}.lock`;
|
|
90
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
91
|
+
let lockFd;
|
|
92
|
+
while (lockFd === undefined) {
|
|
93
|
+
try {
|
|
94
|
+
lockFd = openSync(lockPath, "wx", 0o600);
|
|
95
|
+
try {
|
|
96
|
+
writeFileSync(lockFd, `${JSON.stringify({ pid: process.pid, acquiredAt: new Date().toISOString() })}\n`);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
closeSync(lockFd);
|
|
100
|
+
lockFd = undefined;
|
|
101
|
+
try {
|
|
102
|
+
unlinkSync(lockPath);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Preserve the lock-write error.
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (!isErrorCode(error, "EEXIST")) {
|
|
112
|
+
if (lockFd !== undefined)
|
|
113
|
+
closeSync(lockFd);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
if (Date.now() >= deadline) {
|
|
117
|
+
throw new Error(`Cookie-store update timed out waiting for lock "${lockPath}" after ${LOCK_WAIT_MS}ms. ` +
|
|
118
|
+
"The cookie-store file was left unchanged.");
|
|
119
|
+
}
|
|
120
|
+
sleepSync(LOCK_POLL_MS);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
closeSync(lockFd);
|
|
124
|
+
try {
|
|
125
|
+
return operation();
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
try {
|
|
129
|
+
unlinkSync(lockPath);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// The update has already committed. Do not replace its result with a
|
|
133
|
+
// cleanup error; a later writer will report the exact lock path.
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
3
137
|
export class CookieJar {
|
|
4
138
|
path;
|
|
5
139
|
source;
|
|
@@ -11,11 +145,16 @@ export class CookieJar {
|
|
|
11
145
|
return existsSync(this.path);
|
|
12
146
|
}
|
|
13
147
|
load() {
|
|
14
|
-
|
|
148
|
+
const raw = readStableFile(this.path);
|
|
149
|
+
if (raw === undefined)
|
|
15
150
|
return { cookies: [], origins: [] };
|
|
151
|
+
let parsed;
|
|
152
|
+
try {
|
|
153
|
+
parsed = JSON.parse(raw);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
throw new CookieStoreParseError(this.path, error);
|
|
16
157
|
}
|
|
17
|
-
const raw = readFileSync(this.path, "utf-8");
|
|
18
|
-
const parsed = JSON.parse(raw);
|
|
19
158
|
return {
|
|
20
159
|
cookies: parsed.cookies ?? [],
|
|
21
160
|
origins: parsed.origins ?? [],
|
|
@@ -28,13 +167,26 @@ export class CookieJar {
|
|
|
28
167
|
* (constructor-provided source). Creates the parent directory if needed.
|
|
29
168
|
*/
|
|
30
169
|
save(store) {
|
|
31
|
-
|
|
170
|
+
withStoreLock(this.path, () => this.saveUnlocked(store));
|
|
171
|
+
}
|
|
172
|
+
saveUnlocked(store) {
|
|
173
|
+
const stamped = this.stamp(store);
|
|
174
|
+
atomicWrite(this.path, `${JSON.stringify(stamped, null, 2)}\n`);
|
|
175
|
+
return stamped;
|
|
176
|
+
}
|
|
177
|
+
stamp(store) {
|
|
178
|
+
return {
|
|
32
179
|
...store,
|
|
33
180
|
exportedAt: new Date().toISOString(),
|
|
34
181
|
exportedFrom: this.source,
|
|
35
182
|
};
|
|
36
|
-
|
|
37
|
-
|
|
183
|
+
}
|
|
184
|
+
update(operation) {
|
|
185
|
+
return withStoreLock(this.path, () => {
|
|
186
|
+
const updated = operation(this.load());
|
|
187
|
+
this.saveUnlocked(updated.store);
|
|
188
|
+
return updated.result;
|
|
189
|
+
});
|
|
38
190
|
}
|
|
39
191
|
/**
|
|
40
192
|
* Read + filter helper. Drops expired cookies. Optional domain filter
|
|
@@ -54,10 +206,18 @@ export class CookieJar {
|
|
|
54
206
|
* Returns the saved store.
|
|
55
207
|
*/
|
|
56
208
|
set(cookie) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
209
|
+
return this.merge([cookie]);
|
|
210
|
+
}
|
|
211
|
+
/** Merge cookies and origins in one interprocess-coordinated update. */
|
|
212
|
+
merge(cookies, origins = []) {
|
|
213
|
+
return this.update((store) => {
|
|
214
|
+
const merged = mergeCookies(store, cookies);
|
|
215
|
+
const byOrigin = new Map(store.origins.map((origin) => [origin.origin, origin]));
|
|
216
|
+
for (const origin of origins)
|
|
217
|
+
byOrigin.set(origin.origin, origin);
|
|
218
|
+
merged.origins = [...byOrigin.values()];
|
|
219
|
+
return { store: merged, result: merged };
|
|
220
|
+
});
|
|
61
221
|
}
|
|
62
222
|
/**
|
|
63
223
|
* Clear cookies. Pass `{ all: true }` to wipe everything (including
|
|
@@ -68,26 +228,29 @@ export class CookieJar {
|
|
|
68
228
|
if (!opts.domain && !opts.all) {
|
|
69
229
|
throw new Error("Specify { domain } or { all: true }");
|
|
70
230
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
231
|
+
return this.update((store) => {
|
|
232
|
+
const before = store.cookies.length;
|
|
233
|
+
if (opts.all) {
|
|
234
|
+
store.cookies = [];
|
|
235
|
+
store.origins = [];
|
|
236
|
+
}
|
|
237
|
+
else if (opts.domain) {
|
|
238
|
+
const dom = opts.domain;
|
|
239
|
+
store.cookies = store.cookies.filter((c) => !domainMatches(c.domain, dom));
|
|
240
|
+
store.origins = store.origins.filter((o) => {
|
|
241
|
+
try {
|
|
242
|
+
return !domainMatches(dom, new URL(o.origin).hostname);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
store,
|
|
251
|
+
result: { before, after: store.cookies.length },
|
|
252
|
+
};
|
|
253
|
+
});
|
|
91
254
|
}
|
|
92
255
|
/**
|
|
93
256
|
* Build a `Cookie:` header value for a URL. Only cookies that match
|
|
@@ -123,16 +286,7 @@ export class CookieJar {
|
|
|
123
286
|
this.save(store);
|
|
124
287
|
}
|
|
125
288
|
else {
|
|
126
|
-
|
|
127
|
-
const merged = mergeCookies(store, cookies);
|
|
128
|
-
if (incoming.origins) {
|
|
129
|
-
const seen = new Set(store.origins.map((o) => o.origin));
|
|
130
|
-
for (const o of incoming.origins) {
|
|
131
|
-
if (!seen.has(o.origin))
|
|
132
|
-
merged.origins.push(o);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
this.save(merged);
|
|
289
|
+
this.merge(cookies, incoming.origins ?? []);
|
|
136
290
|
}
|
|
137
291
|
return { count: cookies.length };
|
|
138
292
|
}
|
|
@@ -144,8 +298,7 @@ export class CookieJar {
|
|
|
144
298
|
exportedAt: new Date().toISOString(),
|
|
145
299
|
exportedFrom: `${this.source}-export`,
|
|
146
300
|
};
|
|
147
|
-
|
|
148
|
-
writeFileSync(filePath, `${JSON.stringify(stamped, null, 2)}\n`);
|
|
301
|
+
atomicWrite(filePath, `${JSON.stringify(stamped, null, 2)}\n`);
|
|
149
302
|
return { count: stamped.cookies.length };
|
|
150
303
|
}
|
|
151
304
|
/** Stats for the `info` command. Stable shape so callers can JSON it. */
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Cookie, CookieJar } from "./client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Host callback that can mint or refresh cookies for one request URL.
|
|
4
|
+
* Must stay synchronous: `fetch` and `browse` attach cookies before they
|
|
5
|
+
* leave this process, the same constraint as `extraHeaders`.
|
|
6
|
+
*
|
|
7
|
+
* Return cookies to add; do not mutate the jar. The caller persists them
|
|
8
|
+
* with `jar.set()` so `--no-cookies` (no jar) skips the callback entirely.
|
|
9
|
+
*/
|
|
10
|
+
export type ExtraCookies = (url: string, jar: CookieJar) => Cookie[];
|
|
11
|
+
/**
|
|
12
|
+
* Run a host `extraCookies` callback and persist whatever it returns.
|
|
13
|
+
* No-op when the callback is omitted. Order matters: this must run
|
|
14
|
+
* before `jar.header()` or Playwright `addCookies`, because an already
|
|
15
|
+
* populated `Cookie` header cannot pick up extra cookies later.
|
|
16
|
+
*/
|
|
17
|
+
export declare function applyExtraCookies(url: string, jar: CookieJar, extraCookies?: ExtraCookies): Cookie[];
|
|
18
|
+
//# sourceMappingURL=extra.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extra.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies/extra.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,KAAK,MAAM,EAAE,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,SAAS,EACd,YAAY,CAAC,EAAE,YAAY,GAC1B,MAAM,EAAE,CAKV"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a host `extraCookies` callback and persist whatever it returns.
|
|
3
|
+
* No-op when the callback is omitted. Order matters: this must run
|
|
4
|
+
* before `jar.header()` or Playwright `addCookies`, because an already
|
|
5
|
+
* populated `Cookie` header cannot pick up extra cookies later.
|
|
6
|
+
*/
|
|
7
|
+
export function applyExtraCookies(url, jar, extraCookies) {
|
|
8
|
+
if (!extraCookies)
|
|
9
|
+
return [];
|
|
10
|
+
const cookies = extraCookies(url, jar);
|
|
11
|
+
for (const cookie of cookies)
|
|
12
|
+
jar.set(cookie);
|
|
13
|
+
return cookies;
|
|
14
|
+
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { type Cookie, CookieJar, type CookieJarOptions, type CookieStore, domainMatches, type InfoResult, isExpired, matchingCookies, mergeCookies, type OriginEntry, pathMatches, } from "./client.js";
|
|
1
|
+
export { type Cookie, CookieJar, type CookieJarOptions, type CookieStore, CookieStoreParseError, domainMatches, type InfoResult, isExpired, matchingCookies, mergeCookies, type OriginEntry, pathMatches, } from "./client.js";
|
|
2
|
+
export { applyExtraCookies, type ExtraCookies } from "./extra.js";
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,aAAa,EACb,KAAK,UAAU,EACf,SAAS,EACT,eAAe,EACf,YAAY,EACZ,KAAK,WAAW,EAChB,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,qBAAqB,EACrB,aAAa,EACb,KAAK,UAAU,EACf,SAAS,EACT,eAAe,EACf,YAAY,EACZ,KAAK,WAAW,EAChB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { CookieJar, domainMatches, isExpired, matchingCookies, mergeCookies, pathMatches, } from "./client.js";
|
|
1
|
+
export { CookieJar, CookieStoreParseError, domainMatches, isExpired, matchingCookies, mergeCookies, pathMatches, } from "./client.js";
|
|
2
|
+
export { applyExtraCookies } from "./extra.js";
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
export declare const DURABLE_JOB_SCHEMA_VERSION = 1;
|
|
2
|
+
/** How often the supervisor rewrites status.json while a job runs. */
|
|
3
|
+
export declare const DURABLE_JOB_HEARTBEAT_MS = 15000;
|
|
4
|
+
/** A running job whose heartbeat is older than this earns a staleness warning,
|
|
5
|
+
* but stays "running" while its PID is alive. */
|
|
6
|
+
export declare const DURABLE_JOB_HEARTBEAT_STALE_MS = 120000;
|
|
7
|
+
export declare const DURABLE_JOB_DOCUMENT_FILENAME = "job.json";
|
|
8
|
+
export declare const DURABLE_JOB_STATUS_FILENAME = "status.json";
|
|
9
|
+
export declare const DURABLE_JOB_LOG_FILENAME = "job.log";
|
|
10
|
+
/** States a supervisor writes. "completed" is the only terminal one. */
|
|
11
|
+
export type DurableJobState = "launching" | "queued" | "running" | "completed";
|
|
12
|
+
/** States a reader can observe. "dead" is derived, never written. */
|
|
13
|
+
export type DurableJobObservedState = DurableJobState | "dead";
|
|
14
|
+
export interface DurableJobDocument {
|
|
15
|
+
schema_version: number;
|
|
16
|
+
job_id: string;
|
|
17
|
+
/** Admission resource the job queues on. */
|
|
18
|
+
resource: string;
|
|
19
|
+
/** Concurrent holders allowed on that resource. */
|
|
20
|
+
capacity: number;
|
|
21
|
+
/** Human-readable description shown in listings. */
|
|
22
|
+
label: string;
|
|
23
|
+
/** Argument vector of the wrapped command; argv[0] is the executable. */
|
|
24
|
+
argv: string[];
|
|
25
|
+
/** Directory the wrapped command runs in. */
|
|
26
|
+
cwd: string;
|
|
27
|
+
created_at: string;
|
|
28
|
+
}
|
|
29
|
+
export interface DurableJobStatus {
|
|
30
|
+
schema_version: number;
|
|
31
|
+
job_id: string;
|
|
32
|
+
/** PID of the supervisor, not of the wrapped command. */
|
|
33
|
+
pid: number;
|
|
34
|
+
state: DurableJobState;
|
|
35
|
+
started_at: string;
|
|
36
|
+
updated_at: string;
|
|
37
|
+
/** Present while the supervisor waits for an admission slot. */
|
|
38
|
+
queue?: {
|
|
39
|
+
resource: string;
|
|
40
|
+
waiting_since: string;
|
|
41
|
+
};
|
|
42
|
+
exit_code?: number | null;
|
|
43
|
+
signal?: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface DurableJobReport {
|
|
46
|
+
state: DurableJobObservedState;
|
|
47
|
+
/** The job reached "completed"; exit_code and signal are final. */
|
|
48
|
+
terminal: boolean;
|
|
49
|
+
job_id: string | null;
|
|
50
|
+
pid: number | null;
|
|
51
|
+
resource: string | null;
|
|
52
|
+
label: string | null;
|
|
53
|
+
argv: string[] | null;
|
|
54
|
+
exit_code: number | null;
|
|
55
|
+
signal: string | null;
|
|
56
|
+
created_at: string | null;
|
|
57
|
+
started_at: string | null;
|
|
58
|
+
updated_at: string | null;
|
|
59
|
+
/** now minus status.updated_at; null without a parseable heartbeat. */
|
|
60
|
+
heartbeat_age_ms: number | null;
|
|
61
|
+
queue?: {
|
|
62
|
+
resource: string;
|
|
63
|
+
waiting_since: string;
|
|
64
|
+
};
|
|
65
|
+
job_dir: string;
|
|
66
|
+
log_path: string;
|
|
67
|
+
warnings: string[];
|
|
68
|
+
}
|
|
69
|
+
export interface DurableJobDeps {
|
|
70
|
+
/** PID liveness probe (injectable for tests). Default: process.kill(pid, 0). */
|
|
71
|
+
pidAlive?: (pid: number) => boolean;
|
|
72
|
+
/** Evaluation instant in epoch milliseconds. Default: Date.now(). */
|
|
73
|
+
now?: () => number;
|
|
74
|
+
}
|
|
75
|
+
export type DurableJobClassification = {
|
|
76
|
+
ok: true;
|
|
77
|
+
report: DurableJobReport;
|
|
78
|
+
} | {
|
|
79
|
+
ok: false;
|
|
80
|
+
error: string;
|
|
81
|
+
};
|
|
82
|
+
export interface DurableJobListEntry {
|
|
83
|
+
job_id: string;
|
|
84
|
+
job_dir: string;
|
|
85
|
+
created_at: string | null;
|
|
86
|
+
document: DurableJobDocument | null;
|
|
87
|
+
report: DurableJobReport | null;
|
|
88
|
+
/** Set when the directory exists but its status document is unusable. */
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
/** Directory holding every job record under a base directory. */
|
|
92
|
+
export declare function jobsRoot(base: string): string;
|
|
93
|
+
/** Directory of one job record. Does not create it. */
|
|
94
|
+
export declare function jobDirFor(base: string, jobId: string): string;
|
|
95
|
+
/** Create (idempotently) the directory for one job and return its path. */
|
|
96
|
+
export declare function createJobDir(base: string, jobId: string): string;
|
|
97
|
+
export declare function jobLogPath(jobDir: string): string;
|
|
98
|
+
/** Write the immutable job description. */
|
|
99
|
+
export declare function writeJobDocument(jobDir: string, document: DurableJobDocument): void;
|
|
100
|
+
/** Replace the status document atomically, so a reader never sees a torn file. */
|
|
101
|
+
export declare function writeJobStatus(jobDir: string, status: DurableJobStatus): void;
|
|
102
|
+
/** Read the job description, or null when it is missing or unusable. */
|
|
103
|
+
export declare function readJobDocument(jobDir: string): DurableJobDocument | null;
|
|
104
|
+
/** Read the status document, or null when it is missing or unusable. */
|
|
105
|
+
export declare function readJobStatus(jobDir: string): DurableJobStatus | null;
|
|
106
|
+
/**
|
|
107
|
+
* Classify one job directory, fail-closed. "completed" is terminal and carries
|
|
108
|
+
* the wrapped command's exit code. Any other written state is trusted only
|
|
109
|
+
* while the supervisor PID is alive; otherwise the job is "dead" — the record
|
|
110
|
+
* outlived the process that owned it.
|
|
111
|
+
*/
|
|
112
|
+
export declare function classifyJob(jobDir: string, deps?: DurableJobDeps): DurableJobClassification;
|
|
113
|
+
/**
|
|
114
|
+
* Every job record under a base directory, newest first. Ordering keys on the
|
|
115
|
+
* description's created_at, falling back to the status document's started_at,
|
|
116
|
+
* then to the directory name, so a record missing its description still lists.
|
|
117
|
+
*/
|
|
118
|
+
export declare function listJobs(base: string, deps?: DurableJobDeps): DurableJobListEntry[];
|
|
119
|
+
/** Describe a job's outcome as a process exit code: the wrapped command's own
|
|
120
|
+
* code, 1 when it died on a signal, 4 when the record is dead. */
|
|
121
|
+
export declare function jobExitCode(report: DurableJobReport): number;
|
|
122
|
+
/** Format a duration the way the status commands do. */
|
|
123
|
+
export declare function formatJobAge(ms: number): string;
|
|
124
|
+
//# sourceMappingURL=durable-job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-job.d.ts","sourceRoot":"","sources":["../../src/lib/durable-job.ts"],"names":[],"mappings":"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"}
|