@nifrajs/coding-agent 3.2.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/EXTENSIONS.md +25 -0
- package/PERFORMANCE.md +19 -0
- package/README.md +69 -0
- package/REGISTRY.md +15 -0
- package/SECURITY.md +32 -0
- package/dist/approvals.d.ts +70 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +174 -0
- package/dist/approvals.js.map +1 -0
- package/dist/capabilities.d.ts +20 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +49 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli.d.ts +24 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +380 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +66 -0
- package/dist/context.js.map +1 -0
- package/dist/deployment-adapters.d.ts +40 -0
- package/dist/deployment-adapters.d.ts.map +1 -0
- package/dist/deployment-adapters.js +147 -0
- package/dist/deployment-adapters.js.map +1 -0
- package/dist/diff.d.ts +17 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +61 -0
- package/dist/diff.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions.d.ts +104 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +284 -0
- package/dist/extensions.js.map +1 -0
- package/dist/handoffs.d.ts +97 -0
- package/dist/handoffs.d.ts.map +1 -0
- package/dist/handoffs.js +199 -0
- package/dist/handoffs.js.map +1 -0
- package/dist/healing.d.ts +56 -0
- package/dist/healing.d.ts.map +1 -0
- package/dist/healing.js +54 -0
- package/dist/healing.js.map +1 -0
- package/dist/host.d.ts +61 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +369 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/isolated-worker.d.ts +2 -0
- package/dist/isolated-worker.d.ts.map +1 -0
- package/dist/isolated-worker.js +155 -0
- package/dist/isolated-worker.js.map +1 -0
- package/dist/isolated.d.ts +52 -0
- package/dist/isolated.d.ts.map +1 -0
- package/dist/isolated.js +293 -0
- package/dist/isolated.js.map +1 -0
- package/dist/native.d.ts +92 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +339 -0
- package/dist/native.js.map +1 -0
- package/dist/orchestration/artifact-port.d.ts +30 -0
- package/dist/orchestration/artifact-port.d.ts.map +1 -0
- package/dist/orchestration/artifact-port.js +59 -0
- package/dist/orchestration/artifact-port.js.map +1 -0
- package/dist/orchestration/catalog.d.ts +71 -0
- package/dist/orchestration/catalog.d.ts.map +1 -0
- package/dist/orchestration/catalog.js +46 -0
- package/dist/orchestration/catalog.js.map +1 -0
- package/dist/orchestration/compile.d.ts +59 -0
- package/dist/orchestration/compile.d.ts.map +1 -0
- package/dist/orchestration/compile.js +268 -0
- package/dist/orchestration/compile.js.map +1 -0
- package/dist/orchestration/dispatch.d.ts +115 -0
- package/dist/orchestration/dispatch.d.ts.map +1 -0
- package/dist/orchestration/dispatch.js +220 -0
- package/dist/orchestration/dispatch.js.map +1 -0
- package/dist/orchestration/durable-jobs.d.ts +35 -0
- package/dist/orchestration/durable-jobs.d.ts.map +1 -0
- package/dist/orchestration/durable-jobs.js +273 -0
- package/dist/orchestration/durable-jobs.js.map +1 -0
- package/dist/orchestration/effect-key.d.ts +23 -0
- package/dist/orchestration/effect-key.d.ts.map +1 -0
- package/dist/orchestration/effect-key.js +24 -0
- package/dist/orchestration/effect-key.js.map +1 -0
- package/dist/orchestration/evidence-store.d.ts +75 -0
- package/dist/orchestration/evidence-store.d.ts.map +1 -0
- package/dist/orchestration/evidence-store.js +183 -0
- package/dist/orchestration/evidence-store.js.map +1 -0
- package/dist/orchestration/hash.d.ts +12 -0
- package/dist/orchestration/hash.d.ts.map +1 -0
- package/dist/orchestration/hash.js +43 -0
- package/dist/orchestration/hash.js.map +1 -0
- package/dist/orchestration/host.d.ts +121 -0
- package/dist/orchestration/host.d.ts.map +1 -0
- package/dist/orchestration/host.js +334 -0
- package/dist/orchestration/host.js.map +1 -0
- package/dist/orchestration/index.d.ts +20 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +19 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/policy.d.ts +63 -0
- package/dist/orchestration/policy.d.ts.map +1 -0
- package/dist/orchestration/policy.js +80 -0
- package/dist/orchestration/policy.js.map +1 -0
- package/dist/orchestration/recovery.d.ts +87 -0
- package/dist/orchestration/recovery.d.ts.map +1 -0
- package/dist/orchestration/recovery.js +197 -0
- package/dist/orchestration/recovery.js.map +1 -0
- package/dist/orchestration/tracer.d.ts +31 -0
- package/dist/orchestration/tracer.d.ts.map +1 -0
- package/dist/orchestration/tracer.js +141 -0
- package/dist/orchestration/tracer.js.map +1 -0
- package/dist/plans.d.ts +35 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +63 -0
- package/dist/plans.js.map +1 -0
- package/dist/presets.d.ts +10 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +70 -0
- package/dist/presets.js.map +1 -0
- package/dist/process.d.ts +6 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +42 -0
- package/dist/process.js.map +1 -0
- package/dist/registry.d.ts +37 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +51 -0
- package/dist/registry.js.map +1 -0
- package/dist/replay.d.ts +24 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +154 -0
- package/dist/replay.js.map +1 -0
- package/dist/rpc.d.ts +51 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +412 -0
- package/dist/rpc.js.map +1 -0
- package/dist/session-migration.d.ts +59 -0
- package/dist/session-migration.d.ts.map +1 -0
- package/dist/session-migration.js +315 -0
- package/dist/session-migration.js.map +1 -0
- package/dist/sessions.d.ts +74 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +222 -0
- package/dist/sessions.js.map +1 -0
- package/dist/subagents.d.ts +51 -0
- package/dist/subagents.d.ts.map +1 -0
- package/dist/subagents.js +141 -0
- package/dist/subagents.js.map +1 -0
- package/dist/tools.d.ts +13 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +37 -0
- package/dist/tools.js.map +1 -0
- package/dist/ui.d.ts +42 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +93 -0
- package/dist/ui.js.map +1 -0
- package/dist/verification.d.ts +34 -0
- package/dist/verification.d.ts.map +1 -0
- package/dist/verification.js +91 -0
- package/dist/verification.js.map +1 -0
- package/dist/workflows.d.ts +98 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +174 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +84 -0
- package/src/approvals.ts +249 -0
- package/src/capabilities.ts +74 -0
- package/src/cli.ts +405 -0
- package/src/context.ts +81 -0
- package/src/deployment-adapters.ts +181 -0
- package/src/diff.ts +80 -0
- package/src/errors.ts +46 -0
- package/src/extensions.ts +402 -0
- package/src/handoffs.ts +299 -0
- package/src/healing.ts +93 -0
- package/src/host.ts +465 -0
- package/src/index.ts +165 -0
- package/src/isolated-worker.ts +177 -0
- package/src/isolated.ts +344 -0
- package/src/native.ts +478 -0
- package/src/orchestration/artifact-port.ts +75 -0
- package/src/orchestration/catalog.ts +102 -0
- package/src/orchestration/compile.ts +373 -0
- package/src/orchestration/dispatch.ts +383 -0
- package/src/orchestration/durable-jobs.ts +374 -0
- package/src/orchestration/effect-key.ts +35 -0
- package/src/orchestration/evidence-store.ts +233 -0
- package/src/orchestration/hash.ts +43 -0
- package/src/orchestration/host.ts +445 -0
- package/src/orchestration/index.ts +131 -0
- package/src/orchestration/policy.ts +116 -0
- package/src/orchestration/recovery.ts +271 -0
- package/src/orchestration/tracer.ts +177 -0
- package/src/plans.ts +105 -0
- package/src/presets.ts +90 -0
- package/src/process.ts +47 -0
- package/src/registry.ts +80 -0
- package/src/replay.ts +190 -0
- package/src/rpc.ts +598 -0
- package/src/session-migration.ts +401 -0
- package/src/sessions.ts +303 -0
- package/src/subagents.ts +210 -0
- package/src/tools.ts +52 -0
- package/src/ui.ts +137 -0
- package/src/verification.ts +133 -0
- package/src/workflows.ts +279 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence-only run stores. A store keeps a bounded live window of the most recent
|
|
3
|
+
* {@link RunEvidence} records, a set of order-independent aggregates (completed node ids, artifact
|
|
4
|
+
* refs, counters), and an order-independent terminal digest - never the whole stream, so a 100k-event
|
|
5
|
+
* run stays bounded in memory. Every record is re-parsed through {@link parseRunEvidence} on the way
|
|
6
|
+
* in, so a payload-bearing or oversized record cannot be written through either store: the parser is
|
|
7
|
+
* the privacy gate, not the caller's discipline.
|
|
8
|
+
*
|
|
9
|
+
* There is no dependency on `FileSessionStore` or any session machinery: these stores hold run
|
|
10
|
+
* evidence only, and the file store persists exactly the content-free record it parsed.
|
|
11
|
+
*/
|
|
12
|
+
import type { ArtifactRef, RunEvidence } from "@nifrajs/agent-protocol";
|
|
13
|
+
/** Terminal tally of a run's evidence stream. Counts only; no payloads. */
|
|
14
|
+
export interface EvidenceCounters {
|
|
15
|
+
readonly total: number;
|
|
16
|
+
readonly started: number;
|
|
17
|
+
readonly completed: number;
|
|
18
|
+
readonly failed: number;
|
|
19
|
+
}
|
|
20
|
+
/** A bounded, evidence-only run store. Append is fail-closed; reads are content-free aggregates. */
|
|
21
|
+
export interface EvidenceStore {
|
|
22
|
+
/** Parse, tally, and persist one record. Throws on a payload-bearing or oversized record. */
|
|
23
|
+
append(record: RunEvidence): Promise<void>;
|
|
24
|
+
/** Total records appended (not the live-window size). */
|
|
25
|
+
readonly count: number;
|
|
26
|
+
/** The most recent records, oldest first, capped at the configured window. */
|
|
27
|
+
live(): readonly RunEvidence[];
|
|
28
|
+
counters(): EvidenceCounters;
|
|
29
|
+
/** Distinct node ids that reached `completed`, sorted for determinism. */
|
|
30
|
+
completedNodeIds(): readonly string[];
|
|
31
|
+
/** Every artifact ref referenced by the stream, in append order. */
|
|
32
|
+
artifacts(): readonly ArtifactRef[];
|
|
33
|
+
/** Order-independent SHA-256 of the run's outcome multiset (parallel order cannot change it). */
|
|
34
|
+
digest(): Promise<string>;
|
|
35
|
+
}
|
|
36
|
+
export interface MemoryEvidenceStoreOptions {
|
|
37
|
+
/** Records retained in the live window. Older records fall out; aggregates still count them. */
|
|
38
|
+
readonly maxLive?: number;
|
|
39
|
+
}
|
|
40
|
+
/** A fully in-memory bounded store. Keeps a window plus aggregates; never the whole stream. */
|
|
41
|
+
export declare class MemoryEvidenceStore implements EvidenceStore {
|
|
42
|
+
private readonly accumulator;
|
|
43
|
+
constructor(options?: MemoryEvidenceStoreOptions);
|
|
44
|
+
append(record: RunEvidence): Promise<void>;
|
|
45
|
+
get count(): number;
|
|
46
|
+
live(): readonly RunEvidence[];
|
|
47
|
+
counters(): EvidenceCounters;
|
|
48
|
+
completedNodeIds(): readonly string[];
|
|
49
|
+
artifacts(): readonly ArtifactRef[];
|
|
50
|
+
digest(): Promise<string>;
|
|
51
|
+
}
|
|
52
|
+
export interface FileEvidenceStoreOptions {
|
|
53
|
+
/** Append-only newline-delimited file. One canonical JSON record per line, in append order. */
|
|
54
|
+
readonly path: string;
|
|
55
|
+
readonly maxLive?: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A bounded store that also appends each parsed record as one canonical-JSON line to a file, in
|
|
59
|
+
* deterministic append order. The record is normalized (and so a forbidden-content record is
|
|
60
|
+
* rejected) BEFORE the line is written, so the file never receives a payload. The append uses the
|
|
61
|
+
* `a` flag, so each record is one O_APPEND write.
|
|
62
|
+
*/
|
|
63
|
+
export declare class FileEvidenceStore implements EvidenceStore {
|
|
64
|
+
private readonly accumulator;
|
|
65
|
+
private readonly path;
|
|
66
|
+
constructor(options: FileEvidenceStoreOptions);
|
|
67
|
+
append(record: RunEvidence): Promise<void>;
|
|
68
|
+
get count(): number;
|
|
69
|
+
live(): readonly RunEvidence[];
|
|
70
|
+
counters(): EvidenceCounters;
|
|
71
|
+
completedNodeIds(): readonly string[];
|
|
72
|
+
artifacts(): readonly ArtifactRef[];
|
|
73
|
+
digest(): Promise<string>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=evidence-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-store.d.ts","sourceRoot":"","sources":["../../src/orchestration/evidence-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAIvE,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC5B,6FAA6F;IAC7F,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,8EAA8E;IAC9E,IAAI,IAAI,SAAS,WAAW,EAAE,CAAA;IAC9B,QAAQ,IAAI,gBAAgB,CAAA;IAC5B,0EAA0E;IAC1E,gBAAgB,IAAI,SAAS,MAAM,EAAE,CAAA;IACrC,oEAAoE;IACpE,SAAS,IAAI,SAAS,WAAW,EAAE,CAAA;IACnC,iGAAiG;IACjG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAC1B;AA8GD,MAAM,WAAW,0BAA0B;IACzC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,+FAA+F;AAC/F,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;gBAErC,OAAO,GAAE,0BAA+B;IAI9C,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,IAAI,SAAS,WAAW,EAAE;IAG9B,QAAQ,IAAI,gBAAgB;IAG5B,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAGrC,SAAS,IAAI,SAAS,WAAW,EAAE;IAG7B,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CAGhC;AAED,MAAM,WAAW,wBAAwB;IACvC,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAEjB,OAAO,EAAE,wBAAwB;IAKvC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,IAAI,SAAS,WAAW,EAAE;IAG9B,QAAQ,IAAI,gBAAgB;IAG5B,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAGrC,SAAS,IAAI,SAAS,WAAW,EAAE;IAG7B,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CAGhC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence-only run stores. A store keeps a bounded live window of the most recent
|
|
3
|
+
* {@link RunEvidence} records, a set of order-independent aggregates (completed node ids, artifact
|
|
4
|
+
* refs, counters), and an order-independent terminal digest - never the whole stream, so a 100k-event
|
|
5
|
+
* run stays bounded in memory. Every record is re-parsed through {@link parseRunEvidence} on the way
|
|
6
|
+
* in, so a payload-bearing or oversized record cannot be written through either store: the parser is
|
|
7
|
+
* the privacy gate, not the caller's discipline.
|
|
8
|
+
*
|
|
9
|
+
* There is no dependency on `FileSessionStore` or any session machinery: these stores hold run
|
|
10
|
+
* evidence only, and the file store persists exactly the content-free record it parsed.
|
|
11
|
+
*/
|
|
12
|
+
import { appendFile } from "node:fs/promises";
|
|
13
|
+
import { assertEvidenceSize, parseRunEvidence } from "@nifrajs/agent-protocol";
|
|
14
|
+
import { canonicalJson } from "./hash.js";
|
|
15
|
+
const DEFAULT_MAX_LIVE = 1024;
|
|
16
|
+
const encoder = new TextEncoder();
|
|
17
|
+
async function sha256Bytes(text) {
|
|
18
|
+
const digest = await crypto.subtle.digest("SHA-256", encoder.encode(text));
|
|
19
|
+
return new Uint8Array(digest);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The identity of one record for the terminal digest: node outcome only. `seq`, `durationMs`, and
|
|
23
|
+
* `runId` are excluded so two runs of the same plan (or the same plan under a different parallel
|
|
24
|
+
* schedule) produce an identical digest - the deterministic-eval anchor. Each node emits at most one
|
|
25
|
+
* record per status, so XOR accumulation never cancels a distinct outcome.
|
|
26
|
+
*/
|
|
27
|
+
function digestKey(record) {
|
|
28
|
+
return canonicalJson({
|
|
29
|
+
planDigest: record.planDigest,
|
|
30
|
+
nodeId: record.nodeId,
|
|
31
|
+
status: record.status,
|
|
32
|
+
idempotent: record.idempotent,
|
|
33
|
+
...(record.errorCode !== undefined ? { errorCode: record.errorCode } : {}),
|
|
34
|
+
...(record.effectKey !== undefined ? { effectKey: record.effectKey } : {}),
|
|
35
|
+
...(record.artifacts !== undefined ? { artifacts: record.artifacts } : {}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Shared accumulator: bounded ring window plus order-independent aggregates. No payload retained. */
|
|
39
|
+
class EvidenceAccumulator {
|
|
40
|
+
max;
|
|
41
|
+
buf = [];
|
|
42
|
+
head = 0;
|
|
43
|
+
filled = false;
|
|
44
|
+
acc = new Uint8Array(32);
|
|
45
|
+
completed = new Set();
|
|
46
|
+
artifactRefs = [];
|
|
47
|
+
totalCount = 0;
|
|
48
|
+
startedCount = 0;
|
|
49
|
+
completedCount = 0;
|
|
50
|
+
failedCount = 0;
|
|
51
|
+
constructor(maxLive) {
|
|
52
|
+
if (!Number.isSafeInteger(maxLive) || maxLive < 0)
|
|
53
|
+
throw new RangeError("evidence store: maxLive must be a non-negative integer");
|
|
54
|
+
this.max = maxLive;
|
|
55
|
+
}
|
|
56
|
+
/** `record` is already parsed and within the size cap. */
|
|
57
|
+
async add(record) {
|
|
58
|
+
this.totalCount++;
|
|
59
|
+
if (record.status === "started")
|
|
60
|
+
this.startedCount++;
|
|
61
|
+
else if (record.status === "completed") {
|
|
62
|
+
this.completedCount++;
|
|
63
|
+
this.completed.add(record.nodeId);
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
this.failedCount++;
|
|
67
|
+
if (record.artifacts !== undefined)
|
|
68
|
+
for (const ref of record.artifacts)
|
|
69
|
+
this.artifactRefs.push(ref);
|
|
70
|
+
const hash = await sha256Bytes(digestKey(record));
|
|
71
|
+
for (let i = 0; i < 32; i++)
|
|
72
|
+
this.acc[i] = this.acc[i] ^ hash[i];
|
|
73
|
+
this.pushLive(record);
|
|
74
|
+
}
|
|
75
|
+
pushLive(record) {
|
|
76
|
+
if (this.max === 0)
|
|
77
|
+
return;
|
|
78
|
+
this.buf[this.head] = record;
|
|
79
|
+
this.head = (this.head + 1) % this.max;
|
|
80
|
+
if (this.head === 0)
|
|
81
|
+
this.filled = true;
|
|
82
|
+
}
|
|
83
|
+
get count() {
|
|
84
|
+
return this.totalCount;
|
|
85
|
+
}
|
|
86
|
+
live() {
|
|
87
|
+
if (!this.filled)
|
|
88
|
+
return this.buf.slice(0, this.head);
|
|
89
|
+
return [...this.buf.slice(this.head), ...this.buf.slice(0, this.head)];
|
|
90
|
+
}
|
|
91
|
+
counters() {
|
|
92
|
+
return {
|
|
93
|
+
total: this.totalCount,
|
|
94
|
+
started: this.startedCount,
|
|
95
|
+
completed: this.completedCount,
|
|
96
|
+
failed: this.failedCount,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
completedNodeIds() {
|
|
100
|
+
return [...this.completed].sort();
|
|
101
|
+
}
|
|
102
|
+
artifacts() {
|
|
103
|
+
return [...this.artifactRefs];
|
|
104
|
+
}
|
|
105
|
+
digest() {
|
|
106
|
+
let hex = "";
|
|
107
|
+
for (let i = 0; i < 32; i++)
|
|
108
|
+
hex += this.acc[i].toString(16).padStart(2, "0");
|
|
109
|
+
return hex;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Normalize on the way in: re-parse (content-free gate) then re-check the size cap. */
|
|
113
|
+
function normalize(record) {
|
|
114
|
+
const parsed = parseRunEvidence(record);
|
|
115
|
+
assertEvidenceSize(parsed);
|
|
116
|
+
return parsed;
|
|
117
|
+
}
|
|
118
|
+
/** A fully in-memory bounded store. Keeps a window plus aggregates; never the whole stream. */
|
|
119
|
+
export class MemoryEvidenceStore {
|
|
120
|
+
accumulator;
|
|
121
|
+
constructor(options = {}) {
|
|
122
|
+
this.accumulator = new EvidenceAccumulator(options.maxLive ?? DEFAULT_MAX_LIVE);
|
|
123
|
+
}
|
|
124
|
+
async append(record) {
|
|
125
|
+
await this.accumulator.add(normalize(record));
|
|
126
|
+
}
|
|
127
|
+
get count() {
|
|
128
|
+
return this.accumulator.count;
|
|
129
|
+
}
|
|
130
|
+
live() {
|
|
131
|
+
return this.accumulator.live();
|
|
132
|
+
}
|
|
133
|
+
counters() {
|
|
134
|
+
return this.accumulator.counters();
|
|
135
|
+
}
|
|
136
|
+
completedNodeIds() {
|
|
137
|
+
return this.accumulator.completedNodeIds();
|
|
138
|
+
}
|
|
139
|
+
artifacts() {
|
|
140
|
+
return this.accumulator.artifacts();
|
|
141
|
+
}
|
|
142
|
+
async digest() {
|
|
143
|
+
return this.accumulator.digest();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A bounded store that also appends each parsed record as one canonical-JSON line to a file, in
|
|
148
|
+
* deterministic append order. The record is normalized (and so a forbidden-content record is
|
|
149
|
+
* rejected) BEFORE the line is written, so the file never receives a payload. The append uses the
|
|
150
|
+
* `a` flag, so each record is one O_APPEND write.
|
|
151
|
+
*/
|
|
152
|
+
export class FileEvidenceStore {
|
|
153
|
+
accumulator;
|
|
154
|
+
path;
|
|
155
|
+
constructor(options) {
|
|
156
|
+
this.path = options.path;
|
|
157
|
+
this.accumulator = new EvidenceAccumulator(options.maxLive ?? DEFAULT_MAX_LIVE);
|
|
158
|
+
}
|
|
159
|
+
async append(record) {
|
|
160
|
+
const parsed = normalize(record);
|
|
161
|
+
await this.accumulator.add(parsed);
|
|
162
|
+
await appendFile(this.path, `${canonicalJson(parsed)}\n`, { flag: "a" });
|
|
163
|
+
}
|
|
164
|
+
get count() {
|
|
165
|
+
return this.accumulator.count;
|
|
166
|
+
}
|
|
167
|
+
live() {
|
|
168
|
+
return this.accumulator.live();
|
|
169
|
+
}
|
|
170
|
+
counters() {
|
|
171
|
+
return this.accumulator.counters();
|
|
172
|
+
}
|
|
173
|
+
completedNodeIds() {
|
|
174
|
+
return this.accumulator.completedNodeIds();
|
|
175
|
+
}
|
|
176
|
+
artifacts() {
|
|
177
|
+
return this.accumulator.artifacts();
|
|
178
|
+
}
|
|
179
|
+
async digest() {
|
|
180
|
+
return this.accumulator.digest();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=evidence-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-store.js","sourceRoot":"","sources":["../../src/orchestration/evidence-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressing helpers shared by the orchestration module: a SHA-256 hex digest over bytes
|
|
3
|
+
* and a canonical JSON encoding with sorted object keys so a digest is stable across key order.
|
|
4
|
+
* Mirrors `@nifrajs/core`'s idempotency fingerprint (the content-free key precedent).
|
|
5
|
+
*/
|
|
6
|
+
/** SHA-256 of `bytes` as lowercase hex. Collision-resistant so a digest cannot be forged from content. */
|
|
7
|
+
export declare function sha256Hex(bytes: Uint8Array): Promise<string>;
|
|
8
|
+
/** SHA-256 hex of a UTF-8 string. */
|
|
9
|
+
export declare function sha256HexOf(text: string): Promise<string>;
|
|
10
|
+
/** Deterministic JSON with recursively sorted object keys. Arrays keep order. Rejects non-finite numbers. */
|
|
11
|
+
export declare function canonicalJson(value: unknown): string;
|
|
12
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/orchestration/hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,0GAA0G;AAC1G,wBAAsB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlE;AAED,qCAAqC;AACrC,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzD;AAED,6GAA6G;AAC7G,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressing helpers shared by the orchestration module: a SHA-256 hex digest over bytes
|
|
3
|
+
* and a canonical JSON encoding with sorted object keys so a digest is stable across key order.
|
|
4
|
+
* Mirrors `@nifrajs/core`'s idempotency fingerprint (the content-free key precedent).
|
|
5
|
+
*/
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
/** SHA-256 of `bytes` as lowercase hex. Collision-resistant so a digest cannot be forged from content. */
|
|
8
|
+
export async function sha256Hex(bytes) {
|
|
9
|
+
// Copy into a fresh ArrayBuffer-backed view so the digest input is a concrete BufferSource
|
|
10
|
+
// regardless of the caller's backing buffer (SharedArrayBuffer-typed views are rejected).
|
|
11
|
+
const digest = await crypto.subtle.digest("SHA-256", new Uint8Array(bytes));
|
|
12
|
+
const view = new Uint8Array(digest);
|
|
13
|
+
let hex = "";
|
|
14
|
+
for (let i = 0; i < view.length; i++)
|
|
15
|
+
hex += view[i].toString(16).padStart(2, "0");
|
|
16
|
+
return hex;
|
|
17
|
+
}
|
|
18
|
+
/** SHA-256 hex of a UTF-8 string. */
|
|
19
|
+
export function sha256HexOf(text) {
|
|
20
|
+
return sha256Hex(encoder.encode(text));
|
|
21
|
+
}
|
|
22
|
+
/** Deterministic JSON with recursively sorted object keys. Arrays keep order. Rejects non-finite numbers. */
|
|
23
|
+
export function canonicalJson(value) {
|
|
24
|
+
if (value === null || typeof value === "boolean" || typeof value === "string") {
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === "number") {
|
|
28
|
+
if (!Number.isFinite(value))
|
|
29
|
+
throw new TypeError("non-finite JSON number");
|
|
30
|
+
return JSON.stringify(value);
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(value))
|
|
33
|
+
return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
|
|
34
|
+
if (typeof value === "object") {
|
|
35
|
+
const record = value;
|
|
36
|
+
const keys = Object.keys(record)
|
|
37
|
+
.filter((key) => record[key] !== undefined)
|
|
38
|
+
.sort();
|
|
39
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
|
|
40
|
+
}
|
|
41
|
+
throw new TypeError(`cannot canonicalize ${typeof value}`);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/orchestration/hash.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;AAEjC,0GAA0G;AAC1G,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAiB;IAC/C,2FAA2F;IAC3F,0FAA0F;IAC1F,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3E,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;IACnC,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,IAAK,IAAI,CAAC,CAAC,CAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC9F,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9E,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAA;QAC1E,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IAC1F,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAgC,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aAC7B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;aAC1C,IAAI,EAAE,CAAA;QACT,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;IACnG,CAAC;IACD,MAAM,IAAI,SAAS,CAAC,uBAAuB,OAAO,KAAK,EAAE,CAAC,CAAA;AAC5D,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OrchestrationHost: the lifecycle owner for a compiled {@link RunPlan}. It does not schedule
|
|
3
|
+
* work itself - each top-level DAG layer is handed to a kernel {@link WorkflowRunner}, exactly as
|
|
4
|
+
* {@link compileRunPlan} would fold them into one `sequence`. Driving layer by layer gives a safe
|
|
5
|
+
* pause boundary (in-flight nodes finish; no new layer starts) and a cancellation seam (the layer's
|
|
6
|
+
* runner and any bounded subagent share the run's abort signal) without a second engine.
|
|
7
|
+
*
|
|
8
|
+
* Every transition is guarded by an explicit state machine: an illegal transition returns a stable
|
|
9
|
+
* code and mutates nothing. A terminal run is frozen - a late completion from an aborted layer
|
|
10
|
+
* cannot change its status, counters, or digest. Terminal results expose status, completed node ids,
|
|
11
|
+
* an order-independent evidence digest, artifact refs, counters, and a failure code only: never a
|
|
12
|
+
* step output, prompt, or payload.
|
|
13
|
+
*/
|
|
14
|
+
import type { CapabilityDescriptor } from "@nifrajs/agent/registry";
|
|
15
|
+
import type { ArtifactPort, ArtifactRef, RunPlan } from "@nifrajs/agent-protocol";
|
|
16
|
+
import type { StepCatalog } from "./catalog.js";
|
|
17
|
+
import { type OrchestrationLimits } from "./compile.js";
|
|
18
|
+
import { type EvidenceCounters, type EvidenceStore } from "./evidence-store.js";
|
|
19
|
+
import { type HostPolicy } from "./policy.js";
|
|
20
|
+
export type RunState = "submitted" | "running" | "paused" | "succeeded" | "failed" | "cancelled";
|
|
21
|
+
/** Thrown on an illegal lifecycle transition or an unknown run. `code` is stable. */
|
|
22
|
+
export declare class OrchestrationStateError extends Error {
|
|
23
|
+
readonly code: string;
|
|
24
|
+
constructor(reason: string, code: string);
|
|
25
|
+
}
|
|
26
|
+
/** Content-free progress view of a run. */
|
|
27
|
+
export interface RunStatus {
|
|
28
|
+
readonly runId: string;
|
|
29
|
+
readonly state: RunState;
|
|
30
|
+
readonly planDigest: string;
|
|
31
|
+
readonly layerIndex: number;
|
|
32
|
+
readonly layerCount: number;
|
|
33
|
+
readonly counters: EvidenceCounters;
|
|
34
|
+
}
|
|
35
|
+
/** Deterministic terminal result. Outcome identity only - no step output, prompt, or payload. */
|
|
36
|
+
export interface RunResult {
|
|
37
|
+
readonly runId: string;
|
|
38
|
+
readonly status: "succeeded" | "failed" | "cancelled";
|
|
39
|
+
readonly planDigest: string;
|
|
40
|
+
readonly completedNodeIds: readonly string[];
|
|
41
|
+
readonly evidenceDigest: string;
|
|
42
|
+
readonly artifacts: readonly ArtifactRef[];
|
|
43
|
+
readonly counters: EvidenceCounters;
|
|
44
|
+
readonly failureCode?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface SubmitOptions {
|
|
47
|
+
/** Caller-supplied for reproducibility; defaults to a per-host monotonic id (no clock, no random). */
|
|
48
|
+
readonly runId?: string;
|
|
49
|
+
/** Caller-owned payload sink. Defaults to hash-and-discard. */
|
|
50
|
+
readonly artifactPort?: ArtifactPort;
|
|
51
|
+
/** Evidence store for this run. Defaults to a bounded {@link MemoryEvidenceStore}. */
|
|
52
|
+
readonly store?: EvidenceStore;
|
|
53
|
+
}
|
|
54
|
+
export interface OrchestrationHostOptions {
|
|
55
|
+
readonly catalog: StepCatalog;
|
|
56
|
+
readonly limits?: OrchestrationLimits;
|
|
57
|
+
/** Kernel step ceiling per layer. Generous by default so a full 256-node layer runs. */
|
|
58
|
+
readonly maxSteps?: number;
|
|
59
|
+
readonly maxDepth?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Authoritative admission policy. When set, {@link OrchestrationHost.admit} refuses any capability
|
|
62
|
+
* descriptor that asks to run outside the policy's kinds, capability allowlist, isolation floor, or
|
|
63
|
+
* approval requirement. A descriptor, plan, model, or extension cannot override it.
|
|
64
|
+
*/
|
|
65
|
+
readonly policy?: HostPolicy;
|
|
66
|
+
}
|
|
67
|
+
/** Owns run lifecycle and evidence projection over the kernel WorkflowRunner. */
|
|
68
|
+
export declare class OrchestrationHost {
|
|
69
|
+
private readonly catalog;
|
|
70
|
+
private readonly limits;
|
|
71
|
+
private readonly maxSteps;
|
|
72
|
+
private readonly maxDepth;
|
|
73
|
+
private readonly policy;
|
|
74
|
+
private readonly vectors;
|
|
75
|
+
private readonly runs;
|
|
76
|
+
private counter;
|
|
77
|
+
constructor(options: OrchestrationHostOptions);
|
|
78
|
+
/**
|
|
79
|
+
* Admit a capability descriptor against the host policy before it can be invoked. Throws
|
|
80
|
+
* {@link OrchestrationStateError} (`E_POLICY_REJECTED`) carrying the admission reason when refused.
|
|
81
|
+
* With no policy configured this is a passthrough - the host admits nothing it is not told to gate.
|
|
82
|
+
*/
|
|
83
|
+
admit(descriptor: CapabilityDescriptor): void;
|
|
84
|
+
/**
|
|
85
|
+
* Allocate the next monotonic child vector for a live run, addressing a decision boundary the run
|
|
86
|
+
* pauses on. Strictly increasing per run, so a decision carrying any other vector is provably stale.
|
|
87
|
+
*/
|
|
88
|
+
openBoundaryVector(runId: string): number;
|
|
89
|
+
/**
|
|
90
|
+
* Parse, compile, and register a run in `submitted`. All structural ceilings and capability
|
|
91
|
+
* authority are enforced here (a `CompileError` with a stable code), so an over-limit or
|
|
92
|
+
* unauthorized plan never reaches `running`.
|
|
93
|
+
*/
|
|
94
|
+
submit(source: RunPlan | unknown, options?: SubmitOptions): Promise<string>;
|
|
95
|
+
/** Content-free progress view. Throws `E_NOT_FOUND` for an unknown run. */
|
|
96
|
+
inspect(runId: string): RunStatus;
|
|
97
|
+
/** `submitted` -> `running`. Begins the driver. */
|
|
98
|
+
start(runId: string): void;
|
|
99
|
+
/** `running` -> `paused`. Takes effect at the next layer boundary; in-flight nodes finish. */
|
|
100
|
+
pause(runId: string): void;
|
|
101
|
+
/** `paused` -> `running`. Releases the layer boundary. */
|
|
102
|
+
resume(runId: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* Cancel from any non-terminal state. Aborts the in-flight layer and any bounded subagent, frees a
|
|
105
|
+
* paused gate, and freezes the run in `cancelled`. A late completion cannot revive it.
|
|
106
|
+
*/
|
|
107
|
+
cancel(runId: string): void;
|
|
108
|
+
/** Terminal result. Throws `E_NOT_TERMINAL` while the run is still live. */
|
|
109
|
+
result(runId: string): Promise<RunResult>;
|
|
110
|
+
/** Await the run reaching a terminal state, then return its result. */
|
|
111
|
+
settled(runId: string): Promise<RunResult>;
|
|
112
|
+
private require;
|
|
113
|
+
private transition;
|
|
114
|
+
private buildResult;
|
|
115
|
+
private drive;
|
|
116
|
+
/** Project one kernel event into a content-free evidence record. Frozen once the run is terminal. */
|
|
117
|
+
private project;
|
|
118
|
+
/** Walk the plan tree once: node kinds, idempotency flags, and the full id set. */
|
|
119
|
+
private indexPlan;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/orchestration/host.ts"],"names":[],"mappings":"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"}
|