@relayflows/sdk 2.0.6 → 2.0.8
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/authored-flow-error.d.ts +1 -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 +27 -1
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +139 -22
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-flow-loader.d.ts +16 -2
- package/dist/authored-flow-loader.d.ts.map +1 -1
- package/dist/authored-flow-loader.js +47 -3
- package/dist/authored-flow-loader.js.map +1 -1
- package/dist/cli/direct-run.d.ts.map +1 -1
- package/dist/cli/direct-run.js +38 -3
- package/dist/cli/direct-run.js.map +1 -1
- package/package.json +2 -2
- package/src/authored-flow-error.ts +3 -0
- package/src/authored-flow-executor.ts +208 -18
- package/src/authored-flow-loader.ts +77 -4
- package/src/cli/direct-run.ts +38 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CompletionReason as ProtocolCompletionReason, RunCompletionReason as ProtocolRunCompletionReason } from './protocol.js';
|
|
2
|
-
export type AuthoredFlowExecutionErrorCode = 'duplicate_completion' | 'journal_protocol_violation' | 'missing_completion' | 'operation_after_completion' | 'operation_callback_failed' | 'step_failed' | 'unsupported_completion' | 'unsupported_gate' | 'unsupported_header' | 'unsettled_derived_work' | 'unsupported_promise_lifecycle' | 'unawaited_step' | 'unsupported_verb';
|
|
2
|
+
export type AuthoredFlowExecutionErrorCode = 'agent_cli_unresolved' | 'agent_parked' | 'duplicate_completion' | 'journal_protocol_violation' | 'missing_completion' | 'operation_after_completion' | 'operation_callback_failed' | 'step_failed' | 'unsupported_completion' | 'unsupported_gate' | 'unsupported_header' | 'unsettled_derived_work' | 'unsupported_promise_lifecycle' | 'unsupported_workspace_permission' | 'unawaited_step' | 'unsupported_verb';
|
|
3
3
|
export declare class AuthoredFlowExecutionError extends Error {
|
|
4
4
|
readonly code: AuthoredFlowExecutionErrorCode;
|
|
5
5
|
readonly completionReason?: (ProtocolCompletionReason | ProtocolRunCompletionReason) | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-error.d.ts","sourceRoot":"","sources":["../src/authored-flow-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,IAAI,wBAAwB,EAC5C,mBAAmB,IAAI,2BAA2B,EACnD,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,8BAA8B,GACtC,sBAAsB,GACtB,4BAA4B,GAC5B,oBAAoB,GACpB,4BAA4B,GAC5B,2BAA2B,GAC3B,aAAa,GACb,wBAAwB,GACxB,kBAAkB,GAClB,oBAAoB,GACpB,wBAAwB,GACxB,+BAA+B,GAC/B,gBAAgB,GAChB,kBAAkB,CAAC;AAEvB,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,QAAQ,CAAC,IAAI,EAAE,8BAA8B;IAE7C,QAAQ,CAAC,gBAAgB,CAAC,GAAE,wBAAwB,GAAG,2BAA2B;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM;gBAHd,IAAI,EAAE,8BAA8B,EAC7C,OAAO,EAAE,MAAM,EACN,gBAAgB,CAAC,GAAE,wBAAwB,GAAG,2BAA2B,aAAA,EACzE,KAAK,CAAC,EAAE,MAAM,YAAA;CAK1B"}
|
|
1
|
+
{"version":3,"file":"authored-flow-error.d.ts","sourceRoot":"","sources":["../src/authored-flow-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,IAAI,wBAAwB,EAC5C,mBAAmB,IAAI,2BAA2B,EACnD,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,8BAA8B,GACtC,sBAAsB,GACtB,cAAc,GACd,sBAAsB,GACtB,4BAA4B,GAC5B,oBAAoB,GACpB,4BAA4B,GAC5B,2BAA2B,GAC3B,aAAa,GACb,wBAAwB,GACxB,kBAAkB,GAClB,oBAAoB,GACpB,wBAAwB,GACxB,+BAA+B,GAC/B,kCAAkC,GAClC,gBAAgB,GAChB,kBAAkB,CAAC;AAEvB,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,QAAQ,CAAC,IAAI,EAAE,8BAA8B;IAE7C,QAAQ,CAAC,gBAAgB,CAAC,GAAE,wBAAwB,GAAG,2BAA2B;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM;gBAHd,IAAI,EAAE,8BAA8B,EAC7C,OAAO,EAAE,MAAM,EACN,gBAAgB,CAAC,GAAE,wBAAwB,GAAG,2BAA2B,aAAA,EACzE,KAAK,CAAC,EAAE,MAAM,YAAA;CAK1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-error.js","sourceRoot":"","sources":["../src/authored-flow-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authored-flow-error.js","sourceRoot":"","sources":["../src/authored-flow-error.ts"],"names":[],"mappings":"AAuBA,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAExC;IAEA;IACA;IAJX,YACW,IAAoC,EAC7C,OAAe,EACN,gBAAyE,EACzE,KAAc;QAEvB,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QALpB,SAAI,GAAJ,IAAI,CAAgC;QAEpC,qBAAgB,GAAhB,gBAAgB,CAAyD;QACzE,UAAK,GAAL,KAAK,CAAS;QAGvB,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { FlowHandle } from '@relayflows/surface/runtime';
|
|
2
|
+
import type { GetFlowDefinition } from './authored-flow-loader.js';
|
|
3
|
+
import { type RunLifecycleOptions } from './cli/run.js';
|
|
2
4
|
import { AuthoredFlowExecutionError, type AuthoredFlowExecutionErrorCode } from './authored-flow-error.js';
|
|
3
5
|
import { JournalClient } from './journal-client.js';
|
|
4
6
|
import type { CompletionReason as ProtocolCompletionReason, RunCompletionReason as ProtocolRunCompletionReason } from './protocol.js';
|
|
@@ -24,5 +26,29 @@ export interface AuthoredFlowExecutionResult {
|
|
|
24
26
|
* `JournalClient`; values are read back from `step.completed` journal entries.
|
|
25
27
|
* Unsupported headers, verbs, gates, or completion lowering fail closed.
|
|
26
28
|
*/
|
|
27
|
-
export
|
|
29
|
+
export interface ExecuteAuthoredFlowOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Defaults to this package's own static import — correct for every
|
|
32
|
+
* existing (internal, single-instance) caller. A flow loaded from an
|
|
33
|
+
* external path via `loadAuthoredFlow` must pass ITS resolved
|
|
34
|
+
* `getDefinition` instead; see authored-flow-loader.ts's comment on why.
|
|
35
|
+
*/
|
|
36
|
+
readonly getDefinition?: GetFlowDefinition;
|
|
37
|
+
/**
|
|
38
|
+
* The flow file's own path — passed straight to `checkAuthoredFlow`
|
|
39
|
+
* (cli/check.ts) so `f.agent` resolves a CLI the same way a declarative
|
|
40
|
+
* `type: agent` step does: nearest `flows.json`, real auth/model probing,
|
|
41
|
+
* canonicalized path. `checkAuthoredFlow` always does `dirname()` on this,
|
|
42
|
+
* matching `checkFlow`'s real `flows check <file>` contract — pass a FILE
|
|
43
|
+
* path, not a directory, or the search starts one level too high. Defaults
|
|
44
|
+
* to a synthetic `flow.ts` under `process.cwd()` for exactly this reason:
|
|
45
|
+
* `process.cwd()` itself is a directory, and `dirname(process.cwd())`
|
|
46
|
+
* would search cwd's PARENT.
|
|
47
|
+
*/
|
|
48
|
+
readonly flowPath?: string;
|
|
49
|
+
/** Passed straight through to classifyOutcome (cli/run.ts) for f.agent's wait. */
|
|
50
|
+
readonly signal?: RunLifecycleOptions['signal'];
|
|
51
|
+
readonly onWait?: RunLifecycleOptions['onWait'];
|
|
52
|
+
}
|
|
53
|
+
export declare function executeAuthoredFlow<Input = undefined>(handle: FlowHandle, journal: JournalClient, input?: Input, options?: ExecuteAuthoredFlowOptions): Promise<AuthoredFlowExecutionResult>;
|
|
28
54
|
//# sourceMappingURL=authored-flow-executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-executor.d.ts","sourceRoot":"","sources":["../src/authored-flow-executor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authored-flow-executor.d.ts","sourceRoot":"","sources":["../src/authored-flow-executor.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAI9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAmB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EACL,0BAA0B,EAC1B,KAAK,8BAA8B,EACpC,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,gBAAgB,IAAI,wBAAwB,EAC5C,mBAAmB,IAAI,2BAA2B,EAEnD,MAAM,eAAe,CAAC;AAqBvB,OAAO,EAAE,0BAA0B,EAAE,KAAK,8BAA8B,EAAE,CAAC;AAW3E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,EAAE,wBAAwB,CAAC;CACrD;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,gBAAgB,EAAE,2BAA2B,CAAC;IACvD,QAAQ,CAAC,YAAY,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC3D;AASD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAC3C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;CACjD;AAED,wBAAsB,mBAAmB,CAAC,KAAK,GAAG,SAAS,EACzD,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,KAAK,EACb,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,2BAA2B,CAAC,CA6PtC"}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
import { COMPLETION_REASONS, RUN_COMPLETION_REASONS, } from '@relayflows/surface';
|
|
2
|
+
import { join } from 'node:path';
|
|
2
3
|
import { compileSpec, toKernelSpec } from './compile.js';
|
|
3
4
|
import { getAuthoredFlowDefinition } from './authored-flow.js';
|
|
5
|
+
import { checkAuthoredFlow } from './cli/check.js';
|
|
6
|
+
import { classifyOutcome } from './cli/run.js';
|
|
4
7
|
import { AuthoredFlowExecutionError, } from './authored-flow-error.js';
|
|
5
8
|
import { AuthoredFlowOperation, stopAuthoredOperations, verifyAuthoredOperations, } from './authored-flow-operation.js';
|
|
6
9
|
import { AuthoredFlowLifecycle } from './authored-flow-lifecycle.js';
|
|
7
10
|
import { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
8
11
|
export { AuthoredFlowExecutionError };
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `f.done("success")`. Every run and
|
|
16
|
-
* the terminal marker is a compiled deterministic spec submitted through
|
|
17
|
-
* `JournalClient`; values are read back from `step.completed` journal entries.
|
|
18
|
-
* Unsupported headers, verbs, gates, or completion lowering fail closed.
|
|
13
|
+
* Matches the `"path/glob: readonly"` / `"path/glob: readwrite"` shorthand
|
|
14
|
+
* shown in docs/SURFACE.md and the examples — the only shape a workspace
|
|
15
|
+
* string could plausibly declare a permission in. No parser anywhere in this
|
|
16
|
+
* package turns that annotation into a real restriction, so `lowerAgent`
|
|
17
|
+
* refuses rather than silently accepting and ignoring it.
|
|
19
18
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const WORKSPACE_PERMISSION_ANNOTATION = /:\s*(readonly|readwrite)\s*$/i;
|
|
20
|
+
export async function executeAuthoredFlow(handle, journal, input, options = {}) {
|
|
21
|
+
const getDefinition = options.getDefinition ?? getAuthoredFlowDefinition;
|
|
22
|
+
const flowPath = options.flowPath ?? join(process.cwd(), 'flow.ts');
|
|
23
|
+
// Named separately from `options` because `lowerAgent` below has its own,
|
|
24
|
+
// differently-typed `options: AgentOptions` parameter that shadows this one.
|
|
25
|
+
const waitOptions = {
|
|
26
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
27
|
+
...(options.onWait !== undefined ? { onWait: options.onWait } : {}),
|
|
28
|
+
};
|
|
29
|
+
const definition = getDefinition(handle);
|
|
22
30
|
const headerFields = Object.keys(definition.header);
|
|
23
31
|
if (headerFields.length > 0) {
|
|
24
32
|
throw new AuthoredFlowExecutionError('unsupported_header', `flow "${definition.name}" uses unsupported header fields: ${headerFields.join(', ')}`);
|
|
@@ -37,6 +45,74 @@ export async function executeAuthoredFlow(handle, journal, input) {
|
|
|
37
45
|
const outcome = await journal.runStart(spec);
|
|
38
46
|
return readSuccessfulOutput(journal, outcome, id, journalSteps);
|
|
39
47
|
};
|
|
48
|
+
// `name` (the first f.agent argument, e.g. "fixer") is not wired to the
|
|
49
|
+
// kernel's `agent` field: that field selects a NAMED declaration from
|
|
50
|
+
// `FlowSpec.agents`, and this executor refuses every non-empty header
|
|
51
|
+
// (see the top of this function) — an authored flow has no way to declare
|
|
52
|
+
// one today. `name` is kept only for step-id readability; CLI selection
|
|
53
|
+
// goes through the project's flows.json default below, same as it does
|
|
54
|
+
// for a bare `type: agent` YAML step with no explicit `cli`.
|
|
55
|
+
const lowerAgent = async (id, options) => {
|
|
56
|
+
if (options.workspace !== undefined && WORKSPACE_PERMISSION_ANNOTATION.test(options.workspace)) {
|
|
57
|
+
throw new AuthoredFlowExecutionError('unsupported_workspace_permission', `flow "${definition.name}" step "${id}": workspace "${options.workspace}" declares a `
|
|
58
|
+
+ 'permission annotation ("...: readonly" / "...: readwrite"), but nothing enforces it — '
|
|
59
|
+
+ 'no parser anywhere in this package turns that annotation into a real restriction '
|
|
60
|
+
+ '(kernel/DAEMON-LIFECYCLE.md\'s permission model is untouched by f.agent). '
|
|
61
|
+
+ 'Silently accepting and ignoring it would let a flow believe a restriction is in effect '
|
|
62
|
+
+ "when it is not. Declare a bare surface name (no trailing \": readonly\"/\": readwrite\") "
|
|
63
|
+
+ 'if you do not need enforcement, or use the declarative spec\'s `permissions` field, which is real.');
|
|
64
|
+
}
|
|
65
|
+
const authoring = {
|
|
66
|
+
version: SPEC_SCHEMA_VERSION,
|
|
67
|
+
name: `${definition.name}/${id}`,
|
|
68
|
+
steps: [{
|
|
69
|
+
id,
|
|
70
|
+
type: 'agent',
|
|
71
|
+
instruction: options.task,
|
|
72
|
+
...(options.workspace === undefined ? {} : {
|
|
73
|
+
surfaces: { workspace: [{ surface: options.workspace }] },
|
|
74
|
+
}),
|
|
75
|
+
}],
|
|
76
|
+
};
|
|
77
|
+
// The kernel never resolves a `cli` on its own — every declarative
|
|
78
|
+
// `flows run`/`flows check` binds it first via this exact function
|
|
79
|
+
// (cli/check.ts), searching for the nearest flows.json from `flowPath`
|
|
80
|
+
// and real-probing auth/model readiness. An authored agent step gets
|
|
81
|
+
// nothing for free just because it was declared in TS instead of YAML.
|
|
82
|
+
const { report, flow: resolved } = checkAuthoredFlow(authoring, flowPath);
|
|
83
|
+
if (!report.ok || resolved === undefined) {
|
|
84
|
+
const refusal = report.diagnostics.find((diagnostic) => diagnostic.severity === 'refusal');
|
|
85
|
+
throw new AuthoredFlowExecutionError('agent_cli_unresolved', refusal?.message
|
|
86
|
+
?? `flow "${definition.name}" step "${id}": no CLI could be resolved for f.agent `
|
|
87
|
+
+ `(searched for flows.json from "${flowPath}")`);
|
|
88
|
+
}
|
|
89
|
+
const spec = toKernelSpec(resolved);
|
|
90
|
+
const outcome = await journal.runStart(spec);
|
|
91
|
+
// Reuse the declarative CLI's own wait/classification (cli/run.ts) rather
|
|
92
|
+
// than a hand-rolled poll: `step.completed` and the run's own terminal
|
|
93
|
+
// state are appended as two SEPARATE actions (kernel/relayflowd-core/src/machine.rs
|
|
94
|
+
// completion_actions vs complete_run_actions), so a naive read right
|
|
95
|
+
// after runStart can race a real, valid completion — and a genuinely
|
|
96
|
+
// long-running agent has no reason to be bounded by anything other than
|
|
97
|
+
// its own worker's lease, which classifyOutcome already follows
|
|
98
|
+
// (renewing as the lease renews, per docs/SURFACE.md §5's WAITING
|
|
99
|
+
// [worker_lease] contract), never an unrelated fixed deadline.
|
|
100
|
+
const execution = await classifyOutcome(journal, 'run', outcome, report, '', waitOptions);
|
|
101
|
+
if (execution.exitCode === 3) {
|
|
102
|
+
const parked = execution.report.parkedStep;
|
|
103
|
+
throw new AuthoredFlowExecutionError('agent_parked', execution.report.diagnostics.at(-1)?.message
|
|
104
|
+
?? `flow "${definition.name}" step "${id}" parked`
|
|
105
|
+
+ (parked !== undefined ? ` (${parked.type})` : '')
|
|
106
|
+
+ ': no worker is attached to run it.', undefined, outcome.run_id);
|
|
107
|
+
}
|
|
108
|
+
if (execution.exitCode !== 0) {
|
|
109
|
+
const reason = execution.report.completionReason;
|
|
110
|
+
throw new AuthoredFlowExecutionError('step_failed', execution.report.diagnostics.at(-1)?.message
|
|
111
|
+
?? `flow "${definition.name}" step "${id}" did not complete successfully `
|
|
112
|
+
+ `(status: ${execution.report.status ?? 'unknown'})`, isSurfaceCompletionReason(reason) ? reason : undefined, outcome.run_id);
|
|
113
|
+
}
|
|
114
|
+
return readSuccessfulAgentOutput(journal, outcome.run_id, id, journalSteps);
|
|
115
|
+
};
|
|
40
116
|
const context = {
|
|
41
117
|
run(command) {
|
|
42
118
|
assertOperationAllowed('run', definition.name, requestedCompletion);
|
|
@@ -48,10 +124,11 @@ export async function executeAuthoredFlow(handle, journal, input) {
|
|
|
48
124
|
const id = `llm-${nextStep++}`;
|
|
49
125
|
return trackStep(authoredSteps, unsupportedStep(id, 'llm', () => assertOperationAllowed('llm', definition.name, requestedCompletion), lifecycle));
|
|
50
126
|
},
|
|
51
|
-
agent() {
|
|
127
|
+
agent(name, options) {
|
|
52
128
|
assertOperationAllowed('agent', definition.name, requestedCompletion);
|
|
129
|
+
void name; // step-id readability only — see the comment on lowerAgent.
|
|
53
130
|
const id = `agent-${nextStep++}`;
|
|
54
|
-
return trackStep(authoredSteps,
|
|
131
|
+
return trackStep(authoredSteps, new AuthoredFlowOperation(id, 'agent', () => assertOperationAllowed('agent', definition.name, requestedCompletion), () => lowerAgent(id, options), lifecycle));
|
|
55
132
|
},
|
|
56
133
|
human() {
|
|
57
134
|
assertOperationAllowed('human', definition.name, requestedCompletion);
|
|
@@ -157,26 +234,66 @@ function unsupportedCloud(assertOpen) {
|
|
|
157
234
|
},
|
|
158
235
|
});
|
|
159
236
|
}
|
|
160
|
-
|
|
161
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Shared by every `f.*` verb that lowers to one kernel step run in isolation:
|
|
239
|
+
* find its `step.completed` entry, record it, and refuse anything but a
|
|
240
|
+
* clean success before handing the raw `output` back for verb-specific
|
|
241
|
+
* extraction (a plain string for `f.run`, an `AgentResult` for `f.agent`).
|
|
242
|
+
*
|
|
243
|
+
* Callers are responsible for having already established that the RUN
|
|
244
|
+
* reached a terminal, successful state before calling this — `f.run`'s
|
|
245
|
+
* caller relies on `runStart`'s own immediate response (the kernel drives a
|
|
246
|
+
* deterministic step to completion inline, no race); `f.agent`'s caller
|
|
247
|
+
* relies on `classifyOutcome` (cli/run.ts) having already polled to a true
|
|
248
|
+
* terminal state. Given that, a single read from the start of this run's
|
|
249
|
+
* (small, single-step) journal is enough — no polling here, and no run
|
|
250
|
+
* outcome ever needs re-checking.
|
|
251
|
+
*/
|
|
252
|
+
async function readCompletedStepOutput(journal, runId, stepId, journalSteps) {
|
|
253
|
+
const entries = (await journal.journalRead(runId, 1)).entries;
|
|
162
254
|
const completed = entries.find((entry) => isStepCompleted(entry, stepId));
|
|
163
255
|
if (!isStepCompleted(completed, stepId)) {
|
|
164
|
-
throw protocolViolation(
|
|
256
|
+
throw protocolViolation(runId, `journal has no step.completed for "${stepId}"`);
|
|
165
257
|
}
|
|
166
258
|
const reason = completed.payload.completionReason;
|
|
167
|
-
journalSteps.push(Object.freeze({ id: stepId, runId
|
|
259
|
+
journalSteps.push(Object.freeze({ id: stepId, runId, completionReason: reason }));
|
|
168
260
|
if (reason !== 'success') {
|
|
169
|
-
throw new AuthoredFlowExecutionError('step_failed', `journal step "${stepId}" completed with ${reason}`, reason,
|
|
261
|
+
throw new AuthoredFlowExecutionError('step_failed', `journal step "${stepId}" completed with ${reason}`, reason, runId);
|
|
170
262
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const output =
|
|
263
|
+
return completed.payload.output;
|
|
264
|
+
}
|
|
265
|
+
async function readSuccessfulOutput(journal, outcome, stepId, journalSteps) {
|
|
266
|
+
const output = await readCompletedStepOutput(journal, outcome.run_id, stepId, journalSteps);
|
|
175
267
|
if (!isRecord(output) || typeof output['stdout_tail'] !== 'string') {
|
|
176
268
|
throw protocolViolation(outcome.run_id, `step "${stepId}" has no string stdout_tail`);
|
|
177
269
|
}
|
|
178
270
|
return output['stdout_tail'];
|
|
179
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* The kernel journals an agent step's raw `CliResult` shape
|
|
274
|
+
* (`exit_code`/`stdout_tail`/`stderr_tail`) — same as a deterministic step —
|
|
275
|
+
* UNLESS the CLI's stdout parsed as JSON, in which case `output` is that
|
|
276
|
+
* parsed object directly (worker.ts: `parseJsonOutput(result.stdout_tail) ??
|
|
277
|
+
* result`). Neither shape carries a real `artifacts` list today: nothing in
|
|
278
|
+
* the kernel or worker enumerates files an agent wrote, and `f.agent`'s
|
|
279
|
+
* `AgentOptions` has no `output` schema parameter for a CLI to target either
|
|
280
|
+
* (unlike the declarative `AgentStepSpec.output` field). `artifacts` is
|
|
281
|
+
* therefore always empty here — honest about what data exists, not a
|
|
282
|
+
* placeholder for something not yet wired.
|
|
283
|
+
*/
|
|
284
|
+
async function readSuccessfulAgentOutput(journal, runId, stepId, journalSteps) {
|
|
285
|
+
const output = await readCompletedStepOutput(journal, runId, stepId, journalSteps);
|
|
286
|
+
if (!isRecord(output)) {
|
|
287
|
+
throw protocolViolation(runId, `step "${stepId}" produced a non-object output`);
|
|
288
|
+
}
|
|
289
|
+
if (typeof output['stdout_tail'] === 'string') {
|
|
290
|
+
return { summary: output['stdout_tail'], artifacts: [] };
|
|
291
|
+
}
|
|
292
|
+
// The CLI's stdout parsed as JSON, so `output` is that value, not a
|
|
293
|
+
// CliResult. Fall back to a stable, inspectable summary rather than
|
|
294
|
+
// refusing a run whose agent step genuinely succeeded.
|
|
295
|
+
return { summary: JSON.stringify(output), artifacts: [] };
|
|
296
|
+
}
|
|
180
297
|
function isStepCompleted(value, stepId) {
|
|
181
298
|
if (!isRecord(value) || value['entry_type'] !== 'step.completed' || value['step_id'] !== stepId) {
|
|
182
299
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-executor.js","sourceRoot":"","sources":["../src/authored-flow-executor.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"authored-flow-executor.js","sourceRoot":"","sources":["../src/authored-flow-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import { type FlowHandle } from './authored-flow.js';
|
|
1
|
+
import { getAuthoredFlowDefinition, type AuthoredFlowDefinition, type FlowHandle } from './authored-flow.js';
|
|
2
2
|
export declare class AuthoredFlowLoadError extends Error {
|
|
3
3
|
constructor(message: string);
|
|
4
4
|
}
|
|
5
|
+
/** Same signature as `getAuthoredFlowDefinition`, resolved from wherever a flow was loaded. */
|
|
6
|
+
export type GetFlowDefinition = <Input = unknown>(handle: FlowHandle) => AuthoredFlowDefinition<Input>;
|
|
7
|
+
export interface LoadedAuthoredFlow {
|
|
8
|
+
readonly handle: FlowHandle;
|
|
9
|
+
/**
|
|
10
|
+
* Bound to the SAME `@relayflows/surface` module instance the flow file
|
|
11
|
+
* itself imported `flow` from — see the comment on
|
|
12
|
+
* {@link resolveGetFlowDefinition}. Callers that go on to execute the flow
|
|
13
|
+
* (not just validate it) must keep using this, not the SDK's own static
|
|
14
|
+
* `getAuthoredFlowDefinition` import.
|
|
15
|
+
*/
|
|
16
|
+
readonly getDefinition: GetFlowDefinition;
|
|
17
|
+
}
|
|
5
18
|
/** Import and validate a direct-run module without executing its authored body. */
|
|
6
|
-
export declare function loadAuthoredFlow(path: string): Promise<
|
|
19
|
+
export declare function loadAuthoredFlow(path: string): Promise<LoadedAuthoredFlow>;
|
|
20
|
+
export { getAuthoredFlowDefinition };
|
|
7
21
|
//# sourceMappingURL=authored-flow-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-loader.d.ts","sourceRoot":"","sources":["../src/authored-flow-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authored-flow-loader.d.ts","sourceRoot":"","sources":["../src/authored-flow-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,+FAA+F;AAC/F,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,KAAK,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAEvG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;CAC3C;AAED,mFAAmF;AACnF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BhF;AAoDD,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { accessSync, constants } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { resolve } from 'node:path';
|
|
3
4
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { getAuthoredFlowDefinition } from './authored-flow.js';
|
|
5
|
+
import { getAuthoredFlowDefinition, } from './authored-flow.js';
|
|
5
6
|
export class AuthoredFlowLoadError extends Error {
|
|
6
7
|
constructor(message) {
|
|
7
8
|
super(message);
|
|
@@ -24,15 +25,58 @@ export async function loadAuthoredFlow(path) {
|
|
|
24
25
|
catch (error) {
|
|
25
26
|
throw new AuthoredFlowLoadError(`Flow "${path}" could not be imported: ${errorMessage(error)}`);
|
|
26
27
|
}
|
|
28
|
+
const getDefinition = await resolveGetFlowDefinition(absolutePath, path);
|
|
27
29
|
const handle = authoredModule['default'];
|
|
28
30
|
try {
|
|
29
|
-
|
|
31
|
+
getDefinition(handle);
|
|
30
32
|
}
|
|
31
33
|
catch (error) {
|
|
32
34
|
throw new AuthoredFlowLoadError(`Flow "${path}" must default-export flow(...): ${errorMessage(error)}`);
|
|
33
35
|
}
|
|
34
|
-
return handle;
|
|
36
|
+
return { handle, getDefinition };
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* `getFlowDefinition` recognizes a handle by object identity in a `WeakMap`
|
|
40
|
+
* scoped to whichever copy of `@relayflows/surface` created it — deliberately:
|
|
41
|
+
* that is what makes a handle unforgeable (surface/tests/flow.test.ts
|
|
42
|
+
* "refuses malformed and forged handles at the runtime boundary" locks this
|
|
43
|
+
* in, including against a well-known-symbol forgery, so this must not be
|
|
44
|
+
* "fixed" by switching that map to a symbol-tagged property instead).
|
|
45
|
+
*
|
|
46
|
+
* An author's `.flow.ts` almost never lives inside this monorepo. It
|
|
47
|
+
* resolves `@relayflows/surface` from ITS OWN `node_modules` — a physically
|
|
48
|
+
* different module instance than the one this SDK package statically
|
|
49
|
+
* imports for itself, so the SDK's own copy's `WeakMap` never has the
|
|
50
|
+
* entry the flow file's copy wrote. The fix is not a new identity
|
|
51
|
+
* mechanism; it is asking the SAME question Node itself would ask: resolve
|
|
52
|
+
* `@relayflows/surface/runtime` from the flow file's own location, exactly
|
|
53
|
+
* as the flow file's `import { flow } from "@relayflows/surface"`
|
|
54
|
+
* already did, and use THAT copy's `getFlowDefinition`. Since the flow
|
|
55
|
+
* module already imported successfully (by the time this runs), a
|
|
56
|
+
* compatible `@relayflows/surface` is provably resolvable from this same
|
|
57
|
+
* anchor.
|
|
58
|
+
*/
|
|
59
|
+
async function resolveGetFlowDefinition(absolutePath, displayPath) {
|
|
60
|
+
const require = createRequire(pathToFileURL(absolutePath));
|
|
61
|
+
let resolvedRuntimePath;
|
|
62
|
+
try {
|
|
63
|
+
resolvedRuntimePath = require.resolve('@relayflows/surface/runtime');
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new AuthoredFlowLoadError(`Flow "${displayPath}" imports @relayflows/surface, but @relayflows/surface/runtime `
|
|
67
|
+
+ `could not be resolved from the same location: ${errorMessage(error)}`);
|
|
68
|
+
}
|
|
69
|
+
const runtimeModule = await import(pathToFileURL(resolvedRuntimePath).href);
|
|
70
|
+
if (typeof runtimeModule.getFlowDefinition !== 'function') {
|
|
71
|
+
throw new AuthoredFlowLoadError(`Flow "${displayPath}": the @relayflows/surface/runtime resolved from its location `
|
|
72
|
+
+ 'does not export getFlowDefinition — check its @relayflows/surface version.');
|
|
73
|
+
}
|
|
74
|
+
return runtimeModule.getFlowDefinition;
|
|
75
|
+
}
|
|
76
|
+
// Exported for callers (internal SDK tests, and any co-located flow that is
|
|
77
|
+
// provably the same `@relayflows/surface` instance as this package) that
|
|
78
|
+
// have no need to resolve a separate copy.
|
|
79
|
+
export { getAuthoredFlowDefinition };
|
|
36
80
|
function errorMessage(error) {
|
|
37
81
|
return error instanceof Error ? error.message : 'unknown authored-flow error';
|
|
38
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authored-flow-loader.js","sourceRoot":"","sources":["../src/authored-flow-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"authored-flow-loader.js","sourceRoot":"","sources":["../src/authored-flow-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,yBAAyB,GAG1B,MAAM,oBAAoB,CAAC;AAE5B,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAiBD,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,qBAAqB,CAAC,SAAS,IAAI,oBAAoB,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,cAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,IAAI,CAA4B,CAAC;IAC7F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,4BAA4B,YAAY,CAAC,KAAK,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAe,CAAC;IACvD,IAAI,CAAC;QACH,aAAa,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,oCAAoC,YAAY,CAAC,KAAK,CAAC,EAAE,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,KAAK,UAAU,wBAAwB,CACrC,YAAoB,EACpB,WAAmB;IAEnB,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3D,IAAI,mBAA2B,CAAC;IAChC,IAAI,CAAC;QACH,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,qBAAqB,CAC7B,SAAS,WAAW,iEAAiE;cACjF,iDAAiD,YAAY,CAAC,KAAK,CAAC,EAAE,CAC3E,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAEzE,CAAC;IACF,IAAI,OAAO,aAAa,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;QAC1D,MAAM,IAAI,qBAAqB,CAC7B,SAAS,WAAW,gEAAgE;cAChF,4EAA4E,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,aAAa,CAAC,iBAAsC,CAAC;AAC9D,CAAC;AAED,4EAA4E;AAC5E,yEAAyE;AACzE,2CAA2C;AAC3C,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAErC,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;AAChF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-run.d.ts","sourceRoot":"","sources":["../../src/cli/direct-run.ts"],"names":[],"mappings":"AAQA,OAAO,EAML,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAEzB,MAAM,UAAU,CAAC;AAElB,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"direct-run.d.ts","sourceRoot":"","sources":["../../src/cli/direct-run.ts"],"names":[],"mappings":"AAQA,OAAO,EAML,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAEzB,MAAM,UAAU,CAAC;AAElB,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,YAAY,CAAC,CAgGvB"}
|
package/dist/cli/direct-run.js
CHANGED
|
@@ -26,8 +26,13 @@ export async function runDirectFlow(path, inputArgument, dataDir, options = {})
|
|
|
26
26
|
if (connected !== undefined)
|
|
27
27
|
return connected;
|
|
28
28
|
try {
|
|
29
|
-
const handle = await loadAuthoredFlow(path);
|
|
30
|
-
const result = await executeAuthoredFlow(handle, client, input
|
|
29
|
+
const { handle, getDefinition } = await loadAuthoredFlow(path);
|
|
30
|
+
const result = await executeAuthoredFlow(handle, client, input, {
|
|
31
|
+
getDefinition,
|
|
32
|
+
flowPath: path,
|
|
33
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
34
|
+
...(options.onWait !== undefined ? { onWait: options.onWait } : {}),
|
|
35
|
+
});
|
|
31
36
|
const terminal = result.journalSteps.at(-1);
|
|
32
37
|
if (terminal === undefined) {
|
|
33
38
|
return protocolFailure('run', base, socketPath, new Error(`authored flow "${result.name}" completed without a journal step`));
|
|
@@ -46,8 +51,21 @@ export async function runDirectFlow(path, inputArgument, dataDir, options = {})
|
|
|
46
51
|
};
|
|
47
52
|
}
|
|
48
53
|
catch (error) {
|
|
54
|
+
// `agent_cli_unresolved` and `unsupported_workspace_permission` are
|
|
55
|
+
// preflight-shaped refusals, not protocol failures — `flows check`
|
|
56
|
+
// returns exit 2 for the equivalent declarative-spec failures, and this
|
|
57
|
+
// path should match it. Known gap, not solved here: if a `f.run` before
|
|
58
|
+
// the failing `f.agent` already journaled real work, this still reports
|
|
59
|
+
// as a clean refusal — true upfront preflight would need to know every
|
|
60
|
+
// `f.agent` call an imperative TS body will make before running any of
|
|
61
|
+
// it, which isn't knowable without running the body (see the comment on
|
|
62
|
+
// ExecuteAuthoredFlowOptions and this project's own examples/README for
|
|
63
|
+
// the same limitation already documented elsewhere).
|
|
49
64
|
if (error instanceof AuthoredFlowLoadError
|
|
50
|
-
|| (error instanceof AuthoredFlowExecutionError
|
|
65
|
+
|| (error instanceof AuthoredFlowExecutionError
|
|
66
|
+
&& (error.code === 'unsupported_header'
|
|
67
|
+
|| error.code === 'agent_cli_unresolved'
|
|
68
|
+
|| error.code === 'unsupported_workspace_permission'))) {
|
|
51
69
|
return {
|
|
52
70
|
exitCode: 2,
|
|
53
71
|
report: {
|
|
@@ -59,6 +77,23 @@ export async function runDirectFlow(path, inputArgument, dataDir, options = {})
|
|
|
59
77
|
},
|
|
60
78
|
};
|
|
61
79
|
}
|
|
80
|
+
if (error instanceof AuthoredFlowExecutionError && error.code === 'agent_parked') {
|
|
81
|
+
return {
|
|
82
|
+
exitCode: 3,
|
|
83
|
+
report: {
|
|
84
|
+
...base,
|
|
85
|
+
ok: false,
|
|
86
|
+
runId: error.runId,
|
|
87
|
+
socketPath,
|
|
88
|
+
status: 'parked',
|
|
89
|
+
diagnostics: [...base.diagnostics, {
|
|
90
|
+
severity: 'parked',
|
|
91
|
+
kind: 'run_parked',
|
|
92
|
+
message: error.message,
|
|
93
|
+
}],
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
62
97
|
const runId = error instanceof AuthoredFlowExecutionError ? error.runId : undefined;
|
|
63
98
|
return protocolFailure('run', base, socketPath, error, runId);
|
|
64
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"direct-run.js","sourceRoot":"","sources":["../../src/cli/direct-run.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,OAAO,EACP,WAAW,EACX,eAAe,EACf,eAAe,EACf,SAAS,GAIV,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,aAAiC,EACjC,OAAe,EACf,UAA+B,EAAE;IAEjC,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,IAAI,EAAE,eAAwB;YAC9B,OAAO,EAAE,mCAAmC;SAC7C,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,eAAe,CAAC,KAAK,EAAE,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;SAClE,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,IAAI,GAAc,EAAE,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACvE,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"direct-run.js","sourceRoot":"","sources":["../../src/cli/direct-run.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.8",
|
|
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",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@relayflows/surface": "2.0.
|
|
33
|
+
"@relayflows/surface": "2.0.8",
|
|
34
34
|
"@types/js-yaml": "^4.0.9",
|
|
35
35
|
"ajv": "^8.17.1",
|
|
36
36
|
"ajv-draft-04": "^1.0.0",
|
|
@@ -4,6 +4,8 @@ import type {
|
|
|
4
4
|
} from './protocol.js';
|
|
5
5
|
|
|
6
6
|
export type AuthoredFlowExecutionErrorCode =
|
|
7
|
+
| 'agent_cli_unresolved'
|
|
8
|
+
| 'agent_parked'
|
|
7
9
|
| 'duplicate_completion'
|
|
8
10
|
| 'journal_protocol_violation'
|
|
9
11
|
| 'missing_completion'
|
|
@@ -15,6 +17,7 @@ export type AuthoredFlowExecutionErrorCode =
|
|
|
15
17
|
| 'unsupported_header'
|
|
16
18
|
| 'unsettled_derived_work'
|
|
17
19
|
| 'unsupported_promise_lifecycle'
|
|
20
|
+
| 'unsupported_workspace_permission'
|
|
18
21
|
| 'unawaited_step'
|
|
19
22
|
| 'unsupported_verb';
|
|
20
23
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
COMPLETION_REASONS,
|
|
3
3
|
RUN_COMPLETION_REASONS,
|
|
4
|
+
type AgentOptions,
|
|
4
5
|
type AgentResult,
|
|
5
6
|
type CloudHelper,
|
|
6
7
|
type CompletionReason as SurfaceCompletionReason,
|
|
@@ -9,8 +10,13 @@ import {
|
|
|
9
10
|
type Step,
|
|
10
11
|
} from '@relayflows/surface';
|
|
11
12
|
import type { FlowHandle } from '@relayflows/surface/runtime';
|
|
13
|
+
import { join } from 'node:path';
|
|
12
14
|
import { compileSpec, toKernelSpec } from './compile.js';
|
|
13
15
|
import { getAuthoredFlowDefinition } from './authored-flow.js';
|
|
16
|
+
import type { GetFlowDefinition } from './authored-flow-loader.js';
|
|
17
|
+
import { checkAuthoredFlow } from './cli/check.js';
|
|
18
|
+
import { classifyOutcome, type RunLifecycleOptions } from './cli/run.js';
|
|
19
|
+
import type { PreflightDiagnostic } from './preflight.js';
|
|
14
20
|
import {
|
|
15
21
|
AuthoredFlowExecutionError,
|
|
16
22
|
type AuthoredFlowExecutionErrorCode,
|
|
@@ -27,7 +33,7 @@ import type {
|
|
|
27
33
|
RunCompletionReason as ProtocolRunCompletionReason,
|
|
28
34
|
RunOutcome,
|
|
29
35
|
} from './protocol.js';
|
|
30
|
-
import { SPEC_SCHEMA_VERSION } from './spec.js';
|
|
36
|
+
import { SPEC_SCHEMA_VERSION, type FlowSpec } from './spec.js';
|
|
31
37
|
|
|
32
38
|
type Assert<T extends true> = T;
|
|
33
39
|
type Equal<A, B> = [A] extends [B]
|
|
@@ -49,6 +55,15 @@ type EveryRunCompletionReasonIsAcceptedByDone = Assert<
|
|
|
49
55
|
|
|
50
56
|
export { AuthoredFlowExecutionError, type AuthoredFlowExecutionErrorCode };
|
|
51
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Matches the `"path/glob: readonly"` / `"path/glob: readwrite"` shorthand
|
|
60
|
+
* shown in docs/SURFACE.md and the examples — the only shape a workspace
|
|
61
|
+
* string could plausibly declare a permission in. No parser anywhere in this
|
|
62
|
+
* package turns that annotation into a real restriction, so `lowerAgent`
|
|
63
|
+
* refuses rather than silently accepting and ignoring it.
|
|
64
|
+
*/
|
|
65
|
+
const WORKSPACE_PERMISSION_ANNOTATION = /:\s*(readonly|readwrite)\s*$/i;
|
|
66
|
+
|
|
52
67
|
export interface AuthoredFlowJournalStep {
|
|
53
68
|
readonly id: string;
|
|
54
69
|
readonly runId: string;
|
|
@@ -79,12 +94,46 @@ type JournalStepUsesStepCompletionReason = Assert<
|
|
|
79
94
|
* `JournalClient`; values are read back from `step.completed` journal entries.
|
|
80
95
|
* Unsupported headers, verbs, gates, or completion lowering fail closed.
|
|
81
96
|
*/
|
|
97
|
+
export interface ExecuteAuthoredFlowOptions {
|
|
98
|
+
/**
|
|
99
|
+
* Defaults to this package's own static import — correct for every
|
|
100
|
+
* existing (internal, single-instance) caller. A flow loaded from an
|
|
101
|
+
* external path via `loadAuthoredFlow` must pass ITS resolved
|
|
102
|
+
* `getDefinition` instead; see authored-flow-loader.ts's comment on why.
|
|
103
|
+
*/
|
|
104
|
+
readonly getDefinition?: GetFlowDefinition;
|
|
105
|
+
/**
|
|
106
|
+
* The flow file's own path — passed straight to `checkAuthoredFlow`
|
|
107
|
+
* (cli/check.ts) so `f.agent` resolves a CLI the same way a declarative
|
|
108
|
+
* `type: agent` step does: nearest `flows.json`, real auth/model probing,
|
|
109
|
+
* canonicalized path. `checkAuthoredFlow` always does `dirname()` on this,
|
|
110
|
+
* matching `checkFlow`'s real `flows check <file>` contract — pass a FILE
|
|
111
|
+
* path, not a directory, or the search starts one level too high. Defaults
|
|
112
|
+
* to a synthetic `flow.ts` under `process.cwd()` for exactly this reason:
|
|
113
|
+
* `process.cwd()` itself is a directory, and `dirname(process.cwd())`
|
|
114
|
+
* would search cwd's PARENT.
|
|
115
|
+
*/
|
|
116
|
+
readonly flowPath?: string;
|
|
117
|
+
/** Passed straight through to classifyOutcome (cli/run.ts) for f.agent's wait. */
|
|
118
|
+
readonly signal?: RunLifecycleOptions['signal'];
|
|
119
|
+
readonly onWait?: RunLifecycleOptions['onWait'];
|
|
120
|
+
}
|
|
121
|
+
|
|
82
122
|
export async function executeAuthoredFlow<Input = undefined>(
|
|
83
123
|
handle: FlowHandle,
|
|
84
124
|
journal: JournalClient,
|
|
85
125
|
input?: Input,
|
|
126
|
+
options: ExecuteAuthoredFlowOptions = {},
|
|
86
127
|
): Promise<AuthoredFlowExecutionResult> {
|
|
87
|
-
const
|
|
128
|
+
const getDefinition = options.getDefinition ?? getAuthoredFlowDefinition;
|
|
129
|
+
const flowPath = options.flowPath ?? join(process.cwd(), 'flow.ts');
|
|
130
|
+
// Named separately from `options` because `lowerAgent` below has its own,
|
|
131
|
+
// differently-typed `options: AgentOptions` parameter that shadows this one.
|
|
132
|
+
const waitOptions: RunLifecycleOptions = {
|
|
133
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
134
|
+
...(options.onWait !== undefined ? { onWait: options.onWait } : {}),
|
|
135
|
+
};
|
|
136
|
+
const definition = getDefinition<Input>(handle);
|
|
88
137
|
const headerFields = Object.keys(definition.header);
|
|
89
138
|
if (headerFields.length > 0) {
|
|
90
139
|
throw new AuthoredFlowExecutionError(
|
|
@@ -112,6 +161,97 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
112
161
|
return readSuccessfulOutput(journal, outcome, id, journalSteps);
|
|
113
162
|
};
|
|
114
163
|
|
|
164
|
+
// `name` (the first f.agent argument, e.g. "fixer") is not wired to the
|
|
165
|
+
// kernel's `agent` field: that field selects a NAMED declaration from
|
|
166
|
+
// `FlowSpec.agents`, and this executor refuses every non-empty header
|
|
167
|
+
// (see the top of this function) — an authored flow has no way to declare
|
|
168
|
+
// one today. `name` is kept only for step-id readability; CLI selection
|
|
169
|
+
// goes through the project's flows.json default below, same as it does
|
|
170
|
+
// for a bare `type: agent` YAML step with no explicit `cli`.
|
|
171
|
+
const lowerAgent = async (
|
|
172
|
+
id: string,
|
|
173
|
+
options: AgentOptions,
|
|
174
|
+
): Promise<AgentResult> => {
|
|
175
|
+
if (options.workspace !== undefined && WORKSPACE_PERMISSION_ANNOTATION.test(options.workspace)) {
|
|
176
|
+
throw new AuthoredFlowExecutionError(
|
|
177
|
+
'unsupported_workspace_permission',
|
|
178
|
+
`flow "${definition.name}" step "${id}": workspace "${options.workspace}" declares a `
|
|
179
|
+
+ 'permission annotation ("...: readonly" / "...: readwrite"), but nothing enforces it — '
|
|
180
|
+
+ 'no parser anywhere in this package turns that annotation into a real restriction '
|
|
181
|
+
+ '(kernel/DAEMON-LIFECYCLE.md\'s permission model is untouched by f.agent). '
|
|
182
|
+
+ 'Silently accepting and ignoring it would let a flow believe a restriction is in effect '
|
|
183
|
+
+ "when it is not. Declare a bare surface name (no trailing \": readonly\"/\": readwrite\") "
|
|
184
|
+
+ 'if you do not need enforcement, or use the declarative spec\'s `permissions` field, which is real.',
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const authoring: FlowSpec = {
|
|
188
|
+
version: SPEC_SCHEMA_VERSION,
|
|
189
|
+
name: `${definition.name}/${id}`,
|
|
190
|
+
steps: [{
|
|
191
|
+
id,
|
|
192
|
+
type: 'agent',
|
|
193
|
+
instruction: options.task,
|
|
194
|
+
...(options.workspace === undefined ? {} : {
|
|
195
|
+
surfaces: { workspace: [{ surface: options.workspace }] },
|
|
196
|
+
}),
|
|
197
|
+
}],
|
|
198
|
+
};
|
|
199
|
+
// The kernel never resolves a `cli` on its own — every declarative
|
|
200
|
+
// `flows run`/`flows check` binds it first via this exact function
|
|
201
|
+
// (cli/check.ts), searching for the nearest flows.json from `flowPath`
|
|
202
|
+
// and real-probing auth/model readiness. An authored agent step gets
|
|
203
|
+
// nothing for free just because it was declared in TS instead of YAML.
|
|
204
|
+
const { report, flow: resolved } = checkAuthoredFlow(authoring, flowPath);
|
|
205
|
+
if (!report.ok || resolved === undefined) {
|
|
206
|
+
const refusal = report.diagnostics.find(
|
|
207
|
+
(diagnostic): diagnostic is PreflightDiagnostic & { severity: 'refusal' } =>
|
|
208
|
+
diagnostic.severity === 'refusal',
|
|
209
|
+
);
|
|
210
|
+
throw new AuthoredFlowExecutionError(
|
|
211
|
+
'agent_cli_unresolved',
|
|
212
|
+
refusal?.message
|
|
213
|
+
?? `flow "${definition.name}" step "${id}": no CLI could be resolved for f.agent `
|
|
214
|
+
+ `(searched for flows.json from "${flowPath}")`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
const spec = toKernelSpec(resolved);
|
|
218
|
+
const outcome = await journal.runStart(spec);
|
|
219
|
+
// Reuse the declarative CLI's own wait/classification (cli/run.ts) rather
|
|
220
|
+
// than a hand-rolled poll: `step.completed` and the run's own terminal
|
|
221
|
+
// state are appended as two SEPARATE actions (kernel/relayflowd-core/src/machine.rs
|
|
222
|
+
// completion_actions vs complete_run_actions), so a naive read right
|
|
223
|
+
// after runStart can race a real, valid completion — and a genuinely
|
|
224
|
+
// long-running agent has no reason to be bounded by anything other than
|
|
225
|
+
// its own worker's lease, which classifyOutcome already follows
|
|
226
|
+
// (renewing as the lease renews, per docs/SURFACE.md §5's WAITING
|
|
227
|
+
// [worker_lease] contract), never an unrelated fixed deadline.
|
|
228
|
+
const execution = await classifyOutcome(journal, 'run', outcome, report, '', waitOptions);
|
|
229
|
+
if (execution.exitCode === 3) {
|
|
230
|
+
const parked = execution.report.parkedStep;
|
|
231
|
+
throw new AuthoredFlowExecutionError(
|
|
232
|
+
'agent_parked',
|
|
233
|
+
execution.report.diagnostics.at(-1)?.message
|
|
234
|
+
?? `flow "${definition.name}" step "${id}" parked`
|
|
235
|
+
+ (parked !== undefined ? ` (${parked.type})` : '')
|
|
236
|
+
+ ': no worker is attached to run it.',
|
|
237
|
+
undefined,
|
|
238
|
+
outcome.run_id,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (execution.exitCode !== 0) {
|
|
242
|
+
const reason = execution.report.completionReason;
|
|
243
|
+
throw new AuthoredFlowExecutionError(
|
|
244
|
+
'step_failed',
|
|
245
|
+
execution.report.diagnostics.at(-1)?.message
|
|
246
|
+
?? `flow "${definition.name}" step "${id}" did not complete successfully `
|
|
247
|
+
+ `(status: ${execution.report.status ?? 'unknown'})`,
|
|
248
|
+
isSurfaceCompletionReason(reason) ? reason : undefined,
|
|
249
|
+
outcome.run_id,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return readSuccessfulAgentOutput(journal, outcome.run_id, id, journalSteps);
|
|
253
|
+
};
|
|
254
|
+
|
|
115
255
|
const context: Ctx = {
|
|
116
256
|
run(command) {
|
|
117
257
|
assertOperationAllowed('run', definition.name, requestedCompletion);
|
|
@@ -134,13 +274,15 @@ export async function executeAuthoredFlow<Input = undefined>(
|
|
|
134
274
|
lifecycle,
|
|
135
275
|
));
|
|
136
276
|
},
|
|
137
|
-
agent() {
|
|
277
|
+
agent(name, options) {
|
|
138
278
|
assertOperationAllowed('agent', definition.name, requestedCompletion);
|
|
279
|
+
void name; // step-id readability only — see the comment on lowerAgent.
|
|
139
280
|
const id = `agent-${nextStep++}`;
|
|
140
|
-
return trackStep(authoredSteps,
|
|
281
|
+
return trackStep(authoredSteps, new AuthoredFlowOperation(
|
|
141
282
|
id,
|
|
142
283
|
'agent',
|
|
143
284
|
() => assertOperationAllowed('agent', definition.name, requestedCompletion),
|
|
285
|
+
() => lowerAgent(id, options),
|
|
144
286
|
lifecycle,
|
|
145
287
|
));
|
|
146
288
|
},
|
|
@@ -286,42 +428,90 @@ function unsupportedCloud(assertOpen: () => void): CloudHelper {
|
|
|
286
428
|
}) as CloudHelper;
|
|
287
429
|
}
|
|
288
430
|
|
|
289
|
-
|
|
431
|
+
/**
|
|
432
|
+
* Shared by every `f.*` verb that lowers to one kernel step run in isolation:
|
|
433
|
+
* find its `step.completed` entry, record it, and refuse anything but a
|
|
434
|
+
* clean success before handing the raw `output` back for verb-specific
|
|
435
|
+
* extraction (a plain string for `f.run`, an `AgentResult` for `f.agent`).
|
|
436
|
+
*
|
|
437
|
+
* Callers are responsible for having already established that the RUN
|
|
438
|
+
* reached a terminal, successful state before calling this — `f.run`'s
|
|
439
|
+
* caller relies on `runStart`'s own immediate response (the kernel drives a
|
|
440
|
+
* deterministic step to completion inline, no race); `f.agent`'s caller
|
|
441
|
+
* relies on `classifyOutcome` (cli/run.ts) having already polled to a true
|
|
442
|
+
* terminal state. Given that, a single read from the start of this run's
|
|
443
|
+
* (small, single-step) journal is enough — no polling here, and no run
|
|
444
|
+
* outcome ever needs re-checking.
|
|
445
|
+
*/
|
|
446
|
+
async function readCompletedStepOutput(
|
|
290
447
|
journal: JournalClient,
|
|
291
|
-
|
|
448
|
+
runId: string,
|
|
292
449
|
stepId: string,
|
|
293
450
|
journalSteps: AuthoredFlowJournalStep[],
|
|
294
|
-
): Promise<
|
|
295
|
-
const entries = (await journal.journalRead(
|
|
451
|
+
): Promise<unknown> {
|
|
452
|
+
const entries = (await journal.journalRead(runId, 1)).entries;
|
|
296
453
|
const completed = entries.find((entry) => isStepCompleted(entry, stepId));
|
|
297
454
|
if (!isStepCompleted(completed, stepId)) {
|
|
298
|
-
throw protocolViolation(
|
|
455
|
+
throw protocolViolation(runId, `journal has no step.completed for "${stepId}"`);
|
|
299
456
|
}
|
|
300
457
|
|
|
301
458
|
const reason = completed.payload.completionReason;
|
|
302
|
-
journalSteps.push(Object.freeze({ id: stepId, runId
|
|
459
|
+
journalSteps.push(Object.freeze({ id: stepId, runId, completionReason: reason }));
|
|
303
460
|
if (reason !== 'success') {
|
|
304
461
|
throw new AuthoredFlowExecutionError(
|
|
305
462
|
'step_failed',
|
|
306
463
|
`journal step "${stepId}" completed with ${reason}`,
|
|
307
464
|
reason,
|
|
308
|
-
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
if (outcome.status !== 'completed' || outcome.completion_reason !== 'success') {
|
|
312
|
-
throw protocolViolation(
|
|
313
|
-
outcome.run_id,
|
|
314
|
-
`successful step entry conflicts with run outcome ${outcome.status}/${String(outcome.completion_reason)}`,
|
|
465
|
+
runId,
|
|
315
466
|
);
|
|
316
467
|
}
|
|
468
|
+
return completed.payload.output;
|
|
469
|
+
}
|
|
317
470
|
|
|
318
|
-
|
|
471
|
+
async function readSuccessfulOutput(
|
|
472
|
+
journal: JournalClient,
|
|
473
|
+
outcome: RunOutcome,
|
|
474
|
+
stepId: string,
|
|
475
|
+
journalSteps: AuthoredFlowJournalStep[],
|
|
476
|
+
): Promise<string> {
|
|
477
|
+
const output = await readCompletedStepOutput(journal, outcome.run_id, stepId, journalSteps);
|
|
319
478
|
if (!isRecord(output) || typeof output['stdout_tail'] !== 'string') {
|
|
320
479
|
throw protocolViolation(outcome.run_id, `step "${stepId}" has no string stdout_tail`);
|
|
321
480
|
}
|
|
322
481
|
return output['stdout_tail'];
|
|
323
482
|
}
|
|
324
483
|
|
|
484
|
+
/**
|
|
485
|
+
* The kernel journals an agent step's raw `CliResult` shape
|
|
486
|
+
* (`exit_code`/`stdout_tail`/`stderr_tail`) — same as a deterministic step —
|
|
487
|
+
* UNLESS the CLI's stdout parsed as JSON, in which case `output` is that
|
|
488
|
+
* parsed object directly (worker.ts: `parseJsonOutput(result.stdout_tail) ??
|
|
489
|
+
* result`). Neither shape carries a real `artifacts` list today: nothing in
|
|
490
|
+
* the kernel or worker enumerates files an agent wrote, and `f.agent`'s
|
|
491
|
+
* `AgentOptions` has no `output` schema parameter for a CLI to target either
|
|
492
|
+
* (unlike the declarative `AgentStepSpec.output` field). `artifacts` is
|
|
493
|
+
* therefore always empty here — honest about what data exists, not a
|
|
494
|
+
* placeholder for something not yet wired.
|
|
495
|
+
*/
|
|
496
|
+
async function readSuccessfulAgentOutput(
|
|
497
|
+
journal: JournalClient,
|
|
498
|
+
runId: string,
|
|
499
|
+
stepId: string,
|
|
500
|
+
journalSteps: AuthoredFlowJournalStep[],
|
|
501
|
+
): Promise<AgentResult> {
|
|
502
|
+
const output = await readCompletedStepOutput(journal, runId, stepId, journalSteps);
|
|
503
|
+
if (!isRecord(output)) {
|
|
504
|
+
throw protocolViolation(runId, `step "${stepId}" produced a non-object output`);
|
|
505
|
+
}
|
|
506
|
+
if (typeof output['stdout_tail'] === 'string') {
|
|
507
|
+
return { summary: output['stdout_tail'], artifacts: [] };
|
|
508
|
+
}
|
|
509
|
+
// The CLI's stdout parsed as JSON, so `output` is that value, not a
|
|
510
|
+
// CliResult. Fall back to a stable, inspectable summary rather than
|
|
511
|
+
// refusing a run whose agent step genuinely succeeded.
|
|
512
|
+
return { summary: JSON.stringify(output), artifacts: [] };
|
|
513
|
+
}
|
|
514
|
+
|
|
325
515
|
interface StepCompletedEntry {
|
|
326
516
|
entry_type: 'step.completed';
|
|
327
517
|
step_id: string;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { accessSync, constants } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { resolve } from 'node:path';
|
|
3
4
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getAuthoredFlowDefinition,
|
|
7
|
+
type AuthoredFlowDefinition,
|
|
8
|
+
type FlowHandle,
|
|
9
|
+
} from './authored-flow.js';
|
|
5
10
|
|
|
6
11
|
export class AuthoredFlowLoadError extends Error {
|
|
7
12
|
constructor(message: string) {
|
|
@@ -10,8 +15,23 @@ export class AuthoredFlowLoadError extends Error {
|
|
|
10
15
|
}
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
/** Same signature as `getAuthoredFlowDefinition`, resolved from wherever a flow was loaded. */
|
|
19
|
+
export type GetFlowDefinition = <Input = unknown>(handle: FlowHandle) => AuthoredFlowDefinition<Input>;
|
|
20
|
+
|
|
21
|
+
export interface LoadedAuthoredFlow {
|
|
22
|
+
readonly handle: FlowHandle;
|
|
23
|
+
/**
|
|
24
|
+
* Bound to the SAME `@relayflows/surface` module instance the flow file
|
|
25
|
+
* itself imported `flow` from — see the comment on
|
|
26
|
+
* {@link resolveGetFlowDefinition}. Callers that go on to execute the flow
|
|
27
|
+
* (not just validate it) must keep using this, not the SDK's own static
|
|
28
|
+
* `getAuthoredFlowDefinition` import.
|
|
29
|
+
*/
|
|
30
|
+
readonly getDefinition: GetFlowDefinition;
|
|
31
|
+
}
|
|
32
|
+
|
|
13
33
|
/** Import and validate a direct-run module without executing its authored body. */
|
|
14
|
-
export async function loadAuthoredFlow(path: string): Promise<
|
|
34
|
+
export async function loadAuthoredFlow(path: string): Promise<LoadedAuthoredFlow> {
|
|
15
35
|
const absolutePath = resolve(path);
|
|
16
36
|
try {
|
|
17
37
|
accessSync(absolutePath, constants.R_OK);
|
|
@@ -28,17 +48,70 @@ export async function loadAuthoredFlow(path: string): Promise<FlowHandle> {
|
|
|
28
48
|
);
|
|
29
49
|
}
|
|
30
50
|
|
|
51
|
+
const getDefinition = await resolveGetFlowDefinition(absolutePath, path);
|
|
31
52
|
const handle = authoredModule['default'] as FlowHandle;
|
|
32
53
|
try {
|
|
33
|
-
|
|
54
|
+
getDefinition(handle);
|
|
34
55
|
} catch (error) {
|
|
35
56
|
throw new AuthoredFlowLoadError(
|
|
36
57
|
`Flow "${path}" must default-export flow(...): ${errorMessage(error)}`,
|
|
37
58
|
);
|
|
38
59
|
}
|
|
39
|
-
return handle;
|
|
60
|
+
return { handle, getDefinition };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `getFlowDefinition` recognizes a handle by object identity in a `WeakMap`
|
|
65
|
+
* scoped to whichever copy of `@relayflows/surface` created it — deliberately:
|
|
66
|
+
* that is what makes a handle unforgeable (surface/tests/flow.test.ts
|
|
67
|
+
* "refuses malformed and forged handles at the runtime boundary" locks this
|
|
68
|
+
* in, including against a well-known-symbol forgery, so this must not be
|
|
69
|
+
* "fixed" by switching that map to a symbol-tagged property instead).
|
|
70
|
+
*
|
|
71
|
+
* An author's `.flow.ts` almost never lives inside this monorepo. It
|
|
72
|
+
* resolves `@relayflows/surface` from ITS OWN `node_modules` — a physically
|
|
73
|
+
* different module instance than the one this SDK package statically
|
|
74
|
+
* imports for itself, so the SDK's own copy's `WeakMap` never has the
|
|
75
|
+
* entry the flow file's copy wrote. The fix is not a new identity
|
|
76
|
+
* mechanism; it is asking the SAME question Node itself would ask: resolve
|
|
77
|
+
* `@relayflows/surface/runtime` from the flow file's own location, exactly
|
|
78
|
+
* as the flow file's `import { flow } from "@relayflows/surface"`
|
|
79
|
+
* already did, and use THAT copy's `getFlowDefinition`. Since the flow
|
|
80
|
+
* module already imported successfully (by the time this runs), a
|
|
81
|
+
* compatible `@relayflows/surface` is provably resolvable from this same
|
|
82
|
+
* anchor.
|
|
83
|
+
*/
|
|
84
|
+
async function resolveGetFlowDefinition(
|
|
85
|
+
absolutePath: string,
|
|
86
|
+
displayPath: string,
|
|
87
|
+
): Promise<GetFlowDefinition> {
|
|
88
|
+
const require = createRequire(pathToFileURL(absolutePath));
|
|
89
|
+
let resolvedRuntimePath: string;
|
|
90
|
+
try {
|
|
91
|
+
resolvedRuntimePath = require.resolve('@relayflows/surface/runtime');
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new AuthoredFlowLoadError(
|
|
94
|
+
`Flow "${displayPath}" imports @relayflows/surface, but @relayflows/surface/runtime `
|
|
95
|
+
+ `could not be resolved from the same location: ${errorMessage(error)}`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const runtimeModule = await import(pathToFileURL(resolvedRuntimePath).href) as {
|
|
99
|
+
getFlowDefinition?: unknown;
|
|
100
|
+
};
|
|
101
|
+
if (typeof runtimeModule.getFlowDefinition !== 'function') {
|
|
102
|
+
throw new AuthoredFlowLoadError(
|
|
103
|
+
`Flow "${displayPath}": the @relayflows/surface/runtime resolved from its location `
|
|
104
|
+
+ 'does not export getFlowDefinition — check its @relayflows/surface version.',
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return runtimeModule.getFlowDefinition as GetFlowDefinition;
|
|
40
108
|
}
|
|
41
109
|
|
|
110
|
+
// Exported for callers (internal SDK tests, and any co-located flow that is
|
|
111
|
+
// provably the same `@relayflows/surface` instance as this package) that
|
|
112
|
+
// have no need to resolve a separate copy.
|
|
113
|
+
export { getAuthoredFlowDefinition };
|
|
114
|
+
|
|
42
115
|
function errorMessage(error: unknown): string {
|
|
43
116
|
return error instanceof Error ? error.message : 'unknown authored-flow error';
|
|
44
117
|
}
|
package/src/cli/direct-run.ts
CHANGED
|
@@ -44,8 +44,13 @@ export async function runDirectFlow(
|
|
|
44
44
|
if (connected !== undefined) return connected;
|
|
45
45
|
|
|
46
46
|
try {
|
|
47
|
-
const handle = await loadAuthoredFlow(path);
|
|
48
|
-
const result = await executeAuthoredFlow(handle, client, input
|
|
47
|
+
const { handle, getDefinition } = await loadAuthoredFlow(path);
|
|
48
|
+
const result = await executeAuthoredFlow(handle, client, input, {
|
|
49
|
+
getDefinition,
|
|
50
|
+
flowPath: path,
|
|
51
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
52
|
+
...(options.onWait !== undefined ? { onWait: options.onWait } : {}),
|
|
53
|
+
});
|
|
49
54
|
const terminal = result.journalSteps.at(-1);
|
|
50
55
|
if (terminal === undefined) {
|
|
51
56
|
return protocolFailure('run', base, socketPath, new Error(
|
|
@@ -65,8 +70,21 @@ export async function runDirectFlow(
|
|
|
65
70
|
},
|
|
66
71
|
};
|
|
67
72
|
} catch (error) {
|
|
73
|
+
// `agent_cli_unresolved` and `unsupported_workspace_permission` are
|
|
74
|
+
// preflight-shaped refusals, not protocol failures — `flows check`
|
|
75
|
+
// returns exit 2 for the equivalent declarative-spec failures, and this
|
|
76
|
+
// path should match it. Known gap, not solved here: if a `f.run` before
|
|
77
|
+
// the failing `f.agent` already journaled real work, this still reports
|
|
78
|
+
// as a clean refusal — true upfront preflight would need to know every
|
|
79
|
+
// `f.agent` call an imperative TS body will make before running any of
|
|
80
|
+
// it, which isn't knowable without running the body (see the comment on
|
|
81
|
+
// ExecuteAuthoredFlowOptions and this project's own examples/README for
|
|
82
|
+
// the same limitation already documented elsewhere).
|
|
68
83
|
if (error instanceof AuthoredFlowLoadError
|
|
69
|
-
|| (error instanceof AuthoredFlowExecutionError
|
|
84
|
+
|| (error instanceof AuthoredFlowExecutionError
|
|
85
|
+
&& (error.code === 'unsupported_header'
|
|
86
|
+
|| error.code === 'agent_cli_unresolved'
|
|
87
|
+
|| error.code === 'unsupported_workspace_permission'))) {
|
|
70
88
|
return {
|
|
71
89
|
exitCode: 2,
|
|
72
90
|
report: {
|
|
@@ -78,6 +96,23 @@ export async function runDirectFlow(
|
|
|
78
96
|
},
|
|
79
97
|
};
|
|
80
98
|
}
|
|
99
|
+
if (error instanceof AuthoredFlowExecutionError && error.code === 'agent_parked') {
|
|
100
|
+
return {
|
|
101
|
+
exitCode: 3,
|
|
102
|
+
report: {
|
|
103
|
+
...base,
|
|
104
|
+
ok: false,
|
|
105
|
+
runId: error.runId,
|
|
106
|
+
socketPath,
|
|
107
|
+
status: 'parked',
|
|
108
|
+
diagnostics: [...base.diagnostics, {
|
|
109
|
+
severity: 'parked',
|
|
110
|
+
kind: 'run_parked',
|
|
111
|
+
message: error.message,
|
|
112
|
+
}],
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
81
116
|
const runId = error instanceof AuthoredFlowExecutionError ? error.runId : undefined;
|
|
82
117
|
return protocolFailure('run', base, socketPath, error, runId);
|
|
83
118
|
} finally {
|