@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 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../src/orchestration/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovery state machine for at-least-once node dispatch.
|
|
3
|
+
*
|
|
4
|
+
* The machine treats every effect invocation as potentially side-effecting. A normal retry is
|
|
5
|
+
* allowed only for an explicit pre-effect rejection. Once an effect has been invoked, recovery
|
|
6
|
+
* requires a matching idempotency proof; without one it dead-letters the dispatch instead of
|
|
7
|
+
* guessing that a duplicate is safe. This is deliberately conservative and never claims exactly
|
|
8
|
+
* once delivery or hostile-code isolation.
|
|
9
|
+
*/
|
|
10
|
+
import { systemClock, } from "./dispatch.js";
|
|
11
|
+
/** Disposable proof reference for tests and one-process local runs. */
|
|
12
|
+
export class MemoryIdempotencyProofStore {
|
|
13
|
+
keys = new Set();
|
|
14
|
+
has(key) {
|
|
15
|
+
return this.keys.has(key);
|
|
16
|
+
}
|
|
17
|
+
record(key) {
|
|
18
|
+
this.keys.add(key);
|
|
19
|
+
}
|
|
20
|
+
keysSnapshot() {
|
|
21
|
+
return Object.freeze([...this.keys].sort());
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Stable pre-effect failure; it may be retried with a new logical attempt. */
|
|
25
|
+
export class EffectRejectedError extends Error {
|
|
26
|
+
code;
|
|
27
|
+
constructor(code = "effect_rejected") {
|
|
28
|
+
super("run effect was rejected before the side effect boundary");
|
|
29
|
+
this.name = "EffectRejectedError";
|
|
30
|
+
this.code = code;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Simulates worker loss at a named boundary; the lease is intentionally left unresolved. */
|
|
34
|
+
export class RecoveryCrashError extends Error {
|
|
35
|
+
boundary;
|
|
36
|
+
constructor(boundary) {
|
|
37
|
+
super("worker stopped at a recovery boundary");
|
|
38
|
+
this.name = "RecoveryCrashError";
|
|
39
|
+
this.boundary = boundary;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const DEFAULT_LEASE_MS = 30_000;
|
|
43
|
+
const DEFAULT_BACKOFF = (attempt) => Math.min(1_000 * Math.max(1, attempt), 60_000);
|
|
44
|
+
function stableCode(error) {
|
|
45
|
+
if (error instanceof EffectRejectedError)
|
|
46
|
+
return error.code;
|
|
47
|
+
if (error instanceof RecoveryCrashError)
|
|
48
|
+
return `worker_${error.boundary.replaceAll("-", "_")}`;
|
|
49
|
+
return "effect_failed";
|
|
50
|
+
}
|
|
51
|
+
function isAbort(signal, error) {
|
|
52
|
+
return signal.aborted || (error instanceof DOMException && error.name === "AbortError");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Drives leases through safe checkpoints and terminal transitions. The caller owns the effect and
|
|
56
|
+
* any real idempotency ledger; this class stores only opaque proof keys in the reference adapter.
|
|
57
|
+
*/
|
|
58
|
+
export class RunRecoveryMachine {
|
|
59
|
+
store;
|
|
60
|
+
clock;
|
|
61
|
+
proofs;
|
|
62
|
+
leaseMs;
|
|
63
|
+
retryBackoff;
|
|
64
|
+
signal;
|
|
65
|
+
constructor(options) {
|
|
66
|
+
this.store = options.store;
|
|
67
|
+
this.clock = options.clock ?? systemClock;
|
|
68
|
+
this.proofs = options.proofStore ?? new MemoryIdempotencyProofStore();
|
|
69
|
+
this.leaseMs = options.leaseMs ?? DEFAULT_LEASE_MS;
|
|
70
|
+
this.retryBackoff = options.retryBackoff ?? DEFAULT_BACKOFF;
|
|
71
|
+
this.signal = options.signal ?? new AbortController().signal;
|
|
72
|
+
if (!Number.isFinite(this.leaseMs) || this.leaseMs <= 0)
|
|
73
|
+
throw new RangeError("recovery leaseMs must be positive");
|
|
74
|
+
}
|
|
75
|
+
/** Cancel all matching run dispatches; every late lease write then fails closed. */
|
|
76
|
+
async cancel(runId) {
|
|
77
|
+
return await this.store.cancel(runId, "cancelled");
|
|
78
|
+
}
|
|
79
|
+
/** Process one bounded lease batch. No payload is read or emitted by this coordinator. */
|
|
80
|
+
async process(effect, options = {}) {
|
|
81
|
+
const limit = options.limit ?? 1;
|
|
82
|
+
const leases = await this.store.lease(this.clock.now(), limit, this.leaseMs);
|
|
83
|
+
const summary = {
|
|
84
|
+
leased: leases.length,
|
|
85
|
+
completed: 0,
|
|
86
|
+
retried: 0,
|
|
87
|
+
deadLettered: 0,
|
|
88
|
+
cancelled: 0,
|
|
89
|
+
};
|
|
90
|
+
for (const lease of leases) {
|
|
91
|
+
const outcome = await this.processLease(lease, effect);
|
|
92
|
+
summary.completed += outcome === "completed" ? 1 : 0;
|
|
93
|
+
summary.retried += outcome === "retried" ? 1 : 0;
|
|
94
|
+
summary.deadLettered += outcome === "dead-lettered" ? 1 : 0;
|
|
95
|
+
summary.cancelled += outcome === "cancelled" ? 1 : 0;
|
|
96
|
+
}
|
|
97
|
+
return Object.freeze(summary);
|
|
98
|
+
}
|
|
99
|
+
async processLease(lease, effect) {
|
|
100
|
+
const signal = this.signal;
|
|
101
|
+
if (signal.aborted) {
|
|
102
|
+
await this.store.cancel(lease.dispatch.runId, "cancelled");
|
|
103
|
+
return "cancelled";
|
|
104
|
+
}
|
|
105
|
+
const inspection = await this.store.inspect(lease.dispatch.dispatchId);
|
|
106
|
+
const checkpoint = inspection?.checkpoint;
|
|
107
|
+
const proof = await this.proofs.has(lease.idempotencyKey);
|
|
108
|
+
if (proof || checkpoint?.boundary === "after-effect") {
|
|
109
|
+
if (!proof) {
|
|
110
|
+
await this.store.deadLetter(lease, "idempotency_required");
|
|
111
|
+
return "dead-lettered";
|
|
112
|
+
}
|
|
113
|
+
const completed = await this.store.complete(lease);
|
|
114
|
+
return completed.ok ? "completed" : "waiting";
|
|
115
|
+
}
|
|
116
|
+
const before = await this.storeCheckpoint(lease, "before-effect");
|
|
117
|
+
if (!before)
|
|
118
|
+
return "waiting";
|
|
119
|
+
if (signal.aborted) {
|
|
120
|
+
await this.store.cancel(lease.dispatch.runId, "cancelled");
|
|
121
|
+
return "cancelled";
|
|
122
|
+
}
|
|
123
|
+
let invoked = false;
|
|
124
|
+
try {
|
|
125
|
+
invoked = true;
|
|
126
|
+
const committed = await effect({
|
|
127
|
+
lease,
|
|
128
|
+
signal,
|
|
129
|
+
checkpoint: (boundary) => this.storeCheckpoint(lease, boundary),
|
|
130
|
+
});
|
|
131
|
+
if (committed.committed !== true) {
|
|
132
|
+
await this.store.deadLetter(lease, "idempotency_required");
|
|
133
|
+
return "dead-lettered";
|
|
134
|
+
}
|
|
135
|
+
await this.proofs.record(lease.idempotencyKey);
|
|
136
|
+
const after = await this.storeCheckpoint(lease, "after-effect");
|
|
137
|
+
if (!after)
|
|
138
|
+
return "waiting";
|
|
139
|
+
const completed = await this.store.complete(lease);
|
|
140
|
+
return completed.ok ? "completed" : "waiting";
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (error instanceof RecoveryCrashError)
|
|
144
|
+
return "waiting";
|
|
145
|
+
if (isAbort(signal, error)) {
|
|
146
|
+
await this.store.cancel(lease.dispatch.runId, "cancelled");
|
|
147
|
+
return "cancelled";
|
|
148
|
+
}
|
|
149
|
+
const failure = stableCode(error);
|
|
150
|
+
if (invoked && !(error instanceof EffectRejectedError)) {
|
|
151
|
+
// The effect boundary was crossed, so a retry would be an unproven duplicate.
|
|
152
|
+
await this.store.deadLetter(lease, "idempotency_required");
|
|
153
|
+
return "dead-lettered";
|
|
154
|
+
}
|
|
155
|
+
if (lease.attempt >= lease.dispatch.maxAttempts) {
|
|
156
|
+
await this.store.deadLetter(lease, failure);
|
|
157
|
+
return "dead-lettered";
|
|
158
|
+
}
|
|
159
|
+
const delay = this.retryBackoff(lease.attempt);
|
|
160
|
+
if (!Number.isFinite(delay) || delay < 0)
|
|
161
|
+
throw new RangeError("recovery retry backoff is invalid");
|
|
162
|
+
const retried = await this.store.retry(lease, this.clock.now() + Math.min(delay, 86_400_000), failure);
|
|
163
|
+
return retried.ok ? "retried" : "waiting";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async storeCheckpoint(lease, boundary) {
|
|
167
|
+
const outcome = await this.store.checkpoint(lease, {
|
|
168
|
+
version: 1,
|
|
169
|
+
dispatchId: lease.dispatch.dispatchId,
|
|
170
|
+
runId: lease.dispatch.runId,
|
|
171
|
+
nodeId: lease.dispatch.nodeId,
|
|
172
|
+
attempt: lease.attempt,
|
|
173
|
+
generation: lease.generation,
|
|
174
|
+
boundary,
|
|
175
|
+
idempotencyKey: lease.idempotencyKey,
|
|
176
|
+
at: this.clock.now(),
|
|
177
|
+
scheduleToken: lease.scheduleToken,
|
|
178
|
+
});
|
|
179
|
+
return outcome.ok;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** A small deterministic clock useful for recovery schedules and tests. */
|
|
183
|
+
export class TestClock {
|
|
184
|
+
current;
|
|
185
|
+
constructor(start = 0) {
|
|
186
|
+
if (!Number.isSafeInteger(start) || start < 0)
|
|
187
|
+
throw new RangeError("test clock start is invalid");
|
|
188
|
+
this.current = start;
|
|
189
|
+
}
|
|
190
|
+
now = () => this.current;
|
|
191
|
+
advance(milliseconds) {
|
|
192
|
+
if (!Number.isSafeInteger(milliseconds) || milliseconds < 0)
|
|
193
|
+
throw new RangeError("test clock advance is invalid");
|
|
194
|
+
this.current += milliseconds;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/orchestration/recovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The end-to-end tracer: compile a {@link RunPlan}, run it through the {@link WorkflowRunner}, and
|
|
3
|
+
* project each transition into content-free {@link RunEvidence}. Every emitted record is re-parsed
|
|
4
|
+
* through {@link parseRunEvidence}, so the tracer itself proves the stream carries no payload and
|
|
5
|
+
* stays under the size cap. The terminal digest is a deterministic hash of the evidence stream:
|
|
6
|
+
* identical plan + catalog + inputs yield an identical digest, which is the deterministic-eval anchor.
|
|
7
|
+
*/
|
|
8
|
+
import type { ArtifactPort, RunEvidence, RunPlan } from "@nifrajs/agent-protocol";
|
|
9
|
+
import type { StepCatalog } from "./catalog.js";
|
|
10
|
+
export interface RunTraceOptions {
|
|
11
|
+
/** Caller-supplied, so a trace is fully reproducible. No clock or randomness is read here. */
|
|
12
|
+
readonly runId: string;
|
|
13
|
+
readonly catalog: StepCatalog;
|
|
14
|
+
/** Defaults to {@link noopArtifactPort} (hash-and-discard). */
|
|
15
|
+
readonly artifactPort?: ArtifactPort;
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
readonly maxSteps?: number;
|
|
18
|
+
readonly maxDepth?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface RunTraceResult {
|
|
21
|
+
readonly ok: boolean;
|
|
22
|
+
readonly runId: string;
|
|
23
|
+
readonly planDigest: string;
|
|
24
|
+
readonly evidence: readonly RunEvidence[];
|
|
25
|
+
/** SHA-256 hex of the canonical evidence stream. Deterministic across identical runs. */
|
|
26
|
+
readonly terminalDigest: string;
|
|
27
|
+
readonly error?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Run a plan and return its content-free evidence stream plus a deterministic terminal digest. */
|
|
30
|
+
export declare function runTrace(source: RunPlan | unknown, options: RunTraceOptions): Promise<RunTraceResult>;
|
|
31
|
+
//# sourceMappingURL=tracer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/orchestration/tracer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,YAAY,EAGZ,WAAW,EAGX,OAAO,EACR,MAAM,yBAAyB,CAAA;AAIhC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAkB/C,MAAM,WAAW,eAAe;IAC9B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAA;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;IACzC,yFAAyF;IACzF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,mGAAmG;AACnG,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,OAAO,GAAG,OAAO,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAiHzB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The end-to-end tracer: compile a {@link RunPlan}, run it through the {@link WorkflowRunner}, and
|
|
3
|
+
* project each transition into content-free {@link RunEvidence}. Every emitted record is re-parsed
|
|
4
|
+
* through {@link parseRunEvidence}, so the tracer itself proves the stream carries no payload and
|
|
5
|
+
* stays under the size cap. The terminal digest is a deterministic hash of the evidence stream:
|
|
6
|
+
* identical plan + catalog + inputs yield an identical digest, which is the deterministic-eval anchor.
|
|
7
|
+
*/
|
|
8
|
+
import { parseRunEvidence, parseRunPlan, RUN_PLAN_VERSION } from "@nifrajs/agent-protocol";
|
|
9
|
+
import { WorkflowRunner } from "../workflows.js";
|
|
10
|
+
import { noopArtifactPort } from "./artifact-port.js";
|
|
11
|
+
import { compileRunPlan, digestRunPlan } from "./compile.js";
|
|
12
|
+
import { canonicalJson, sha256HexOf } from "./hash.js";
|
|
13
|
+
/** A verify/approve node whose output is not a pass. Other kinds never gate. */
|
|
14
|
+
function isGateRejection(kind, output) {
|
|
15
|
+
if (kind === "verify") {
|
|
16
|
+
if (output === true)
|
|
17
|
+
return false;
|
|
18
|
+
return !(typeof output === "object" &&
|
|
19
|
+
output !== null &&
|
|
20
|
+
output.ok === true);
|
|
21
|
+
}
|
|
22
|
+
if (kind === "approve")
|
|
23
|
+
return output !== true;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
/** Run a plan and return its content-free evidence stream plus a deterministic terminal digest. */
|
|
27
|
+
export async function runTrace(source, options) {
|
|
28
|
+
const plan = parseRunPlan(source);
|
|
29
|
+
const planDigest = await digestRunPlan(plan);
|
|
30
|
+
const artifactPort = options.artifactPort ?? noopArtifactPort();
|
|
31
|
+
const effectKeys = new Map();
|
|
32
|
+
const artifacts = new Map();
|
|
33
|
+
const idempotent = new Map();
|
|
34
|
+
const kindById = new Map();
|
|
35
|
+
const nodeIds = new Set();
|
|
36
|
+
const walk = (node) => {
|
|
37
|
+
nodeIds.add(node.id);
|
|
38
|
+
kindById.set(node.id, node.kind);
|
|
39
|
+
const step = "step" in node ? options.catalog.get(node.step) : undefined;
|
|
40
|
+
idempotent.set(node.id, step?.selectEffect !== undefined);
|
|
41
|
+
switch (node.kind) {
|
|
42
|
+
case "sequence":
|
|
43
|
+
case "parallel":
|
|
44
|
+
for (const child of node.children)
|
|
45
|
+
walk(child);
|
|
46
|
+
break;
|
|
47
|
+
case "retry":
|
|
48
|
+
walk(node.child);
|
|
49
|
+
break;
|
|
50
|
+
case "branch":
|
|
51
|
+
walk(node.then);
|
|
52
|
+
if (node.otherwise !== undefined)
|
|
53
|
+
walk(node.otherwise);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
for (const node of plan.nodes)
|
|
58
|
+
walk(node);
|
|
59
|
+
const step = compileRunPlan(plan, {
|
|
60
|
+
catalog: options.catalog,
|
|
61
|
+
planDigest,
|
|
62
|
+
artifactPort,
|
|
63
|
+
onNodeEffect: (nodeId, key) => effectKeys.set(nodeId, key),
|
|
64
|
+
collectArtifact: (nodeId, ref) => {
|
|
65
|
+
const list = artifacts.get(nodeId);
|
|
66
|
+
if (list === undefined)
|
|
67
|
+
artifacts.set(nodeId, [ref]);
|
|
68
|
+
else
|
|
69
|
+
list.push(ref);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const evidence = [];
|
|
73
|
+
let seq = 0;
|
|
74
|
+
const push = (record) => {
|
|
75
|
+
// Re-parse each record: proves it is content-free and within the size cap before it is kept.
|
|
76
|
+
evidence.push(parseRunEvidence(record));
|
|
77
|
+
};
|
|
78
|
+
const onEvent = (event) => {
|
|
79
|
+
if (!("id" in event) || !nodeIds.has(event.id))
|
|
80
|
+
return;
|
|
81
|
+
const base = {
|
|
82
|
+
version: RUN_PLAN_VERSION,
|
|
83
|
+
runId: options.runId,
|
|
84
|
+
planDigest,
|
|
85
|
+
nodeId: event.id,
|
|
86
|
+
seq: seq++,
|
|
87
|
+
idempotent: idempotent.get(event.id) ?? false,
|
|
88
|
+
};
|
|
89
|
+
if (event.type === "step.started") {
|
|
90
|
+
push({ ...base, status: "started" });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (event.type === "step.completed") {
|
|
94
|
+
const key = effectKeys.get(event.id);
|
|
95
|
+
const refs = artifacts.get(event.id);
|
|
96
|
+
// A verify/approve gate reports pass/fail through its output, then the kernel aborts the run on
|
|
97
|
+
// a non-pass. Project that as a failed record so the evidence reflects the gate's verdict.
|
|
98
|
+
if (isGateRejection(kindById.get(event.id), event.output)) {
|
|
99
|
+
push({
|
|
100
|
+
...base,
|
|
101
|
+
status: "failed",
|
|
102
|
+
errorCode: "GATE_REJECTED",
|
|
103
|
+
...(key !== undefined ? { effectKey: key.digest } : {}),
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
push({
|
|
108
|
+
...base,
|
|
109
|
+
status: "completed",
|
|
110
|
+
...(key !== undefined ? { effectKey: key.digest } : {}),
|
|
111
|
+
...(refs !== undefined && refs.length > 0 ? { artifacts: refs } : {}),
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (event.type === "step.failed") {
|
|
116
|
+
const key = effectKeys.get(event.id);
|
|
117
|
+
push({
|
|
118
|
+
...base,
|
|
119
|
+
status: "failed",
|
|
120
|
+
errorCode: "STEP_FAILED",
|
|
121
|
+
...(key !== undefined ? { effectKey: key.digest } : {}),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const result = await new WorkflowRunner({
|
|
126
|
+
onEvent,
|
|
127
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
128
|
+
...(options.maxSteps !== undefined ? { maxSteps: options.maxSteps } : {}),
|
|
129
|
+
...(options.maxDepth !== undefined ? { maxDepth: options.maxDepth } : {}),
|
|
130
|
+
}).run(step);
|
|
131
|
+
const terminalDigest = await sha256HexOf(canonicalJson(evidence));
|
|
132
|
+
return {
|
|
133
|
+
ok: result.ok,
|
|
134
|
+
runId: options.runId,
|
|
135
|
+
planDigest,
|
|
136
|
+
evidence,
|
|
137
|
+
terminalDigest,
|
|
138
|
+
...(result.error !== undefined ? { error: result.error } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=tracer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/orchestration/tracer.ts"],"names":[],"mappings":"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"}
|
package/dist/plans.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type WorkflowEvent, type WorkflowResult, type WorkflowStep } from "./workflows.js";
|
|
2
|
+
export interface PlanPhase {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly title: string;
|
|
5
|
+
readonly step: WorkflowStep;
|
|
6
|
+
}
|
|
7
|
+
export interface AgentPlan {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly goal: string;
|
|
10
|
+
readonly phases: readonly PlanPhase[];
|
|
11
|
+
readonly maxSteps?: number;
|
|
12
|
+
readonly maxDepth?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface PlanEvent {
|
|
15
|
+
readonly type: "plan.started" | "plan.phase.started" | "plan.phase.completed" | "plan.completed" | "plan.failed";
|
|
16
|
+
readonly planId: string;
|
|
17
|
+
readonly phaseId?: string;
|
|
18
|
+
readonly message?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface PlanRunnerOptions {
|
|
21
|
+
readonly signal?: AbortSignal;
|
|
22
|
+
readonly onEvent?: (event: PlanEvent | WorkflowEvent) => void | PromiseLike<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface PlanResult extends WorkflowResult {
|
|
25
|
+
readonly planId: string;
|
|
26
|
+
readonly goal: string;
|
|
27
|
+
}
|
|
28
|
+
/** First-party plan mode built on the bounded workflow primitives; no model or UI dependency. */
|
|
29
|
+
export declare class PlanRunner {
|
|
30
|
+
private readonly options;
|
|
31
|
+
constructor(options?: PlanRunnerOptions);
|
|
32
|
+
run(plan: AgentPlan): Promise<PlanResult>;
|
|
33
|
+
private emit;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=plans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EACT,cAAc,GACd,oBAAoB,GACpB,sBAAsB,GACtB,gBAAgB,GAChB,aAAa,CAAA;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;CAClF;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,iGAAiG;AACjG,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;gBAE/B,OAAO,GAAE,iBAAsB;IAIrC,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;YAoCjC,IAAI;CAGnB"}
|
package/dist/plans.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { WorkflowRunner, } from "./workflows.js";
|
|
2
|
+
/** First-party plan mode built on the bounded workflow primitives; no model or UI dependency. */
|
|
3
|
+
export class PlanRunner {
|
|
4
|
+
options;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
}
|
|
8
|
+
async run(plan) {
|
|
9
|
+
validatePlan(plan);
|
|
10
|
+
await this.emit({ type: "plan.started", planId: plan.id, message: plan.goal });
|
|
11
|
+
const workflow = new WorkflowRunner({
|
|
12
|
+
...(this.options.signal === undefined ? {} : { signal: this.options.signal }),
|
|
13
|
+
...(plan.maxSteps === undefined ? {} : { maxSteps: plan.maxSteps }),
|
|
14
|
+
...(plan.maxDepth === undefined ? {} : { maxDepth: plan.maxDepth }),
|
|
15
|
+
onEvent: async (event) => this.options.onEvent?.(event),
|
|
16
|
+
});
|
|
17
|
+
const step = {
|
|
18
|
+
type: "sequence",
|
|
19
|
+
steps: plan.phases.map((phase) => ({
|
|
20
|
+
type: "task",
|
|
21
|
+
id: phase.id,
|
|
22
|
+
run: async (context) => {
|
|
23
|
+
await this.emit({
|
|
24
|
+
type: "plan.phase.started",
|
|
25
|
+
planId: plan.id,
|
|
26
|
+
phaseId: phase.id,
|
|
27
|
+
message: phase.title,
|
|
28
|
+
});
|
|
29
|
+
const output = await context.run(phase.step);
|
|
30
|
+
await this.emit({ type: "plan.phase.completed", planId: plan.id, phaseId: phase.id });
|
|
31
|
+
return output;
|
|
32
|
+
},
|
|
33
|
+
})),
|
|
34
|
+
};
|
|
35
|
+
const result = await workflow.run(step);
|
|
36
|
+
await this.emit({
|
|
37
|
+
type: result.ok ? "plan.completed" : "plan.failed",
|
|
38
|
+
planId: plan.id,
|
|
39
|
+
...(result.error === undefined ? {} : { message: result.error }),
|
|
40
|
+
});
|
|
41
|
+
return { ...result, planId: plan.id, goal: plan.goal };
|
|
42
|
+
}
|
|
43
|
+
async emit(event) {
|
|
44
|
+
await this.options.onEvent?.(event);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function validatePlan(plan) {
|
|
48
|
+
if (!/^[a-z][a-z0-9._:-]{0,63}$/.test(plan.id))
|
|
49
|
+
throw new TypeError("plan: id is invalid");
|
|
50
|
+
if (!plan.goal || plan.goal.length > 4_096)
|
|
51
|
+
throw new TypeError("plan: goal is empty or too long");
|
|
52
|
+
if (plan.phases.length === 0 || plan.phases.length > 128)
|
|
53
|
+
throw new RangeError("plan: phases must be between 1 and 128");
|
|
54
|
+
const ids = new Set();
|
|
55
|
+
for (const phase of plan.phases) {
|
|
56
|
+
if (!/^[a-z][a-z0-9._:-]{0,63}$/.test(phase.id) || !phase.title || phase.title.length > 256)
|
|
57
|
+
throw new TypeError(`plan: invalid phase ${phase.id}`);
|
|
58
|
+
if (ids.has(phase.id))
|
|
59
|
+
throw new TypeError(`plan: duplicate phase ${phase.id}`);
|
|
60
|
+
ids.add(phase.id);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=plans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SubagentSpec } from "./subagents.js";
|
|
2
|
+
export type AgentPresetName = "planner" | "implementer" | "test-fixer" | "reviewer" | "security-reviewer" | "final-verifier";
|
|
3
|
+
export interface AgentPreset extends Omit<SubagentSpec, "id" | "prompt"> {
|
|
4
|
+
readonly name: AgentPresetName;
|
|
5
|
+
readonly summary: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const AGENT_PRESETS: Readonly<Record<AgentPresetName, AgentPreset>>;
|
|
8
|
+
export declare function getAgentPreset(name: AgentPresetName): AgentPreset;
|
|
9
|
+
export declare function createPresetSpec(name: AgentPresetName, prompt: string, id?: string): SubagentSpec;
|
|
10
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,aAAa,GACb,YAAY,GACZ,UAAU,GACV,mBAAmB,GACnB,gBAAgB,CAAA;AAEpB,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,QAAQ,CAAC;IACtE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAqDD,eAAO,MAAM,aAAa,gDAAU,CAAA;AAEpC,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,CAEjE;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,MAAM,EACd,EAAE,SAAuC,GACxC,YAAY,CAad"}
|
package/dist/presets.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const PRESETS = Object.freeze({
|
|
2
|
+
planner: {
|
|
3
|
+
name: "planner",
|
|
4
|
+
role: "planner",
|
|
5
|
+
summary: "Break a task into bounded, verifiable phases.",
|
|
6
|
+
capabilities: Object.freeze(["read"]),
|
|
7
|
+
maxDepth: 1,
|
|
8
|
+
timeoutMs: 120_000,
|
|
9
|
+
},
|
|
10
|
+
implementer: {
|
|
11
|
+
name: "implementer",
|
|
12
|
+
role: "implementer",
|
|
13
|
+
summary: "Apply a narrowly scoped implementation and report changed files.",
|
|
14
|
+
capabilities: Object.freeze(["read", "write", "process"]),
|
|
15
|
+
maxDepth: 1,
|
|
16
|
+
timeoutMs: 600_000,
|
|
17
|
+
},
|
|
18
|
+
"test-fixer": {
|
|
19
|
+
name: "test-fixer",
|
|
20
|
+
role: "test-fixer",
|
|
21
|
+
summary: "Reproduce and repair a failing test within the task boundary.",
|
|
22
|
+
capabilities: Object.freeze(["read", "write", "process"]),
|
|
23
|
+
maxDepth: 1,
|
|
24
|
+
timeoutMs: 600_000,
|
|
25
|
+
},
|
|
26
|
+
reviewer: {
|
|
27
|
+
name: "reviewer",
|
|
28
|
+
role: "reviewer",
|
|
29
|
+
summary: "Review a proposed change for correctness and regressions.",
|
|
30
|
+
capabilities: Object.freeze(["read", "process"]),
|
|
31
|
+
maxDepth: 1,
|
|
32
|
+
timeoutMs: 240_000,
|
|
33
|
+
},
|
|
34
|
+
"security-reviewer": {
|
|
35
|
+
name: "security-reviewer",
|
|
36
|
+
role: "security-reviewer",
|
|
37
|
+
summary: "Review capabilities, trust boundaries, secrets, and process execution.",
|
|
38
|
+
capabilities: Object.freeze(["read", "process"]),
|
|
39
|
+
maxDepth: 1,
|
|
40
|
+
timeoutMs: 240_000,
|
|
41
|
+
},
|
|
42
|
+
"final-verifier": {
|
|
43
|
+
name: "final-verifier",
|
|
44
|
+
role: "final-verifier",
|
|
45
|
+
summary: "Run the configured verification gates and return structured evidence.",
|
|
46
|
+
capabilities: Object.freeze(["read", "process"]),
|
|
47
|
+
maxDepth: 1,
|
|
48
|
+
timeoutMs: 300_000,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
export const AGENT_PRESETS = PRESETS;
|
|
52
|
+
export function getAgentPreset(name) {
|
|
53
|
+
return PRESETS[name];
|
|
54
|
+
}
|
|
55
|
+
export function createPresetSpec(name, prompt, id = `${name}-${Date.now().toString(36)}`) {
|
|
56
|
+
const preset = getAgentPreset(name);
|
|
57
|
+
if (!prompt || prompt.length > 16_384)
|
|
58
|
+
throw new TypeError("agent preset: prompt is empty or too long");
|
|
59
|
+
if (!/^[a-z][a-z0-9._:-]{0,63}$/.test(id))
|
|
60
|
+
throw new TypeError("agent preset: id is invalid");
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
role: preset.role,
|
|
64
|
+
prompt,
|
|
65
|
+
...(preset.capabilities === undefined ? {} : { capabilities: preset.capabilities }),
|
|
66
|
+
...(preset.maxDepth === undefined ? {} : { maxDepth: preset.maxDepth }),
|
|
67
|
+
...(preset.timeoutMs === undefined ? {} : { timeoutMs: preset.timeoutMs }),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface BoundedText {
|
|
2
|
+
readonly text: string;
|
|
3
|
+
readonly truncated: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function readBoundedText(stream: ReadableStream<Uint8Array> | null | undefined | number, maxBytes: number): Promise<BoundedText>;
|
|
6
|
+
//# sourceMappingURL=process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAC9D,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAsCtB"}
|