@relayflows/sdk 2.0.36 → 2.0.38
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/agent-reaper.d.ts +1 -1
- package/dist/agent-reaper.d.ts.map +1 -1
- package/dist/agent-reaper.js +6 -4
- package/dist/agent-reaper.js.map +1 -1
- package/dist/authored-budget.d.ts +26 -1
- package/dist/authored-budget.d.ts.map +1 -1
- package/dist/authored-budget.js +72 -2
- package/dist/authored-budget.js.map +1 -1
- package/dist/authored-flow-error.d.ts +7 -1
- package/dist/authored-flow-error.d.ts.map +1 -1
- package/dist/authored-flow-error.js.map +1 -1
- package/dist/authored-flow-executor.d.ts +2 -0
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +2 -1
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-helper-effect.d.ts.map +1 -1
- package/dist/authored-helper-effect.js +3 -2
- package/dist/authored-helper-effect.js.map +1 -1
- package/dist/authored-mcp.d.ts.map +1 -1
- package/dist/authored-mcp.js +2 -0
- package/dist/authored-mcp.js.map +1 -1
- package/dist/authored-node-entry.js +6 -0
- package/dist/authored-node-entry.js.map +1 -1
- package/dist/authored-node-runner.d.ts.map +1 -1
- package/dist/authored-node-runner.js +5 -3
- package/dist/authored-node-runner.js.map +1 -1
- package/dist/authored-plugin-effect.d.ts.map +1 -1
- package/dist/authored-plugin-effect.js +2 -0
- package/dist/authored-plugin-effect.js.map +1 -1
- package/dist/authored-preflight.d.ts +1 -1
- package/dist/authored-preflight.d.ts.map +1 -1
- package/dist/authored-preflight.js +2 -2
- package/dist/authored-preflight.js.map +1 -1
- package/dist/authored-root.d.ts +2 -0
- package/dist/authored-root.d.ts.map +1 -1
- package/dist/authored-root.js +146 -6
- package/dist/authored-root.js.map +1 -1
- package/dist/authored-verdict.d.ts +2 -0
- package/dist/authored-verdict.d.ts.map +1 -1
- package/dist/authored-verdict.js +2 -1
- package/dist/authored-verdict.js.map +1 -1
- package/dist/authored-worker-step.d.ts +1 -1
- package/dist/authored-worker-step.d.ts.map +1 -1
- package/dist/authored-worker-step.js +3 -2
- package/dist/authored-worker-step.js.map +1 -1
- package/dist/child-stop.d.ts +3 -1
- package/dist/child-stop.d.ts.map +1 -1
- package/dist/child-stop.js +42 -2
- package/dist/child-stop.js.map +1 -1
- package/dist/cli/add-extension.js +1 -1
- package/dist/cli/add-extension.js.map +1 -1
- package/dist/cli/check.d.ts +2 -0
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +28 -10
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/cli-probe.d.ts +3 -2
- package/dist/cli/cli-probe.d.ts.map +1 -1
- package/dist/cli/cli-probe.js +79 -42
- package/dist/cli/cli-probe.js.map +1 -1
- package/dist/cli/direct-run.d.ts.map +1 -1
- package/dist/cli/direct-run.js +11 -3
- package/dist/cli/direct-run.js.map +1 -1
- package/dist/cli/pinned-cli-alias.d.ts +13 -0
- package/dist/cli/pinned-cli-alias.d.ts.map +1 -0
- package/dist/cli/pinned-cli-alias.js +58 -0
- package/dist/cli/pinned-cli-alias.js.map +1 -0
- package/dist/cli/run.d.ts +8 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +106 -17
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/step-failure.d.ts.map +1 -1
- package/dist/cli/step-failure.js +18 -0
- package/dist/cli/step-failure.js.map +1 -1
- package/dist/cloud-run.d.ts.map +1 -1
- package/dist/cloud-run.js +9 -2
- package/dist/cloud-run.js.map +1 -1
- package/dist/communication/local.d.ts +1 -1
- package/dist/communication/local.d.ts.map +1 -1
- package/dist/communication/local.js +2 -2
- package/dist/communication/local.js.map +1 -1
- package/dist/communication/worker.d.ts +1 -1
- package/dist/communication/worker.d.ts.map +1 -1
- package/dist/communication/worker.js +27 -9
- package/dist/communication/worker.js.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +16 -7
- package/dist/compile.js.map +1 -1
- package/dist/decimal-dollars.d.ts +12 -0
- package/dist/decimal-dollars.d.ts.map +1 -0
- package/dist/decimal-dollars.js +39 -0
- package/dist/decimal-dollars.js.map +1 -0
- package/dist/effect-channel.d.ts.map +1 -1
- package/dist/effect-channel.js +2 -0
- package/dist/effect-channel.js.map +1 -1
- package/dist/failure-kinds.d.ts +9 -1
- package/dist/failure-kinds.d.ts.map +1 -1
- package/dist/failure-kinds.js +6 -0
- package/dist/failure-kinds.js.map +1 -1
- package/dist/flow-extension-loader.d.ts +1 -1
- package/dist/flow-extension-loader.d.ts.map +1 -1
- package/dist/flow-extension-loader.js +143 -14
- package/dist/flow-extension-loader.js.map +1 -1
- package/dist/flow-extension-manifest.d.ts +1 -0
- package/dist/flow-extension-manifest.d.ts.map +1 -1
- package/dist/flow-extension-manifest.js +12 -3
- package/dist/flow-extension-manifest.js.map +1 -1
- package/dist/helper-instruction.d.ts +3 -0
- package/dist/helper-instruction.d.ts.map +1 -0
- package/dist/helper-instruction.js +3 -0
- package/dist/helper-instruction.js.map +1 -0
- package/dist/hosted-extension-manifest.d.ts.map +1 -1
- package/dist/hosted-extension-manifest.js +25 -4
- package/dist/hosted-extension-manifest.js.map +1 -1
- package/dist/hosted-extension-runtime.js +1 -1
- package/dist/hosted-extension-sandbox.js +2 -2
- package/dist/journal-client.d.ts +5 -2
- package/dist/journal-client.d.ts.map +1 -1
- package/dist/journal-client.js +12 -4
- package/dist/journal-client.js.map +1 -1
- package/dist/llm-worker.d.ts +2 -1
- package/dist/llm-worker.d.ts.map +1 -1
- package/dist/llm-worker.js +10 -3
- package/dist/llm-worker.js.map +1 -1
- package/dist/local-agent-environment.d.ts +13 -0
- package/dist/local-agent-environment.d.ts.map +1 -0
- package/dist/local-agent-environment.js +104 -0
- package/dist/local-agent-environment.js.map +1 -0
- package/dist/local-agent.d.ts +1 -1
- package/dist/local-agent.d.ts.map +1 -1
- package/dist/local-agent.js +2 -2
- package/dist/local-agent.js.map +1 -1
- package/dist/mcp-stdio.d.ts +2 -1
- package/dist/mcp-stdio.d.ts.map +1 -1
- package/dist/mcp-stdio.js +38 -21
- package/dist/mcp-stdio.js.map +1 -1
- package/dist/preflight.d.ts +2 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js.map +1 -1
- package/dist/protocol.d.ts +30 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/reported-cost-total.d.ts +41 -0
- package/dist/reported-cost-total.d.ts.map +1 -0
- package/dist/reported-cost-total.js +63 -0
- package/dist/reported-cost-total.js.map +1 -0
- package/dist/reported-cost.d.ts +24 -0
- package/dist/reported-cost.d.ts.map +1 -0
- package/dist/reported-cost.js +49 -0
- package/dist/reported-cost.js.map +1 -0
- package/dist/resolved-cli-identity.d.ts +14 -0
- package/dist/resolved-cli-identity.d.ts.map +1 -0
- package/dist/resolved-cli-identity.js +19 -0
- package/dist/resolved-cli-identity.js.map +1 -0
- package/dist/run-state.d.ts +9 -11
- package/dist/run-state.d.ts.map +1 -1
- package/dist/run-state.js +15 -38
- package/dist/run-state.js.map +1 -1
- package/dist/worker-cli.d.ts +3 -1
- package/dist/worker-cli.d.ts.map +1 -1
- package/dist/worker-cli.js +118 -42
- package/dist/worker-cli.js.map +1 -1
- package/dist/worker-lease.d.ts +3 -1
- package/dist/worker-lease.d.ts.map +1 -1
- package/dist/worker-lease.js +47 -9
- package/dist/worker-lease.js.map +1 -1
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +8 -3
- package/dist/worker.js.map +1 -1
- package/dist/wrapper-session.d.ts +3 -1
- package/dist/wrapper-session.d.ts.map +1 -1
- package/dist/wrapper-session.js +93 -53
- package/dist/wrapper-session.js.map +1 -1
- package/dist/yaml-helper-effect.d.ts.map +1 -1
- package/dist/yaml-helper-effect.js +2 -1
- package/dist/yaml-helper-effect.js.map +1 -1
- package/dist/yaml-helpers.d.ts.map +1 -1
- package/dist/yaml-helpers.js +2 -1
- package/dist/yaml-helpers.js.map +1 -1
- package/package.json +2 -2
- package/src/agent-reaper.ts +7 -4
- package/src/authored-budget.ts +73 -1
- package/src/authored-flow-error.ts +6 -0
- package/src/authored-flow-executor.ts +4 -1
- package/src/authored-helper-effect.ts +3 -2
- package/src/authored-mcp.ts +2 -0
- package/src/authored-node-entry.ts +8 -1
- package/src/authored-node-runner.ts +5 -3
- package/src/authored-plugin-effect.ts +2 -0
- package/src/authored-preflight.ts +2 -2
- package/src/authored-root.ts +157 -7
- package/src/authored-verdict.ts +2 -1
- package/src/authored-worker-step.ts +3 -1
- package/src/child-stop.ts +40 -1
- package/src/cli/add-extension.ts +1 -1
- package/src/cli/check.ts +31 -7
- package/src/cli/cli-probe.ts +80 -42
- package/src/cli/direct-run.ts +11 -2
- package/src/cli/pinned-cli-alias.ts +74 -0
- package/src/cli/run.ts +118 -14
- package/src/cli/step-failure.ts +18 -0
- package/src/cloud-run.ts +9 -2
- package/src/communication/local.ts +3 -2
- package/src/communication/worker.ts +29 -11
- package/src/compile.ts +28 -13
- package/src/decimal-dollars.ts +38 -0
- package/src/effect-channel.ts +2 -0
- package/src/failure-kinds.ts +14 -0
- package/src/flow-extension-loader.ts +154 -14
- package/src/flow-extension-manifest.ts +6 -3
- package/src/helper-instruction.ts +2 -0
- package/src/hosted-extension-manifest.ts +28 -5
- package/src/hosted-extension-runtime.ts +1 -1
- package/src/hosted-extension-sandbox.ts +2 -2
- package/src/journal-client.ts +14 -5
- package/src/llm-worker.ts +11 -4
- package/src/local-agent-environment.ts +92 -0
- package/src/local-agent.ts +2 -1
- package/src/mcp-stdio.ts +34 -20
- package/src/preflight.ts +2 -0
- package/src/protocol.ts +31 -0
- package/src/reported-cost-total.ts +82 -0
- package/src/reported-cost.ts +51 -0
- package/src/resolved-cli-identity.ts +42 -0
- package/src/run-state.ts +25 -37
- package/src/worker-cli.ts +126 -39
- package/src/worker-lease.ts +50 -9
- package/src/worker.ts +14 -5
- package/src/wrapper-session.ts +89 -56
- package/src/yaml-helper-effect.ts +2 -1
- package/src/yaml-helpers.ts +2 -1
package/dist/yaml-helpers.js
CHANGED
|
@@ -2,6 +2,7 @@ import Ajv from 'ajv';
|
|
|
2
2
|
import { githubClient, linearClient, slackClient } from '@relayfile/relay-helpers';
|
|
3
3
|
import { canonicalize } from './canonical.js';
|
|
4
4
|
import { unknownKeyErrors } from './unknown-keys.js';
|
|
5
|
+
import { HELPER_INSTRUCTION_PREFIX } from './helper-instruction.js';
|
|
5
6
|
const string = { type: 'string', minLength: 1 };
|
|
6
7
|
const text = { type: 'string' };
|
|
7
8
|
const strings = { type: 'array', items: string };
|
|
@@ -40,7 +41,7 @@ const helpers = {
|
|
|
40
41
|
args: object(issueChanges, []) }), (p, transport) => linearClient({ transport }).updateIssue(p.issueId, p.args)),
|
|
41
42
|
},
|
|
42
43
|
};
|
|
43
|
-
const prefix =
|
|
44
|
+
const prefix = HELPER_INSTRUCTION_PREFIX;
|
|
44
45
|
const commonFields = ['id', 'dependsOn', 'maxIterations', 'verification', 'output'];
|
|
45
46
|
const isObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
46
47
|
function descriptor(provider, name) {
|
package/dist/yaml-helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml-helpers.js","sourceRoot":"","sources":["../src/yaml-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAuB,MAAM,0BAA0B,CAAC;AAExG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"yaml-helpers.js","sourceRoot":"","sources":["../src/yaml-helpers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayflows/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.38",
|
|
4
4
|
"description": "TypeScript-first authoring SDK for Relayflows. Compiles specs; speaks the journal protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
50
50
|
"@relayfile/adapter-core": "0.6.2",
|
|
51
51
|
"@relayfile/relay-helpers": "0.4.12",
|
|
52
|
-
"@relayflows/surface": "2.0.
|
|
52
|
+
"@relayflows/surface": "2.0.38",
|
|
53
53
|
"@types/js-yaml": "^4.0.9",
|
|
54
54
|
"acorn": "^8.18.0",
|
|
55
55
|
"ai-hist": "0.4.1",
|
package/src/agent-reaper.ts
CHANGED
|
@@ -16,11 +16,14 @@ import type { ChildStop } from './child-stop.js';
|
|
|
16
16
|
*
|
|
17
17
|
* Nothing survives a SIGKILL of this process; that needs a supervisor.
|
|
18
18
|
*/
|
|
19
|
-
const live = new
|
|
19
|
+
const live = new Map<ChildStop, () => void>();
|
|
20
20
|
const FATAL_SIGNALS: readonly NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
21
21
|
|
|
22
22
|
function killAll(): void {
|
|
23
|
-
for (const stop of live)
|
|
23
|
+
for (const [stop, releaseOnExit] of live) {
|
|
24
|
+
stop.kill();
|
|
25
|
+
releaseOnExit();
|
|
26
|
+
}
|
|
24
27
|
live.clear();
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -42,9 +45,9 @@ function uninstall(): void {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/** Kill this agent tree if the process ends first. Returns the release. */
|
|
45
|
-
export function reapOnExit(stop: ChildStop): () => void {
|
|
48
|
+
export function reapOnExit(stop: ChildStop, releaseOnExit: () => void = () => {}): () => void {
|
|
46
49
|
if (live.size === 0) install();
|
|
47
|
-
live.
|
|
50
|
+
live.set(stop, releaseOnExit);
|
|
48
51
|
return () => {
|
|
49
52
|
if (!live.delete(stop)) return;
|
|
50
53
|
if (live.size === 0) uninstall();
|
package/src/authored-budget.ts
CHANGED
|
@@ -21,6 +21,76 @@ interface Charge {
|
|
|
21
21
|
unmetered: boolean;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
type Total = Omit<Charge, 'day'>;
|
|
25
|
+
|
|
26
|
+
/** `ms` as the budget header writes durations (`45s`, `2h`, `132.9m`), with the value that text denotes. */
|
|
27
|
+
function duration(ms: bigint): {text: string; shown: number} {
|
|
28
|
+
const n = Number(ms);
|
|
29
|
+
if (n < 60_000) { const s = Number((n / 1000).toFixed(1)); return {text: `${s}s`, shown: s * 1000}; }
|
|
30
|
+
if (n % 3_600_000 === 0) return {text: `${n / 3_600_000}h`, shown: n};
|
|
31
|
+
const m = Number((n / 60_000).toFixed(1));
|
|
32
|
+
return {text: `${m}m`, shown: m * 60_000};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const usd = (micro: bigint): string => `$${micro / 1_000_000n}.${String(micro % 1_000_000n).padStart(6, '0').replace(/0{1,4}$/, '')}`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Whether `micro` microdollars exceeds the decimal `limit`, compared exactly at
|
|
39
|
+
* the limit's own precision (legacy `maxDollars` may carry more than six
|
|
40
|
+
* decimals, which the kernel compares as written). Undefined if the limit is
|
|
41
|
+
* not a plain decimal.
|
|
42
|
+
*/
|
|
43
|
+
function dollarsOver(micro: bigint, limit: string): boolean | undefined {
|
|
44
|
+
const match = /^(\d+)(?:\.(\d+))?$/.exec(limit);
|
|
45
|
+
if (match === null) return undefined;
|
|
46
|
+
const scale = Math.max(6, match[2]?.length ?? 0);
|
|
47
|
+
const limitScaled = BigInt(match[1]! + (match[2] ?? '').padEnd(scale, '0'));
|
|
48
|
+
return micro * 10n ** BigInt(scale - 6) > limitScaled;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Both durations, exact to the millisecond whenever rounding would make the
|
|
53
|
+
* overrun invisible: the displayed spend must itself read as over the
|
|
54
|
+
* displayed limit, compared as quantities so `120m` against `2h` counts too.
|
|
55
|
+
*/
|
|
56
|
+
function durations(used: bigint, limit: bigint): [string, string] {
|
|
57
|
+
const [u, l] = [duration(used), duration(limit)];
|
|
58
|
+
return u.shown > l.shown ? [u.text, l.text] : [`${used}ms`, `${limit}ms`];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The kernel refuses admission with only `budget_exceeded`; name which
|
|
63
|
+
* declared limit the carried spend crossed and by how much, using the same
|
|
64
|
+
* strict comparisons as `machine/budget.rs`. The kernel stays the authority: a
|
|
65
|
+
* refusal this accumulator cannot explain keeps the generic wording.
|
|
66
|
+
*/
|
|
67
|
+
export function budgetExceededMessage(limit: KernelBudgetSpec, total: Total, spec?: KernelRunSpec): string {
|
|
68
|
+
const crossed: string[] = [];
|
|
69
|
+
if (limit.max_wallclock_ms !== undefined && total.ms > BigInt(limit.max_wallclock_ms)) {
|
|
70
|
+
const [used, declared] = durations(total.ms, BigInt(limit.max_wallclock_ms));
|
|
71
|
+
crossed.push(`wallclock ${used} used of ${declared} declared`);
|
|
72
|
+
}
|
|
73
|
+
if (limit.max_dollars !== undefined && dollarsOver(total.micro, limit.max_dollars) === true) {
|
|
74
|
+
const exact = /^(\d+)(?:\.(\d{1,6}))?$/.exec(limit.max_dollars);
|
|
75
|
+
const declared = exact === null ? `$${limit.max_dollars}`
|
|
76
|
+
: usd(BigInt(exact[1]!) * 1_000_000n + BigInt((exact[2] ?? '').padEnd(6, '0')));
|
|
77
|
+
crossed.push(`dollars ${usd(total.micro)}${total.unmetered ? ' metered (some steps unmetered)' : ''} used of ${declared} declared`);
|
|
78
|
+
}
|
|
79
|
+
if (limit.max_tokens !== undefined && total.input + total.output > BigInt(limit.max_tokens)) {
|
|
80
|
+
crossed.push(`tokens ${total.input + total.output} used of ${limit.max_tokens} declared`);
|
|
81
|
+
}
|
|
82
|
+
if (limit.max_tokens_in !== undefined && total.input > BigInt(limit.max_tokens_in)) {
|
|
83
|
+
crossed.push(`input tokens ${total.input} used of ${limit.max_tokens_in} declared`);
|
|
84
|
+
}
|
|
85
|
+
if (limit.max_tokens_out !== undefined && total.output > BigInt(limit.max_tokens_out)) {
|
|
86
|
+
crossed.push(`output tokens ${total.output} used of ${limit.max_tokens_out} declared`);
|
|
87
|
+
}
|
|
88
|
+
const next = spec?.steps.length === 1 && typeof spec.steps[0]?.id === 'string' ? `step "${spec.steps[0].id}"` : 'the next step';
|
|
89
|
+
if (crossed.length === 0) return `Flow budget exceeded before ${next}.`;
|
|
90
|
+
const scope = limit.window === 'day' ? "in today's window of the flow's budget header" : "in the flow's budget header";
|
|
91
|
+
return `Flow budget exceeded before ${next}: ${crossed.join('; ')} ${scope}.`;
|
|
92
|
+
}
|
|
93
|
+
|
|
24
94
|
/** Serialized admission for the internal authored runner's separate step runs. */
|
|
25
95
|
export class AuthoredBudget {
|
|
26
96
|
private readonly limit: KernelBudgetSpec | undefined;
|
|
@@ -66,7 +136,9 @@ export class AuthoredBudget {
|
|
|
66
136
|
};
|
|
67
137
|
const outcome = await journal.runStart({ ...spec, budget: { ...this.limit, prior_spend: priorSpend } }, undefined, admissionKey);
|
|
68
138
|
try {
|
|
69
|
-
if (outcome.completion_reason === 'budget_exceeded')
|
|
139
|
+
if (outcome.completion_reason === 'budget_exceeded') {
|
|
140
|
+
throw new AuthoredFlowExecutionError('step_failed', budgetExceededMessage(this.limit!, total, spec), 'budget_exceeded', outcome.run_id);
|
|
141
|
+
}
|
|
70
142
|
return await consume(outcome);
|
|
71
143
|
} finally {
|
|
72
144
|
let seq = 1;
|
|
@@ -30,6 +30,12 @@ export type AuthoredFlowExecutionErrorCode =
|
|
|
30
30
|
| 'operation_callback_failed'
|
|
31
31
|
| 'step_failed'
|
|
32
32
|
| 'lease_exceeded'
|
|
33
|
+
/**
|
|
34
|
+
* The CLI lost the authored root's worker lease and the kernel did not
|
|
35
|
+
* re-dispatch the root to it. The run is not failed: completed steps are
|
|
36
|
+
* journaled and `flows resume <rootRunId>` continues it.
|
|
37
|
+
*/
|
|
38
|
+
| 'root_lease_lost'
|
|
33
39
|
| 'unsupported_completion'
|
|
34
40
|
| 'unsupported_gate'
|
|
35
41
|
| 'gate_failed'
|
|
@@ -185,6 +185,8 @@ export interface ExecuteAuthoredFlowOptions {
|
|
|
185
185
|
readonly onWait?: RunLifecycleOptions['onWait'];
|
|
186
186
|
readonly onProgress?: (event: ProgressEvent) => void;
|
|
187
187
|
readonly localAgentStream?: string;
|
|
188
|
+
/** Environment reserved for provider probes and local agent subprocesses. */
|
|
189
|
+
readonly agentEnvironment?: NodeJS.ProcessEnv;
|
|
188
190
|
/**
|
|
189
191
|
* How many agent (and, separately, LLM) dispatches the attached local
|
|
190
192
|
* workers hold at once. Set, it caps this body's concurrent `f.agent` /
|
|
@@ -320,7 +322,7 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
320
322
|
const worker = authoredWorkerRunner(
|
|
321
323
|
definition, journal, flowPath, journalSteps, waitOptions,
|
|
322
324
|
localAgentStream, budget, definition.header.budget, options.rootRunId, options.workerCapacity, stepEdges,
|
|
323
|
-
options.workerSlots,
|
|
325
|
+
options.workerSlots, options.agentEnvironment,
|
|
324
326
|
);
|
|
325
327
|
|
|
326
328
|
/**
|
|
@@ -685,6 +687,7 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
685
687
|
dataDir: options.dataDir,
|
|
686
688
|
flowPath: child.path,
|
|
687
689
|
...(localAgentStream === undefined ? {} : { localAgentStream }),
|
|
690
|
+
...(options.agentEnvironment === undefined ? {} : { agentEnvironment: options.agentEnvironment }),
|
|
688
691
|
...(options.workerCapacity === undefined ? {} : { workerCapacity: options.workerCapacity }),
|
|
689
692
|
...(options.rootRunId === undefined ? {} : { rootRunId: options.rootRunId }),
|
|
690
693
|
flowGraph: options.flowGraph,
|
|
@@ -14,6 +14,7 @@ import { helperWriteback, HelperDeliveryError } from './helper-writeback.js';
|
|
|
14
14
|
import { checkSlackHelpers } from './slack-preflight.js';
|
|
15
15
|
import { atomicJson, readSlackReceipt, receiptPath, slackWriteback, type SlackCall } from './slack-writeback.js';
|
|
16
16
|
import { authoredChildAdmissionKey } from './authored-admission.js';
|
|
17
|
+
import { NO_MODEL_COST } from './reported-cost.js';
|
|
17
18
|
|
|
18
19
|
type ProviderCall = HelperCall | SlackCall;
|
|
19
20
|
|
|
@@ -135,11 +136,11 @@ async function completeHelperDispatch(client: JournalClient, dispatch: StepDispa
|
|
|
135
136
|
await client.stepComplete(dispatch.run_id, dispatch.step_id, dispatch.attempt,
|
|
136
137
|
dispatch.idempotency_key, 'worker_error', {
|
|
137
138
|
output: { ...call, diagnostic: error.message },
|
|
138
|
-
started_pins: dispatch.pins, end_pins: dispatch.pins, effects: [],
|
|
139
|
+
started_pins: dispatch.pins, end_pins: dispatch.pins, effects: [], reported_cost: NO_MODEL_COST,
|
|
139
140
|
});
|
|
140
141
|
return;
|
|
141
142
|
}
|
|
142
143
|
await client.stepComplete(dispatch.run_id, dispatch.step_id, dispatch.attempt,
|
|
143
|
-
dispatch.idempotency_key, 'success', { output, started_pins: dispatch.pins, end_pins: dispatch.pins,
|
|
144
|
+
dispatch.idempotency_key, 'success', { output, started_pins: dispatch.pins, end_pins: dispatch.pins, reported_cost: NO_MODEL_COST,
|
|
144
145
|
effects: [{ surface_path: `/${call.provider}`, idempotency_key: dispatch.idempotency_key }] });
|
|
145
146
|
}
|
package/src/authored-mcp.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { AuthoredFlowJournalStep } from './authored-flow-executor.js';
|
|
|
12
12
|
import { readCompletedStepOutput } from './authored-step-output.js';
|
|
13
13
|
import { withWorkerLease } from './worker-lease.js';
|
|
14
14
|
import { authoredChildAdmissionKey } from './authored-admission.js';
|
|
15
|
+
import { NO_MODEL_COST } from './reported-cost.js';
|
|
15
16
|
|
|
16
17
|
/** Own keys expose precisely the preflight inventory, including prototype-like names. */
|
|
17
18
|
export function buildMcpProxy(
|
|
@@ -116,6 +117,7 @@ export async function runMcpEffect(
|
|
|
116
117
|
output: { ...receipt, output: output ?? null, ...(diagnostic ? { diagnostic } : {}) },
|
|
117
118
|
started_pins: event.pins, end_pins: event.pins,
|
|
118
119
|
...(diagnostic ? { trajectory_tail: { ...receipt, diagnostic } } : {}),
|
|
120
|
+
reported_cost: NO_MODEL_COST,
|
|
119
121
|
effects: confirmed ? [{ surface_path: surfacePath, idempotency_key: event.idempotency_key }] : [],
|
|
120
122
|
});
|
|
121
123
|
}
|
|
@@ -8,6 +8,7 @@ import { assertAuthoredNodeVersion, parseAuthoredParentPid } from './authored-ru
|
|
|
8
8
|
import { AuthoredFlowExecutionError, AuthoredHumanParked } from './authored-flow-error.js';
|
|
9
9
|
import { isAgentCapacity } from './worker-slots.js';
|
|
10
10
|
import type { AuthoredRootMetadata } from './authored-root.js';
|
|
11
|
+
import { validatedLocalAgentEnvironment } from './local-agent-environment.js';
|
|
11
12
|
|
|
12
13
|
let channelKey: string | undefined, sequence = 0;
|
|
13
14
|
// Capture writers before loading authored modules; credentials never enter env.
|
|
@@ -49,7 +50,8 @@ try {
|
|
|
49
50
|
send({ type: 'ready', runtime: { kind: 'node', version: process.versions.node,
|
|
50
51
|
executableSha256: hash(process.execPath), payloadSha256: hash(process.argv[1]!) } });
|
|
51
52
|
const request = await new Promise<{ channelKey: string; metadata: AuthoredRootMetadata; socketPath: string;
|
|
52
|
-
rootRunId: string; dataDir: string; localAgentStream?: string; workerCapacity?: number
|
|
53
|
+
rootRunId: string; dataDir: string; localAgentStream?: string; workerCapacity?: number;
|
|
54
|
+
agentEnvironment?: unknown }>((resolve, reject) => {
|
|
53
55
|
let buffer = '';
|
|
54
56
|
process.stdin.setEncoding('utf8');
|
|
55
57
|
const onData = (chunk: string): void => {
|
|
@@ -65,6 +67,10 @@ try {
|
|
|
65
67
|
if (typeof request.channelKey !== 'string' || !/^[a-f0-9]{64}$/.test(request.channelKey)) throw new Error('invalid authored channel key');
|
|
66
68
|
channelKey = request.channelKey;
|
|
67
69
|
controller.signal.throwIfAborted();
|
|
70
|
+
// Validate the parent handoff before evaluating any authored module. Only
|
|
71
|
+
// provider credentials may cross this channel; controls such as PATH and
|
|
72
|
+
// NODE_OPTIONS remain the child's inherited values.
|
|
73
|
+
const agentEnvironment = validatedLocalAgentEnvironment(request.agentEnvironment);
|
|
68
74
|
const loaded = await loadPinnedAuthoredSource(request.metadata, true);
|
|
69
75
|
if (request.localAgentStream !== request.metadata.localAgentStream) throw new Error('authored root local agent surface mismatch');
|
|
70
76
|
if (request.workerCapacity !== undefined && !isAgentCapacity(request.workerCapacity)) throw new Error('invalid authored worker capacity');
|
|
@@ -78,6 +84,7 @@ try {
|
|
|
78
84
|
flowGraph: loaded.graph,
|
|
79
85
|
localAgentStream: request.localAgentStream, signal: controller.signal,
|
|
80
86
|
...(request.workerCapacity === undefined ? {} : { workerCapacity: request.workerCapacity }),
|
|
87
|
+
...(agentEnvironment === undefined ? {} : { agentEnvironment: { ...process.env, ...agentEnvironment } }),
|
|
81
88
|
onProgress: event => send({ type: 'progress', event }),
|
|
82
89
|
onWait: event => send({ type: 'wait', event }),
|
|
83
90
|
});
|
|
@@ -83,7 +83,7 @@ export async function runAuthoredInNode(
|
|
|
83
83
|
await writeFile(entry, source, { mode: 0o400, flag: 'wx' });
|
|
84
84
|
if (hash(await readFile(entry)) !== runtime.payloadSha256) throw refusal();
|
|
85
85
|
const child = spawn(authority.path, ['--experimental-transform-types', entry, String(process.pid)], {
|
|
86
|
-
cwd: process.cwd(),
|
|
86
|
+
cwd: process.cwd(),
|
|
87
87
|
stdio: ['pipe', 'inherit', 'inherit', 'pipe'],
|
|
88
88
|
});
|
|
89
89
|
const result = await new Promise<AuthoredFlowExecutionResult>((resolve, reject) => {
|
|
@@ -134,7 +134,8 @@ export async function runAuthoredInNode(
|
|
|
134
134
|
// Keep stdin open: EOF tells the child its lease-owning parent died.
|
|
135
135
|
child.stdin!.write(JSON.stringify({ channelKey, metadata, socketPath, rootRunId,
|
|
136
136
|
dataDir: options.dataDir, localAgentStream: options.localAgentStream,
|
|
137
|
-
workerCapacity: options.workerCapacity
|
|
137
|
+
workerCapacity: options.workerCapacity,
|
|
138
|
+
agentEnvironment: options.agentEnvironment }) + '\n');
|
|
138
139
|
} else if (!ready || result) throw new Error('unexpected authored runtime message');
|
|
139
140
|
else if (message.type === 'progress') options.onProgress?.(message.event);
|
|
140
141
|
else if (message.type === 'wait') options.onWait?.(message.event);
|
|
@@ -239,7 +240,8 @@ export function stepFailedFrame(value: unknown): StepFailedDetails | undefined {
|
|
|
239
240
|
for (const [key, parsed] of [
|
|
240
241
|
['stepId', frameText(frame, 'stepId')], ['stepType', frameText(frame, 'stepType')],
|
|
241
242
|
['completionReason', frameText(frame, 'completionReason')], ['attempt', frameCount(frame, 'attempt')],
|
|
242
|
-
['maxIterations', frameCount(frame, 'maxIterations')],
|
|
243
|
+
['maxIterations', frameCount(frame, 'maxIterations')],
|
|
244
|
+
['unchargedAttempts', frameCount(frame, 'unchargedAttempts')], ['exitCode', frameCount(frame, 'exitCode')],
|
|
243
245
|
['stdoutTail', frameText(frame, 'stdoutTail')], ['stderrTail', frameText(frame, 'stderrTail')],
|
|
244
246
|
['detail', frameText(frame, 'detail')], ['transcriptPath', frameText(frame, 'transcriptPath')],
|
|
245
247
|
['attempts', attemptFrames(frame['attempts'])],
|
|
@@ -11,6 +11,7 @@ import type { AuthoredFlowJournalStep } from './authored-flow-executor.js';
|
|
|
11
11
|
import { readCompletedStepOutput } from './authored-step-output.js';
|
|
12
12
|
import { withWorkerLease } from './worker-lease.js';
|
|
13
13
|
import { authoredChildAdmissionKey } from './authored-admission.js';
|
|
14
|
+
import { NO_MODEL_COST } from './reported-cost.js';
|
|
14
15
|
|
|
15
16
|
export class PluginStepError extends AuthoredFlowExecutionError {
|
|
16
17
|
constructor(readonly diagnostic: string, runId: string) {
|
|
@@ -88,6 +89,7 @@ export async function runPluginEffect(
|
|
|
88
89
|
output: { ...receipt, output: output ?? null, ...(diagnostic ? { diagnostic } : {}) },
|
|
89
90
|
started_pins: event.pins, end_pins: event.pins,
|
|
90
91
|
...(diagnostic ? { trajectory_tail: { ...receipt, diagnostic } } : {}),
|
|
92
|
+
reported_cost: NO_MODEL_COST,
|
|
91
93
|
effects: confirmed ? [{ surface_path: surfacePath, idempotency_key: event.idempotency_key }] : [],
|
|
92
94
|
});
|
|
93
95
|
}
|
|
@@ -6,7 +6,7 @@ import { cliProbeKey, CliProbeError, resolvePreflight, type CliProbeOutcome } fr
|
|
|
6
6
|
import type { FlowSpec } from './spec.js';
|
|
7
7
|
|
|
8
8
|
/** Auth/model facts belong to one execution, including concurrent cold callers. */
|
|
9
|
-
export function authoredPreflight(path: string) {
|
|
9
|
+
export function authoredPreflight(path: string, environment?: NodeJS.ProcessEnv) {
|
|
10
10
|
const probeCache = new Map<string, CliProbeOutcome>();
|
|
11
11
|
const pending = new Map<string, Promise<void>>();
|
|
12
12
|
const directory = dirname(resolve(path));
|
|
@@ -30,7 +30,7 @@ export function authoredPreflight(path: string) {
|
|
|
30
30
|
try {
|
|
31
31
|
probeCache.set(key, { result: await probeCliAsync(resolution.cli,
|
|
32
32
|
resolution.source === 'project' ? config.directory : directory,
|
|
33
|
-
resolution.model, managed ? 'managed' : undefined) });
|
|
33
|
+
resolution.model, managed ? 'managed' : undefined, environment) });
|
|
34
34
|
} catch (error) {
|
|
35
35
|
probeCache.set(key, { failure: error instanceof CliProbeError ? error.detail : null });
|
|
36
36
|
}
|
package/src/authored-root.ts
CHANGED
|
@@ -12,15 +12,16 @@ import {
|
|
|
12
12
|
type LoadedAuthoredFlow,
|
|
13
13
|
type SurfaceModuleAuthority,
|
|
14
14
|
} from './authored-flow-loader.js';
|
|
15
|
-
import { JournalClient } from './journal-client.js';
|
|
15
|
+
import { JournalClient, JournalProtocolError } from './journal-client.js';
|
|
16
16
|
import type { RunOutcome, StepDispatchEvent } from './protocol.js';
|
|
17
17
|
import { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
18
18
|
import type { RunLifecycleOptions } from './cli/run.js';
|
|
19
|
-
import { withWorkerLease } from './worker-lease.js';
|
|
19
|
+
import { isLeaseLost, withWorkerLease } from './worker-lease.js';
|
|
20
20
|
import { AuthoredFlowExecutionError, AuthoredHumanParked } from './authored-flow-error.js';
|
|
21
|
-
import { readOpenHumanWaits } from './authored-human.js';
|
|
21
|
+
import { readOpenHumanWaits, resumeCommand } from './authored-human.js';
|
|
22
22
|
import { isSurfaceCompletionReason } from './authored-step-output.js';
|
|
23
23
|
import { readSubscriptionPark } from './authored-subscription-park.js';
|
|
24
|
+
import { localAgentCredentialEnvironment } from './local-agent-environment.js';
|
|
24
25
|
|
|
25
26
|
export type DurableAuthoredFlowResult =
|
|
26
27
|
| (AuthoredFlowExecutionResult & { readonly rootRunId: string })
|
|
@@ -67,6 +68,8 @@ export interface DurableAuthoredOptions {
|
|
|
67
68
|
readonly localAgentStream?: string;
|
|
68
69
|
/** Concurrency of the attached local workers; see `ExecuteAuthoredFlowOptions.workerCapacity`. */
|
|
69
70
|
readonly workerCapacity?: number;
|
|
71
|
+
/** Provider-only environment consumed by preflight and local workers. */
|
|
72
|
+
readonly agentEnvironment?: NodeJS.ProcessEnv;
|
|
70
73
|
readonly lifecycle?: RunLifecycleOptions;
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -131,7 +134,7 @@ export async function executeDurableAuthoredFlow(
|
|
|
131
134
|
if (parked !== undefined) return { state: 'suspended', name: metadata.flowName,
|
|
132
135
|
suspension: parked, journalSteps: [], rootRunId: outcome.run_id };
|
|
133
136
|
const dispatch = await dispatchWait.promise;
|
|
134
|
-
return await
|
|
137
|
+
return await driveRootFollowingRetries(loaded, metadata, journal, peer, dispatch, options);
|
|
135
138
|
} finally {
|
|
136
139
|
cancelDispatch();
|
|
137
140
|
peer.close();
|
|
@@ -174,7 +177,7 @@ export async function resumeDurableAuthoredFlow(
|
|
|
174
177
|
if (parked !== undefined) return { state: 'suspended', name: metadata.flowName,
|
|
175
178
|
suspension: parked, journalSteps: [], rootRunId };
|
|
176
179
|
const dispatch = await dispatchWait.promise;
|
|
177
|
-
return await
|
|
180
|
+
return await driveRootFollowingRetries(loaded, metadata, journal, peer, dispatch, options);
|
|
178
181
|
} finally {
|
|
179
182
|
cancelDispatch();
|
|
180
183
|
peer.close();
|
|
@@ -211,6 +214,102 @@ export async function readAuthoredRootMetadata(
|
|
|
211
214
|
return Object.freeze({ ...value, extensions: value.extensions ?? [] });
|
|
212
215
|
}
|
|
213
216
|
|
|
217
|
+
/**
|
|
218
|
+
* How many times one CLI re-drives a root whose lease it lost. Each re-drive
|
|
219
|
+
* replays completed steps from their journaled receipts, so the bound guards a
|
|
220
|
+
* lease that keeps being lost, not the cost of the work.
|
|
221
|
+
*/
|
|
222
|
+
const MAX_ROOT_REDRIVES = 3;
|
|
223
|
+
/**
|
|
224
|
+
* How long to wait for the kernel to re-dispatch a root whose lease was lost:
|
|
225
|
+
* a full lease (30s, relayflowd LEASE_RENEWAL_MS) in case the daemon still
|
|
226
|
+
* held it, plus its sweep and grace.
|
|
227
|
+
*/
|
|
228
|
+
const ROOT_REDISPATCH_TIMEOUT_MS = 45_000;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Drive the root, and FOLLOW the kernel when it retries the root attempt.
|
|
232
|
+
*
|
|
233
|
+
* A lost root lease is not a failed flow. The kernel journals the attempt
|
|
234
|
+
* `lease_expired` with `disposition: retry` without charging an iteration
|
|
235
|
+
* (relayflowd-core recovery.rs) and re-dispatches the root to the worker
|
|
236
|
+
* still attached on `peer` -- this process. Exiting there with
|
|
237
|
+
* "worker wait canceled" (customer rw_3a0fcb71) threw away a run the kernel
|
|
238
|
+
* was about to continue, including a child agent already on its second
|
|
239
|
+
* attempt: the re-driven body replays completed steps from their receipts and
|
|
240
|
+
* adopts that in-flight child (authored-step-output.ts). Only when no retry
|
|
241
|
+
* arrives does the error leave, as `root_lease_lost` naming the resume.
|
|
242
|
+
*/
|
|
243
|
+
async function driveRootFollowingRetries(
|
|
244
|
+
loaded: LoadedAuthoredFlow,
|
|
245
|
+
metadata: AuthoredRootMetadata,
|
|
246
|
+
journal: JournalClient,
|
|
247
|
+
peer: JournalClient,
|
|
248
|
+
firstDispatch: StepDispatchEvent,
|
|
249
|
+
options: Omit<DurableAuthoredOptions, 'admissionKey'>,
|
|
250
|
+
): Promise<DurableAuthoredFlowResult> {
|
|
251
|
+
let dispatch = firstDispatch;
|
|
252
|
+
for (let redrives = 0; ; redrives += 1) {
|
|
253
|
+
// Listen before driving: the retry can be dispatched the moment the
|
|
254
|
+
// daemon sweeps the lease, before the aborted body has unwound. The
|
|
255
|
+
// timeout starts only once there is a lost lease to wait on.
|
|
256
|
+
const next = rootRedispatch(peer);
|
|
257
|
+
try {
|
|
258
|
+
const result = await driveRoot(loaded, metadata, journal, peer, dispatch, options);
|
|
259
|
+
next.cancel();
|
|
260
|
+
return result;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
// `run_terminal` from a step verb means the run has already reached a
|
|
263
|
+
// terminal state. It is lease-shaped for worker cleanup, but the kernel
|
|
264
|
+
// cannot re-dispatch this root, so do not turn it into a 45s retry wait.
|
|
265
|
+
const terminal = error instanceof JournalProtocolError && error.code === 'run_terminal';
|
|
266
|
+
if (!isLeaseLost(error) || terminal || options.lifecycle?.signal?.aborted === true) {
|
|
267
|
+
next.cancel();
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
const lost = sentence(error instanceof Error ? error.message : String(error));
|
|
271
|
+
const resume = resumeCommand(dispatch.run_id, options.dataDir, options.localAgentStream !== undefined);
|
|
272
|
+
if (redrives >= MAX_ROOT_REDRIVES) {
|
|
273
|
+
next.cancel();
|
|
274
|
+
throw rootLeaseLost(dispatch, `${lost} It was lost ${redrives + 1} times in this process; continue the run with: ${resume}`, error);
|
|
275
|
+
}
|
|
276
|
+
process.emitWarning(
|
|
277
|
+
`authored root run_id=${dispatch.run_id} attempt=${dispatch.attempt}: ${lost} Waiting for the kernel to retry it.`,
|
|
278
|
+
{ code: 'FLOWS_ROOT_LEASE_LOST' },
|
|
279
|
+
);
|
|
280
|
+
try {
|
|
281
|
+
dispatch = await next.wait(ROOT_REDISPATCH_TIMEOUT_MS, options.lifecycle?.signal);
|
|
282
|
+
} catch (waitError) {
|
|
283
|
+
// A caller cancel while waiting is the caller's, not a lost lease.
|
|
284
|
+
if (aborted(options.lifecycle?.signal)) throw waitError;
|
|
285
|
+
throw rootLeaseLost(dispatch, `${lost} The kernel did not re-dispatch the root within ${ROOT_REDISPATCH_TIMEOUT_MS / 1000}s; continue the run with: ${resume}`, error);
|
|
286
|
+
}
|
|
287
|
+
if (dispatch.run_id !== firstDispatch.run_id) {
|
|
288
|
+
throw new Error('authored root retry was dispatched for a different run');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Read at call time: `signal.aborted` changes while this function awaits. */
|
|
295
|
+
function aborted(signal: AbortSignal | undefined): boolean {
|
|
296
|
+
return signal?.aborted === true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function sentence(text: string): string {
|
|
300
|
+
return /[.!?]$/.test(text) ? text : `${text}.`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function rootLeaseLost(dispatch: StepDispatchEvent, message: string, cause: unknown): AuthoredFlowExecutionError {
|
|
304
|
+
const error = new AuthoredFlowExecutionError('root_lease_lost',
|
|
305
|
+
`authored root run ${dispatch.run_id} lost its worker lease on attempt ${dispatch.attempt}. ${message}`
|
|
306
|
+
+ ' Completed steps are journaled and are not re-run.',
|
|
307
|
+
'lease_expired');
|
|
308
|
+
error.rootRunId = dispatch.run_id;
|
|
309
|
+
(error as { cause?: unknown }).cause = cause;
|
|
310
|
+
return error;
|
|
311
|
+
}
|
|
312
|
+
|
|
214
313
|
async function driveRoot(
|
|
215
314
|
loaded: LoadedAuthoredFlow,
|
|
216
315
|
metadata: AuthoredRootMetadata,
|
|
@@ -226,6 +325,9 @@ async function driveRoot(
|
|
|
226
325
|
if (process.versions['bun'] !== undefined) {
|
|
227
326
|
return runAuthoredInNode(metadata, journal.socketPath, dispatch.run_id, {
|
|
228
327
|
dataDir: options.dataDir, localAgentStream: options.localAgentStream,
|
|
328
|
+
...(options.agentEnvironment === undefined ? {} : {
|
|
329
|
+
agentEnvironment: localAgentCredentialEnvironment(options.agentEnvironment),
|
|
330
|
+
}),
|
|
229
331
|
...(options.workerCapacity === undefined ? {} : { workerCapacity: options.workerCapacity }),
|
|
230
332
|
...options.lifecycle, signal,
|
|
231
333
|
});
|
|
@@ -239,6 +341,7 @@ async function driveRoot(
|
|
|
239
341
|
dataDir: options.dataDir,
|
|
240
342
|
flowPath: metadata.flowPath,
|
|
241
343
|
localAgentStream: options.localAgentStream,
|
|
344
|
+
...(options.agentEnvironment === undefined ? {} : { agentEnvironment: options.agentEnvironment }),
|
|
242
345
|
...(options.workerCapacity === undefined ? {} : { workerCapacity: options.workerCapacity }),
|
|
243
346
|
rootRunId: dispatch.run_id,
|
|
244
347
|
extensions: loaded.extensions,
|
|
@@ -262,6 +365,9 @@ async function driveRoot(
|
|
|
262
365
|
);
|
|
263
366
|
return Object.freeze({ ...result, rootRunId: dispatch.run_id });
|
|
264
367
|
} catch (error) {
|
|
368
|
+
// A lost lease is owned by the kernel's retry path, not by this attempt's
|
|
369
|
+
// terminalization or suspension handling.
|
|
370
|
+
if (isLeaseLost(error)) throw error;
|
|
265
371
|
if (error instanceof AuthoredFlowExecutionError
|
|
266
372
|
&& error.code === 'subscription_suspended'
|
|
267
373
|
&& error.suspension !== undefined) {
|
|
@@ -369,7 +475,51 @@ function hasRootStream(step: Record<string, unknown>): boolean {
|
|
|
369
475
|
try { rootStreamFromMetadata(step); return true; } catch { return false; }
|
|
370
476
|
}
|
|
371
477
|
|
|
372
|
-
|
|
478
|
+
/**
|
|
479
|
+
* Buffers the next root dispatch from the moment it is created; `wait`
|
|
480
|
+
* bounds only the time spent waiting for it. Unlike `nextRootDispatch`, no
|
|
481
|
+
* timer runs while the body is being driven -- a body longer than the
|
|
482
|
+
* timeout must not leave a rejected promise nobody awaits.
|
|
483
|
+
*/
|
|
484
|
+
function rootRedispatch(peer: JournalClient): {
|
|
485
|
+
wait(timeoutMs: number, signal?: AbortSignal): Promise<StepDispatchEvent>;
|
|
486
|
+
cancel(): void;
|
|
487
|
+
} {
|
|
488
|
+
let received: StepDispatchEvent | undefined;
|
|
489
|
+
let deliver: ((dispatch: StepDispatchEvent) => void) | undefined;
|
|
490
|
+
const onDispatch = (dispatch: StepDispatchEvent): void => {
|
|
491
|
+
if (dispatch.step_id !== 'authored-root') return;
|
|
492
|
+
peer.off('step.dispatch', onDispatch);
|
|
493
|
+
if (deliver === undefined) received = dispatch;
|
|
494
|
+
else deliver(dispatch);
|
|
495
|
+
};
|
|
496
|
+
peer.on('step.dispatch', onDispatch);
|
|
497
|
+
const cancel = (): void => { peer.off('step.dispatch', onDispatch); };
|
|
498
|
+
return {
|
|
499
|
+
cancel,
|
|
500
|
+
wait: (timeoutMs, signal) => new Promise((resolve, reject) => {
|
|
501
|
+
if (received !== undefined) { resolve(received); return; }
|
|
502
|
+
const settle = (): void => {
|
|
503
|
+
clearTimeout(timer);
|
|
504
|
+
signal?.removeEventListener('abort', onAbort);
|
|
505
|
+
cancel();
|
|
506
|
+
};
|
|
507
|
+
const onAbort = (): void => {
|
|
508
|
+
settle();
|
|
509
|
+
reject(new Error('waiting for the authored root to be re-dispatched was canceled', { cause: signal?.reason }));
|
|
510
|
+
};
|
|
511
|
+
const timer = setTimeout(() => {
|
|
512
|
+
settle();
|
|
513
|
+
reject(new Error('authored root was not re-dispatched'));
|
|
514
|
+
}, timeoutMs);
|
|
515
|
+
deliver = dispatch => { settle(); resolve(dispatch); };
|
|
516
|
+
if (signal?.aborted === true) onAbort();
|
|
517
|
+
else signal?.addEventListener('abort', onAbort, { once: true });
|
|
518
|
+
}),
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function nextRootDispatch(peer: JournalClient, timeoutMs = 30_000): {
|
|
373
523
|
promise: Promise<StepDispatchEvent>;
|
|
374
524
|
cancel(): void;
|
|
375
525
|
} {
|
|
@@ -378,7 +528,7 @@ function nextRootDispatch(peer: JournalClient): {
|
|
|
378
528
|
const timer = setTimeout(() => {
|
|
379
529
|
peer.off('step.dispatch', onDispatch);
|
|
380
530
|
reject(new Error('authored root was not dispatched'));
|
|
381
|
-
},
|
|
531
|
+
}, timeoutMs);
|
|
382
532
|
const onDispatch = (dispatch: StepDispatchEvent) => {
|
|
383
533
|
if (dispatch.step_id !== 'authored-root') return;
|
|
384
534
|
clearTimeout(timer);
|
package/src/authored-verdict.ts
CHANGED
|
@@ -67,7 +67,8 @@ export function authoredVerdictOf(events: readonly JournalEvent[]): AuthoredVerd
|
|
|
67
67
|
return Object.freeze({ reason, ...(detail === undefined ? {} : { detail }) });
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
/** Whether a journal's spawned spec is a real authored root, not a step merely named `authored-root`. */
|
|
71
|
+
export function declaresAuthoredRoot(spawned: JournalEvent): boolean {
|
|
71
72
|
const spec = record(record(spawned.payload)?.['spec']);
|
|
72
73
|
const steps = spec?.['steps'];
|
|
73
74
|
if (!Array.isArray(steps)) return false;
|
|
@@ -27,6 +27,7 @@ export function authoredWorkerRunner(
|
|
|
27
27
|
localAgentStream?: string, budget?: AuthoredBudget, headerBudget?: unknown,
|
|
28
28
|
rootRunId?: string, workerCapacity?: number, stepEdges?: AuthoredStepContext['stepEdges'],
|
|
29
29
|
sharedSlots?: AuthoredWorkerSlots,
|
|
30
|
+
agentEnvironment?: NodeJS.ProcessEnv,
|
|
30
31
|
) {
|
|
31
32
|
// Sized to the attached local workers, so concurrent calls wait here for a
|
|
32
33
|
// slot instead of being admitted and parked for want of a free worker.
|
|
@@ -36,7 +37,7 @@ export function authoredWorkerRunner(
|
|
|
36
37
|
agent: slots.agent.scope(),
|
|
37
38
|
llm: slots.llm.scope(),
|
|
38
39
|
};
|
|
39
|
-
const check = authoredPreflight(flowPath);
|
|
40
|
+
const check = authoredPreflight(flowPath, agentEnvironment);
|
|
40
41
|
const context: AuthoredStepContext = {
|
|
41
42
|
...(rootRunId === undefined ? {} : { rootRunId }),
|
|
42
43
|
...(waitOptions.dataDir === undefined ? {} : { dataDir: waitOptions.dataDir }),
|
|
@@ -342,6 +343,7 @@ function stepDetails(
|
|
|
342
343
|
...(found.completionReason === undefined ? {} : { completionReason: found.completionReason }),
|
|
343
344
|
...(found.attempt === undefined ? {} : { attempt: found.attempt }),
|
|
344
345
|
...(found.maxIterations === undefined ? {} : { maxIterations: found.maxIterations }),
|
|
346
|
+
...(found.unchargedAttempts === undefined ? {} : { unchargedAttempts: found.unchargedAttempts }),
|
|
345
347
|
...(found.exitCode === undefined ? {} : { exitCode: found.exitCode }),
|
|
346
348
|
...(found.stdoutTail === undefined ? {} : { stdoutTail: found.stdoutTail }),
|
|
347
349
|
...(found.stderrTail === undefined ? {} : { stderrTail: found.stderrTail }),
|