@relayflows/sdk 2.0.13 → 2.0.15
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-executor.d.ts +33 -3
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +53 -7
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-node-runner.d.ts.map +1 -1
- package/dist/authored-node-runner.js +11 -4
- package/dist/authored-node-runner.js.map +1 -1
- package/dist/authored-root.d.ts.map +1 -1
- package/dist/authored-root.js +2 -2
- package/dist/authored-root.js.map +1 -1
- package/dist/cli/check-triggers.d.ts.map +1 -1
- package/dist/cli/check-triggers.js +14 -3
- package/dist/cli/check-triggers.js.map +1 -1
- package/dist/cli/direct-run.d.ts.map +1 -1
- package/dist/cli/direct-run.js +7 -52
- package/dist/cli/direct-run.js.map +1 -1
- package/dist/cli/run.d.ts +34 -0
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +110 -15
- package/dist/cli/run.js.map +1 -1
- package/dist/provider-trigger-contract.d.ts +27 -0
- package/dist/provider-trigger-contract.d.ts.map +1 -0
- package/dist/provider-trigger-contract.js +0 -0
- package/dist/provider-trigger-contract.js.map +1 -0
- package/package.json +2 -2
- package/src/authored-flow-executor.ts +74 -12
- package/src/authored-node-runner.ts +11 -4
- package/src/authored-root.ts +2 -2
- package/src/cli/check-triggers.ts +14 -5
- package/src/cli/direct-run.ts +8 -51
- package/src/cli/run.ts +125 -15
- package/src/provider-trigger-contract.ts +0 -0
package/src/cli/direct-run.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { JournalClient } from '../journal-client.js';
|
|
|
14
14
|
import { inputFailureReport } from './check.js';
|
|
15
15
|
import { checkAuthoredTriggers } from './check-triggers.js';
|
|
16
16
|
import {
|
|
17
|
+
authoredCompletion,
|
|
18
|
+
authoredStepFailure,
|
|
17
19
|
connect,
|
|
18
20
|
emptyReport,
|
|
19
21
|
fromCheckReport,
|
|
@@ -98,31 +100,7 @@ export async function runDirectFlow(
|
|
|
98
100
|
`authored flow "${result.name}" completed without a journal step`,
|
|
99
101
|
));
|
|
100
102
|
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
exitCode: 3,
|
|
104
|
-
report: {
|
|
105
|
-
...base, ok: false, runId: result.rootRunId, socketPath, status: 'parked',
|
|
106
|
-
completedSteps: result.journalSteps.length,
|
|
107
|
-
diagnostics: [...base.diagnostics, {
|
|
108
|
-
severity: 'parked', kind: 'run_parked',
|
|
109
|
-
message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.`,
|
|
110
|
-
}],
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return {
|
|
115
|
-
exitCode: 0,
|
|
116
|
-
report: {
|
|
117
|
-
...base,
|
|
118
|
-
ok: true,
|
|
119
|
-
runId: result.rootRunId,
|
|
120
|
-
socketPath,
|
|
121
|
-
status: 'completed',
|
|
122
|
-
completionReason: result.completionReason,
|
|
123
|
-
completedSteps: result.journalSteps.length,
|
|
124
|
-
},
|
|
125
|
-
};
|
|
103
|
+
return authoredCompletion('run', base, socketPath, result, result.rootRunId);
|
|
126
104
|
} catch (caught) {
|
|
127
105
|
if (caught instanceof McpPreflightError) return {
|
|
128
106
|
exitCode: 2, report: fromCheckReport('run', caught.report),
|
|
@@ -190,33 +168,12 @@ export async function runDirectFlow(
|
|
|
190
168
|
},
|
|
191
169
|
};
|
|
192
170
|
}
|
|
193
|
-
// A step that ran and failed is a run failure, not a protocol failure.
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
// about a run whose outcome was known exactly. The diagnostic carried up
|
|
198
|
-
// from `classifyOutcome` already names the step, its exit code and its
|
|
199
|
-
// output tail; this branch is what lets it reach the terminal. Mirrors
|
|
200
|
-
// the `McpStepError` branch above, which had this shape all along.
|
|
171
|
+
// A step that ran and failed is a run failure, not a protocol failure. The
|
|
172
|
+
// diagnostic carried up from `classifyOutcome` already names the step, its
|
|
173
|
+
// exit code and its output tail; this branch is what lets it reach the
|
|
174
|
+
// terminal. `resumeFlow` takes the same branch, through the same helper.
|
|
201
175
|
if (error instanceof AuthoredFlowExecutionError && error.code === 'step_failed') {
|
|
202
|
-
return
|
|
203
|
-
exitCode: 1,
|
|
204
|
-
report: {
|
|
205
|
-
...base,
|
|
206
|
-
ok: false,
|
|
207
|
-
runId: error.runId,
|
|
208
|
-
socketPath,
|
|
209
|
-
status: 'failed',
|
|
210
|
-
completionReason: 'step_failed',
|
|
211
|
-
diagnostics: [...base.diagnostics, {
|
|
212
|
-
severity: 'failure',
|
|
213
|
-
kind: 'step_failed',
|
|
214
|
-
// The `code: ` prefix `AuthoredFlowExecutionError` adds is
|
|
215
|
-
// redundant once the diagnostic is labelled `[step_failed]`.
|
|
216
|
-
message: error.message.replace(/^step_failed: /, ''),
|
|
217
|
-
}],
|
|
218
|
-
},
|
|
219
|
-
};
|
|
176
|
+
return authoredStepFailure('run', base, socketPath, error);
|
|
220
177
|
}
|
|
221
178
|
const runId = error instanceof AuthoredFlowExecutionError ? error.runId : undefined;
|
|
222
179
|
return protocolFailure('run', base, socketPath, error, runId);
|
package/src/cli/run.ts
CHANGED
|
@@ -22,6 +22,7 @@ import type {
|
|
|
22
22
|
RunStatus,
|
|
23
23
|
} from '../protocol.js';
|
|
24
24
|
import type { StepType } from '../spec.js';
|
|
25
|
+
import type { LoweredCompletionReason } from '../authored-flow-executor.js';
|
|
25
26
|
import {
|
|
26
27
|
checkFlow,
|
|
27
28
|
type CheckReport,
|
|
@@ -191,21 +192,7 @@ export async function resumeFlow(
|
|
|
191
192
|
lifecycle: options,
|
|
192
193
|
});
|
|
193
194
|
if (result === undefined) throw new Error('authored root disappeared during resume');
|
|
194
|
-
return
|
|
195
|
-
exitCode: result.completionReason === 'needs_human' ? 3 : 0,
|
|
196
|
-
report: {
|
|
197
|
-
...base,
|
|
198
|
-
ok: result.completionReason === 'success',
|
|
199
|
-
runId,
|
|
200
|
-
socketPath,
|
|
201
|
-
status: result.completionReason === 'needs_human' ? 'parked' : 'completed',
|
|
202
|
-
...(result.completionReason === 'success'
|
|
203
|
-
? { completionReason: 'success' as const }
|
|
204
|
-
: { diagnostics: [{ severity: 'parked' as const, kind: 'run_parked' as const,
|
|
205
|
-
message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.` }] }),
|
|
206
|
-
completedSteps: result.journalSteps.length,
|
|
207
|
-
},
|
|
208
|
-
};
|
|
195
|
+
return authoredCompletion('resume', base, socketPath, result, runId);
|
|
209
196
|
}
|
|
210
197
|
// resumeHelperEffect subsumes the old resumeSlackEffect: it handles the
|
|
211
198
|
// slack effect resume plus every other provider from N's codegen. The
|
|
@@ -231,6 +218,14 @@ export async function resumeFlow(
|
|
|
231
218
|
return { exitCode: 2, report: { ...base, runId, socketPath,
|
|
232
219
|
diagnostics: [{ severity: 'refusal', kind: error.code, message: error.message }] } };
|
|
233
220
|
}
|
|
221
|
+
// Same classification the run path gets. Resuming an authored root whose
|
|
222
|
+
// `f.agent` step failed is a step failure, not a protocol failure, and
|
|
223
|
+
// leaving it on `protocolFailure` meant `flows run` printed the evidence
|
|
224
|
+
// while `flows resume` still printed `protocol_error` and
|
|
225
|
+
// `RUN <id> unknown` for the identical failure.
|
|
226
|
+
if (error instanceof AuthoredFlowExecutionError && error.code === 'step_failed') {
|
|
227
|
+
return authoredStepFailure('resume', base, socketPath, error, runId);
|
|
228
|
+
}
|
|
234
229
|
if (!(error instanceof JournalProtocolError) || error.code !== 'run_not_found') {
|
|
235
230
|
return protocolFailure('resume', base, socketPath, error, runId);
|
|
236
231
|
}
|
|
@@ -258,6 +253,121 @@ export async function resumeFlow(
|
|
|
258
253
|
}
|
|
259
254
|
}
|
|
260
255
|
|
|
256
|
+
/**
|
|
257
|
+
* A step that ran and failed, reported as the run failure it is.
|
|
258
|
+
*
|
|
259
|
+
* Shared by `runDirectFlow` and `resumeFlow` on purpose. The first cut of this
|
|
260
|
+
* fix classified the run path and left resume on `protocolFailure`, so `flows
|
|
261
|
+
* run` became diagnosable while `flows resume` still printed `protocol_error`
|
|
262
|
+
* and `RUN <id> unknown` for the same failed step — and the surface doc claimed
|
|
263
|
+
* both were fixed. One function is what stops the two paths drifting again.
|
|
264
|
+
*
|
|
265
|
+
* `protocolFailure` is wrong here twice over: it blames the daemon for a run it
|
|
266
|
+
* drove correctly, and it produces a report with no `status`, which is the
|
|
267
|
+
* whole of what `RUN <id> unknown` ever meant.
|
|
268
|
+
*/
|
|
269
|
+
export function authoredStepFailure(
|
|
270
|
+
command: RunCommand,
|
|
271
|
+
base: CheckReport | RunReport,
|
|
272
|
+
socketPath: string,
|
|
273
|
+
error: AuthoredFlowExecutionError,
|
|
274
|
+
fallbackRunId?: string,
|
|
275
|
+
): RunExecution {
|
|
276
|
+
// The failing step runs as its own kernel run, so the error's run id is the
|
|
277
|
+
// one whose journal holds the evidence. The resume target is the fallback.
|
|
278
|
+
const runId = error.runId ?? fallbackRunId;
|
|
279
|
+
return {
|
|
280
|
+
exitCode: 1,
|
|
281
|
+
report: {
|
|
282
|
+
...fromBase(command, base),
|
|
283
|
+
ok: false,
|
|
284
|
+
...(runId === undefined ? {} : { runId }),
|
|
285
|
+
socketPath,
|
|
286
|
+
status: 'failed',
|
|
287
|
+
completionReason: 'step_failed',
|
|
288
|
+
diagnostics: [...base.diagnostics, {
|
|
289
|
+
severity: 'failure',
|
|
290
|
+
kind: 'step_failed',
|
|
291
|
+
// The `step_failed: ` prefix `AuthoredFlowExecutionError` adds is
|
|
292
|
+
// redundant once the diagnostic is labelled `[step_failed]`.
|
|
293
|
+
message: error.message.replace(/^step_failed: /, ''),
|
|
294
|
+
}],
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* An authored body that returned its own terminal verdict, reported as that verdict.
|
|
301
|
+
*
|
|
302
|
+
* Shared by `runDirectFlow` and `resumeFlow` for the reason `authoredStepFailure`
|
|
303
|
+
* is shared: the run and resume paths had already drifted once, and the
|
|
304
|
+
* `needs_human` report was duplicated verbatim in both files.
|
|
305
|
+
*
|
|
306
|
+
* This is NOT `authoredStepFailure`, even though a `step_failed` verdict lands
|
|
307
|
+
* on the same exit code and report shape. That function describes a step that
|
|
308
|
+
* ran and failed, and carries the failing step's evidence. Here every step
|
|
309
|
+
* succeeded and the BODY declared the outcome, so there is no failing step to
|
|
310
|
+
* name — routing this through the other helper would invent one.
|
|
311
|
+
*/
|
|
312
|
+
export function authoredCompletion(
|
|
313
|
+
command: RunCommand,
|
|
314
|
+
base: RunReport,
|
|
315
|
+
socketPath: string,
|
|
316
|
+
result: { name: string; completionReason: LoweredCompletionReason; journalSteps: readonly unknown[] },
|
|
317
|
+
runId: string | undefined,
|
|
318
|
+
): RunExecution {
|
|
319
|
+
const common: RunReport = {
|
|
320
|
+
...fromBase(command, base),
|
|
321
|
+
...(runId === undefined ? {} : { runId }),
|
|
322
|
+
socketPath,
|
|
323
|
+
completedSteps: result.journalSteps.length,
|
|
324
|
+
};
|
|
325
|
+
switch (result.completionReason) {
|
|
326
|
+
case 'success':
|
|
327
|
+
return {
|
|
328
|
+
exitCode: 0,
|
|
329
|
+
report: { ...common, ok: true, status: 'completed', completionReason: 'success' },
|
|
330
|
+
};
|
|
331
|
+
case 'needs_human':
|
|
332
|
+
return {
|
|
333
|
+
exitCode: 3,
|
|
334
|
+
report: {
|
|
335
|
+
...common, ok: false, status: 'parked',
|
|
336
|
+
diagnostics: [...base.diagnostics, {
|
|
337
|
+
severity: 'parked', kind: 'run_parked',
|
|
338
|
+
message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.`,
|
|
339
|
+
}],
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
case 'step_failed':
|
|
343
|
+
// A declared run failure. Exit 1, not the parked 3: nothing here is
|
|
344
|
+
// waiting for a human to recover it, and exit 3 is the local kit's
|
|
345
|
+
// manual-approval stop. `status: failed` with this `completionReason` is
|
|
346
|
+
// also the only terminal shape Cloud accepts for a non-success run
|
|
347
|
+
// (see cloud-run.ts).
|
|
348
|
+
return {
|
|
349
|
+
exitCode: 1,
|
|
350
|
+
report: {
|
|
351
|
+
...common, ok: false, status: 'failed', completionReason: 'step_failed',
|
|
352
|
+
diagnostics: [...base.diagnostics, {
|
|
353
|
+
severity: 'failure', kind: 'step_failed',
|
|
354
|
+
message: `Flow "${result.name}" declared done("step_failed"): its own checks did not pass. `
|
|
355
|
+
+ 'No step failed, so there is no step-level evidence to inspect; the journal holds '
|
|
356
|
+
+ 'every step the flow ran before it decided.',
|
|
357
|
+
}],
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
// Exhaustive by construction. A fourth lowered completion has to choose its
|
|
362
|
+
// own exit code and wording here; it must not inherit "its own checks did not
|
|
363
|
+
// pass", which would state something the body never declared. Letting an
|
|
364
|
+
// unlisted reason fall through to the failure branch is how a reporting-side
|
|
365
|
+
// copy of the same vocabulary drifts from the executor's — the defect this
|
|
366
|
+
// change exists to close — so it is a compile error, not a wrong report.
|
|
367
|
+
const unreachable: never = result.completionReason;
|
|
368
|
+
throw new Error(`unreachable authored completion: ${String(unreachable)}`);
|
|
369
|
+
}
|
|
370
|
+
|
|
261
371
|
/**
|
|
262
372
|
* Get a live daemon, then open the socket to it.
|
|
263
373
|
*
|
|
Binary file
|