@relayflows/sdk 2.0.30 → 2.0.32
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-artifacts.d.ts.map +1 -1
- package/dist/agent-artifacts.js +2 -9
- package/dist/agent-artifacts.js.map +1 -1
- package/dist/agent-cwd.d.ts +69 -0
- package/dist/agent-cwd.d.ts.map +1 -0
- package/dist/agent-cwd.js +140 -0
- package/dist/agent-cwd.js.map +1 -0
- package/dist/artifact-scan-policy.d.ts +35 -0
- package/dist/artifact-scan-policy.d.ts.map +1 -0
- package/dist/artifact-scan-policy.js +49 -0
- package/dist/artifact-scan-policy.js.map +1 -0
- package/dist/authored-completion-record.d.ts +35 -0
- package/dist/authored-completion-record.d.ts.map +1 -0
- package/dist/authored-completion-record.js +92 -0
- package/dist/authored-completion-record.js.map +1 -0
- package/dist/authored-completion.d.ts +99 -0
- package/dist/authored-completion.d.ts.map +1 -0
- package/dist/authored-completion.js +184 -0
- package/dist/authored-completion.js.map +1 -0
- package/dist/authored-flow-error.d.ts +13 -1
- package/dist/authored-flow-error.d.ts.map +1 -1
- package/dist/authored-flow-error.js +12 -0
- package/dist/authored-flow-error.js.map +1 -1
- package/dist/authored-flow-executor.d.ts +7 -30
- package/dist/authored-flow-executor.d.ts.map +1 -1
- package/dist/authored-flow-executor.js +54 -47
- package/dist/authored-flow-executor.js.map +1 -1
- package/dist/authored-human.d.ts.map +1 -1
- package/dist/authored-human.js +1 -3
- package/dist/authored-human.js.map +1 -1
- package/dist/authored-node-entry.js +4 -1
- package/dist/authored-node-entry.js.map +1 -1
- package/dist/authored-node-runner.d.ts +9 -1
- package/dist/authored-node-runner.d.ts.map +1 -1
- package/dist/authored-node-runner.js +92 -17
- package/dist/authored-node-runner.js.map +1 -1
- package/dist/authored-preflight.d.ts +4 -0
- package/dist/authored-preflight.d.ts.map +1 -0
- package/dist/authored-preflight.js +50 -0
- package/dist/authored-preflight.js.map +1 -0
- package/dist/authored-root.d.ts +5 -0
- package/dist/authored-root.d.ts.map +1 -1
- package/dist/authored-root.js +20 -2
- package/dist/authored-root.js.map +1 -1
- package/dist/authored-step-output.d.ts +35 -10
- package/dist/authored-step-output.d.ts.map +1 -1
- package/dist/authored-step-output.js +108 -40
- package/dist/authored-step-output.js.map +1 -1
- package/dist/authored-verdict.d.ts +28 -0
- package/dist/authored-verdict.d.ts.map +1 -0
- package/dist/authored-verdict.js +79 -0
- package/dist/authored-verdict.js.map +1 -0
- package/dist/authored-worker-step.d.ts +5 -2
- package/dist/authored-worker-step.d.ts.map +1 -1
- package/dist/authored-worker-step.js +51 -13
- package/dist/authored-worker-step.js.map +1 -1
- package/dist/cli/check-worker-surface.d.ts +27 -0
- package/dist/cli/check-worker-surface.d.ts.map +1 -0
- package/dist/cli/check-worker-surface.js +63 -0
- package/dist/cli/check-worker-surface.js.map +1 -0
- package/dist/cli/check.d.ts +28 -3
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +27 -140
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/cli-probe.d.ts +20 -0
- package/dist/cli/cli-probe.d.ts.map +1 -0
- package/dist/cli/cli-probe.js +166 -0
- package/dist/cli/cli-probe.js.map +1 -0
- package/dist/cli/cloud-format.d.ts +9 -0
- package/dist/cli/cloud-format.d.ts.map +1 -0
- package/dist/cli/cloud-format.js +77 -0
- package/dist/cli/cloud-format.js.map +1 -0
- package/dist/cli/cloud-live.d.ts +39 -0
- package/dist/cli/cloud-live.d.ts.map +1 -0
- package/dist/cli/cloud-live.js +325 -0
- package/dist/cli/cloud-live.js.map +1 -0
- package/dist/cli/cloud-mirror-session.d.ts +97 -0
- package/dist/cli/cloud-mirror-session.d.ts.map +1 -0
- package/dist/cli/cloud-mirror-session.js +264 -0
- package/dist/cli/cloud-mirror-session.js.map +1 -0
- package/dist/cli/cloud-read.d.ts +3 -7
- package/dist/cli/cloud-read.d.ts.map +1 -1
- package/dist/cli/cloud-read.js +14 -266
- package/dist/cli/cloud-read.js.map +1 -1
- package/dist/cli/cloud-refusal.d.ts +39 -0
- package/dist/cli/cloud-refusal.d.ts.map +1 -0
- package/dist/cli/cloud-refusal.js +95 -0
- package/dist/cli/cloud-refusal.js.map +1 -0
- package/dist/cli/cloud-status-view.d.ts +7 -0
- package/dist/cli/cloud-status-view.d.ts.map +1 -0
- package/dist/cli/cloud-status-view.js +214 -0
- package/dist/cli/cloud-status-view.js.map +1 -0
- package/dist/cli/direct-run.d.ts.map +1 -1
- package/dist/cli/direct-run.js +16 -2
- package/dist/cli/direct-run.js.map +1 -1
- package/dist/cli/hn-monitor.d.ts +0 -13
- package/dist/cli/hn-monitor.d.ts.map +1 -1
- package/dist/cli/hn-monitor.js +2 -1
- package/dist/cli/hn-monitor.js.map +1 -1
- package/dist/cli/local-agent-remedy.d.ts +80 -0
- package/dist/cli/local-agent-remedy.d.ts.map +1 -0
- package/dist/cli/local-agent-remedy.js +116 -0
- package/dist/cli/local-agent-remedy.js.map +1 -0
- package/dist/cli/observer-session.d.ts +41 -0
- package/dist/cli/observer-session.d.ts.map +1 -0
- package/dist/cli/observer-session.js +78 -0
- package/dist/cli/observer-session.js.map +1 -0
- package/dist/cli/run.d.ts +30 -2
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +186 -24
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/status.d.ts +9 -0
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +31 -2
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/step-evidence.d.ts +90 -0
- package/dist/cli/step-evidence.d.ts.map +1 -0
- package/dist/cli/step-evidence.js +259 -0
- package/dist/cli/step-evidence.js.map +1 -0
- package/dist/cli/step-failure.d.ts +14 -4
- package/dist/cli/step-failure.d.ts.map +1 -1
- package/dist/cli/step-failure.js +41 -76
- package/dist/cli/step-failure.js.map +1 -1
- package/dist/cli-commands.d.ts +12 -0
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +3 -0
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +134 -57
- package/dist/cli.js.map +1 -1
- package/dist/cloud-deploy.d.ts +1 -1
- package/dist/cloud-deploy.d.ts.map +1 -1
- package/dist/cloud-deploy.js +24 -8
- package/dist/cloud-deploy.js.map +1 -1
- package/dist/cloud-mirror-ledger.d.ts +40 -0
- package/dist/cloud-mirror-ledger.d.ts.map +1 -0
- package/dist/cloud-mirror-ledger.js +142 -0
- package/dist/cloud-mirror-ledger.js.map +1 -0
- package/dist/cloud-mirror-step.d.ts +168 -0
- package/dist/cloud-mirror-step.d.ts.map +1 -0
- package/dist/cloud-mirror-step.js +504 -0
- package/dist/cloud-mirror-step.js.map +1 -0
- package/dist/cloud-mirror-transport.d.ts +94 -0
- package/dist/cloud-mirror-transport.d.ts.map +1 -0
- package/dist/cloud-mirror-transport.js +163 -0
- package/dist/cloud-mirror-transport.js.map +1 -0
- package/dist/cloud-mirror.d.ts +132 -0
- package/dist/cloud-mirror.d.ts.map +1 -0
- package/dist/cloud-mirror.js +556 -0
- package/dist/cloud-mirror.js.map +1 -0
- package/dist/cloud-read.d.ts +15 -0
- package/dist/cloud-read.d.ts.map +1 -1
- package/dist/cloud-read.js +20 -1
- package/dist/cloud-read.js.map +1 -1
- package/dist/cloud-run-record.d.ts +27 -0
- package/dist/cloud-run-record.d.ts.map +1 -0
- package/dist/cloud-run-record.js +56 -0
- package/dist/cloud-run-record.js.map +1 -0
- package/dist/cloud-run.d.ts +2 -9
- package/dist/cloud-run.d.ts.map +1 -1
- package/dist/cloud-run.js +3 -20
- package/dist/cloud-run.js.map +1 -1
- package/dist/communication/local.d.ts.map +1 -1
- package/dist/communication/local.js +2 -1
- 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 +13 -5
- package/dist/communication/worker.js.map +1 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +28 -6
- package/dist/compile.js.map +1 -1
- package/dist/direct-input.d.ts.map +1 -1
- package/dist/direct-input.js +21 -1
- package/dist/direct-input.js.map +1 -1
- package/dist/failure-kinds.d.ts +96 -6
- package/dist/failure-kinds.d.ts.map +1 -1
- package/dist/failure-kinds.js +29 -2
- package/dist/failure-kinds.js.map +1 -1
- package/dist/flow-requirements.d.ts.map +1 -1
- package/dist/flow-requirements.js +24 -9
- package/dist/flow-requirements.js.map +1 -1
- package/dist/gate-contract.d.ts +7 -0
- package/dist/gate-contract.d.ts.map +1 -1
- package/dist/gate-contract.js +6 -1
- package/dist/gate-contract.js.map +1 -1
- package/dist/helper-preflight.d.ts.map +1 -1
- package/dist/helper-preflight.js +10 -3
- package/dist/helper-preflight.js.map +1 -1
- package/dist/helper-reference.d.ts +25 -0
- package/dist/helper-reference.d.ts.map +1 -0
- package/dist/helper-reference.js +129 -0
- package/dist/helper-reference.js.map +1 -0
- package/dist/hosted-extension-runtime.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/journal-client.d.ts +3 -1
- package/dist/journal-client.d.ts.map +1 -1
- package/dist/journal-client.js +17 -2
- package/dist/journal-client.js.map +1 -1
- package/dist/journal-projection.d.ts +16 -0
- package/dist/journal-projection.d.ts.map +1 -0
- package/dist/journal-projection.js +108 -0
- package/dist/journal-projection.js.map +1 -0
- package/dist/llm-worker.js +1 -1
- package/dist/llm-worker.js.map +1 -1
- package/dist/local-agent.d.ts +1 -1
- package/dist/local-agent.d.ts.map +1 -1
- package/dist/local-agent.js +4 -3
- package/dist/local-agent.js.map +1 -1
- package/dist/named-gate-lowering.js +35 -5
- package/dist/named-gate-lowering.js.map +1 -1
- package/dist/named-gate-preflight.d.ts +27 -0
- package/dist/named-gate-preflight.d.ts.map +1 -0
- package/dist/named-gate-preflight.js +47 -0
- package/dist/named-gate-preflight.js.map +1 -0
- package/dist/named-gates.d.ts +1 -1
- package/dist/named-gates.d.ts.map +1 -1
- package/dist/named-gates.js +3 -0
- package/dist/named-gates.js.map +1 -1
- package/dist/observer-link.d.ts +7 -0
- package/dist/observer-link.d.ts.map +1 -1
- package/dist/observer-link.js +3 -1
- package/dist/observer-link.js.map +1 -1
- package/dist/package-version.d.ts +10 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +22 -0
- package/dist/package-version.js.map +1 -0
- package/dist/preflight.d.ts +14 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +25 -3
- package/dist/preflight.js.map +1 -1
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/redact.d.ts +42 -0
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +128 -0
- package/dist/redact.js.map +1 -1
- package/dist/relay-cli.d.ts.map +1 -1
- package/dist/relay-cli.js +1 -21
- package/dist/relay-cli.js.map +1 -1
- package/dist/run-projection.d.ts +83 -0
- package/dist/run-projection.d.ts.map +1 -0
- package/dist/run-projection.js +199 -0
- package/dist/run-projection.js.map +1 -0
- package/dist/shell-word.d.ts +19 -0
- package/dist/shell-word.d.ts.map +1 -0
- package/dist/shell-word.js +23 -0
- package/dist/shell-word.js.map +1 -0
- package/dist/spec.d.ts +52 -3
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/step-fields.d.ts +1 -1
- package/dist/step-fields.js +1 -1
- package/dist/step-fields.js.map +1 -1
- package/dist/steps-green.d.ts +27 -0
- package/dist/steps-green.d.ts.map +1 -0
- package/dist/steps-green.js +164 -0
- package/dist/steps-green.js.map +1 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +39 -8
- package/dist/validate.js.map +1 -1
- package/dist/worker-lease.d.ts +8 -1
- package/dist/worker-lease.d.ts.map +1 -1
- package/dist/worker-lease.js +34 -4
- package/dist/worker-lease.js.map +1 -1
- package/dist/worker.d.ts +8 -0
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +17 -9
- package/dist/worker.js.map +1 -1
- package/package.json +3 -7
- package/src/agent-artifacts.ts +2 -10
- package/src/agent-cwd.ts +139 -0
- package/src/artifact-scan-policy.ts +51 -0
- package/src/authored-completion-record.ts +119 -0
- package/src/authored-completion.ts +203 -0
- package/src/authored-flow-error.ts +13 -1
- package/src/authored-flow-executor.ts +91 -58
- package/src/authored-human.ts +1 -4
- package/src/authored-node-entry.ts +4 -1
- package/src/authored-node-runner.ts +96 -22
- package/src/authored-preflight.ts +46 -0
- package/src/authored-root.ts +20 -2
- package/src/authored-step-output.ts +139 -42
- package/src/authored-verdict.ts +87 -0
- package/src/authored-worker-step.ts +63 -14
- package/src/cli/check-worker-surface.ts +66 -0
- package/src/cli/check.ts +59 -166
- package/src/cli/cli-probe.ts +194 -0
- package/src/cli/cloud-format.ts +82 -0
- package/src/cli/cloud-live.ts +366 -0
- package/src/cli/cloud-mirror-session.ts +329 -0
- package/src/cli/cloud-read.ts +13 -282
- package/src/cli/cloud-refusal.ts +113 -0
- package/src/cli/cloud-status-view.ts +213 -0
- package/src/cli/direct-run.ts +19 -2
- package/src/cli/hn-monitor.ts +2 -1
- package/src/cli/local-agent-remedy.ts +160 -0
- package/src/cli/observer-session.ts +107 -0
- package/src/cli/run.ts +233 -28
- package/src/cli/status.ts +59 -3
- package/src/cli/step-evidence.ts +310 -0
- package/src/cli/step-failure.ts +57 -81
- package/src/cli-commands.ts +3 -0
- package/src/cli.ts +155 -60
- package/src/cloud-deploy.ts +26 -8
- package/src/cloud-mirror-ledger.ts +161 -0
- package/src/cloud-mirror-step.ts +618 -0
- package/src/cloud-mirror-transport.ts +261 -0
- package/src/cloud-mirror.ts +633 -0
- package/src/cloud-read.ts +25 -1
- package/src/cloud-run-record.ts +64 -0
- package/src/cloud-run.ts +5 -24
- package/src/communication/local.ts +2 -1
- package/src/communication/worker.ts +13 -5
- package/src/compile.ts +28 -6
- package/src/direct-input.ts +22 -1
- package/src/failure-kinds.ts +104 -2
- package/src/flow-requirements.ts +24 -9
- package/src/gate-contract.ts +13 -1
- package/src/helper-preflight.ts +10 -3
- package/src/helper-reference.ts +130 -0
- package/src/hosted-extension-runtime.ts +1 -1
- package/src/index.ts +2 -0
- package/src/journal-client.ts +19 -2
- package/src/journal-projection.ts +106 -0
- package/src/llm-worker.ts +1 -1
- package/src/local-agent.ts +4 -2
- package/src/named-gate-lowering.ts +35 -5
- package/src/named-gate-preflight.ts +47 -0
- package/src/named-gates.ts +3 -0
- package/src/observer-link.ts +10 -1
- package/src/package-version.ts +23 -0
- package/src/preflight.ts +38 -7
- package/src/protocol.ts +2 -0
- package/src/redact.ts +111 -0
- package/src/relay-cli.ts +1 -24
- package/src/run-projection.ts +247 -0
- package/src/shell-word.ts +24 -0
- package/src/spec.ts +54 -3
- package/src/step-fields.ts +1 -1
- package/src/steps-green.ts +168 -0
- package/src/validate.ts +35 -8
- package/src/worker-lease.ts +35 -5
- package/src/worker.ts +27 -11
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The observer half of `flows run` / `flows resume`: once the run id is known,
|
|
3
|
+
* project the run into its `wf-<runId>` channel and mint a read-only link
|
|
4
|
+
* scoped to that channel, so the link opens on this run's step graph instead
|
|
5
|
+
* of an arbitrary workspace channel. The link is printed on stderr the moment
|
|
6
|
+
* it exists, so a human can follow the run live, and again after `RUN`.
|
|
7
|
+
*
|
|
8
|
+
* Best-effort throughout: no workspace key means no session, and a projection
|
|
9
|
+
* or mint failure is a labeled stderr line. The run never depends on it.
|
|
10
|
+
*/
|
|
11
|
+
import type { CliIo } from '../cli.js';
|
|
12
|
+
import type { JournalEvent } from '../journal-reader.js';
|
|
13
|
+
import { type MintObserverOptions } from '../observer-link.js';
|
|
14
|
+
import type { ProgressEvent } from '../progress.js';
|
|
15
|
+
import { type ProjectionFetch } from '../run-projection.js';
|
|
16
|
+
import type { RunReport } from './run.js';
|
|
17
|
+
type MintOutcome = {
|
|
18
|
+
observerUrl?: string;
|
|
19
|
+
warning?: string;
|
|
20
|
+
};
|
|
21
|
+
export interface ObserverSession {
|
|
22
|
+
/** YAML runs: every entry `run.start {watch}` / `run.watch` pushes. */
|
|
23
|
+
onJournalEntry(entry: JournalEvent): void;
|
|
24
|
+
/** Authored runs: the root's id and name, known once it is admitted. */
|
|
25
|
+
onRunStarted(run: {
|
|
26
|
+
runId: string;
|
|
27
|
+
flow: string;
|
|
28
|
+
resumed?: boolean;
|
|
29
|
+
}): void;
|
|
30
|
+
/** Authored runs: step transitions from the body's executor. */
|
|
31
|
+
onProgress(event: ProgressEvent): void;
|
|
32
|
+
/** Close the projection from the final report and settle the link. */
|
|
33
|
+
finish(report: RunReport): Promise<MintOutcome> | undefined;
|
|
34
|
+
}
|
|
35
|
+
export interface ObserverSessionDeps {
|
|
36
|
+
fetch?: ProjectionFetch;
|
|
37
|
+
mint?: (options: MintObserverOptions) => Promise<MintOutcome>;
|
|
38
|
+
}
|
|
39
|
+
export declare function createObserverSession(command: 'run' | 'resume', io: CliIo, env?: NodeJS.ProcessEnv, deps?: ObserverSessionDeps): ObserverSession | undefined;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=observer-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-session.d.ts","sourceRoot":"","sources":["../../src/cli/observer-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAA2C,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACmD,KAAK,eAAe,EAC7E,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,KAAK,WAAW,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1C,wEAAwE;IACxE,YAAY,CAAC,GAAG,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5E,gEAAgE;IAChE,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvC,sEAAsE;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/D;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,KAAK,GAAG,QAAQ,EACzB,EAAE,EAAE,KAAK,EACT,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,mBAAwB,GAC7B,eAAe,GAAG,SAAS,CA2D7B"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The observer half of `flows run` / `flows resume`: once the run id is known,
|
|
3
|
+
* project the run into its `wf-<runId>` channel and mint a read-only link
|
|
4
|
+
* scoped to that channel, so the link opens on this run's step graph instead
|
|
5
|
+
* of an arbitrary workspace channel. The link is printed on stderr the moment
|
|
6
|
+
* it exists, so a human can follow the run live, and again after `RUN`.
|
|
7
|
+
*
|
|
8
|
+
* Best-effort throughout: no workspace key means no session, and a projection
|
|
9
|
+
* or mint failure is a labeled stderr line. The run never depends on it.
|
|
10
|
+
*/
|
|
11
|
+
import { createJournalProjector } from '../journal-projection.js';
|
|
12
|
+
import { mintObserverUrl, resolveObserverLinkEnv } from '../observer-link.js';
|
|
13
|
+
import { createRunProjection, runChannelName, } from '../run-projection.js';
|
|
14
|
+
/** Bounded so an unreachable Relaycast cannot hold the CLI open. */
|
|
15
|
+
const DRAIN_GRACE_MS = 5_000;
|
|
16
|
+
export function createObserverSession(command, io, env = process.env, deps = {}) {
|
|
17
|
+
const link = resolveObserverLinkEnv(env);
|
|
18
|
+
if (link.suppressed || link.workspaceKey === undefined)
|
|
19
|
+
return undefined;
|
|
20
|
+
const workspaceKey = link.workspaceKey;
|
|
21
|
+
const mint = deps.mint ?? mintObserverUrl;
|
|
22
|
+
const liveSinceMs = command === 'resume' ? Date.now() : 0;
|
|
23
|
+
let projection;
|
|
24
|
+
let minted;
|
|
25
|
+
let rootRunId;
|
|
26
|
+
const mintFor = (runId) => minted ??= mint({
|
|
27
|
+
workspaceKey,
|
|
28
|
+
channel: runChannelName(runId),
|
|
29
|
+
...(link.baseUrl === undefined ? {} : { baseUrl: link.baseUrl }),
|
|
30
|
+
...(link.dashboardUrl === undefined ? {} : { dashboardUrl: link.dashboardUrl }),
|
|
31
|
+
}).catch((error) => ({ warning: error instanceof Error ? error.message : 'unknown mint error' }));
|
|
32
|
+
const open = (run) => {
|
|
33
|
+
if (projection !== undefined)
|
|
34
|
+
return projection;
|
|
35
|
+
rootRunId = run.runId;
|
|
36
|
+
projection = createRunProjection({
|
|
37
|
+
workspaceKey,
|
|
38
|
+
...(link.baseUrl === undefined ? {} : { baseUrl: link.baseUrl }),
|
|
39
|
+
...(deps.fetch === undefined ? {} : { fetch: deps.fetch }),
|
|
40
|
+
diagnostic: message => io.stderr(`[observer] ${message}`),
|
|
41
|
+
}, run);
|
|
42
|
+
void mintFor(run.runId).then(outcome => {
|
|
43
|
+
if (outcome.observerUrl !== undefined)
|
|
44
|
+
io.stderr(`Observer: ${outcome.observerUrl}`);
|
|
45
|
+
});
|
|
46
|
+
return projection;
|
|
47
|
+
};
|
|
48
|
+
const project = createJournalProjector(run => open({ ...run, ...(liveSinceMs > 0 ? { resumed: true } : {}) }), liveSinceMs);
|
|
49
|
+
return {
|
|
50
|
+
onJournalEntry(entry) {
|
|
51
|
+
try {
|
|
52
|
+
project(entry);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
io.stderr(`[observer] could not project journal entry ${entry.seq}: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
onRunStarted: run => { open(run); },
|
|
59
|
+
onProgress(event) { projection?.step(event); },
|
|
60
|
+
finish(report) {
|
|
61
|
+
const runId = rootRunId ?? report.runId;
|
|
62
|
+
if (runId === undefined)
|
|
63
|
+
return undefined;
|
|
64
|
+
if (projection === undefined) {
|
|
65
|
+
io.stderr('[observer] this run was not projected (the daemon did not stream its journal); '
|
|
66
|
+
+ 'the observer link opens an empty channel');
|
|
67
|
+
}
|
|
68
|
+
projection?.finish({
|
|
69
|
+
status: report.status === 'parked' ? 'parked' : report.completionReason === 'canceled' ? 'canceled'
|
|
70
|
+
: report.ok ? 'completed' : 'failed',
|
|
71
|
+
...(report.completionReason === undefined ? {} : { completionReason: report.completionReason }),
|
|
72
|
+
});
|
|
73
|
+
const drained = projection?.close(DRAIN_GRACE_MS) ?? Promise.resolve();
|
|
74
|
+
return drained.then(() => mintFor(runId));
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=observer-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observer-session.js","sourceRoot":"","sources":["../../src/cli/observer-session.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/run.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { AuthoredFlowExecutionError, AuthoredHumanParked, type AuthoredHumanWait } from '../authored-flow-error.js';
|
|
2
2
|
import type { ProgressEvent } from '../progress.js';
|
|
3
|
+
import type { JournalEvent } from '../journal-reader.js';
|
|
3
4
|
import { type EnsureDaemonOptions } from '../daemon-lifecycle.js';
|
|
4
|
-
import type { RunFailureKind, RunWarningKind, StepFailedDetails } from '../failure-kinds.js';
|
|
5
|
+
import type { ParkCause, RunFailureKind, RunWarningKind, StepFailedDetails } from '../failure-kinds.js';
|
|
5
6
|
import { JournalClient } from '../journal-client.js';
|
|
6
7
|
import type { RunCompletionReason, RunOutcome, RunStatus } from '../protocol.js';
|
|
7
8
|
import type { StepType } from '../spec.js';
|
|
8
|
-
import type
|
|
9
|
+
import { type LoweredCompletionReason } from '../authored-completion.js';
|
|
9
10
|
import { type CheckReport } from './check.js';
|
|
10
11
|
export type RunExitCode = 0 | 1 | 2 | 3;
|
|
11
12
|
export type RunCommand = 'run' | 'resume' | 'answer';
|
|
@@ -28,6 +29,13 @@ export interface RunReport {
|
|
|
28
29
|
socketPath?: string;
|
|
29
30
|
status?: RunStatus;
|
|
30
31
|
completionReason?: RunCompletionReason;
|
|
32
|
+
/**
|
|
33
|
+
* What the body passed to `done(reason, { detail })`, normalized: redacted,
|
|
34
|
+
* trimmed, and bounded to 2,000 code points. Absent for every one-argument
|
|
35
|
+
* call, so an existing report keeps its exact shape — and absent on the
|
|
36
|
+
* paths where no authored body declared the outcome at all.
|
|
37
|
+
*/
|
|
38
|
+
completionDetail?: string;
|
|
31
39
|
completedSteps?: number;
|
|
32
40
|
reuse?: {
|
|
33
41
|
fromRunId: string;
|
|
@@ -35,6 +43,17 @@ export interface RunReport {
|
|
|
35
43
|
executedSteps: number;
|
|
36
44
|
};
|
|
37
45
|
parkedStep?: ParkedStep;
|
|
46
|
+
/**
|
|
47
|
+
* Why an exit-3 park happened, when classification established it.
|
|
48
|
+
*
|
|
49
|
+
* Carried structurally so a consumer — including this package's own authored
|
|
50
|
+
* boundaries — can tell "nothing is attached to run this step" from "the
|
|
51
|
+
* kernel is waiting for a human to recover it" without matching on the
|
|
52
|
+
* rendered message. Absent means the cause was not established, never
|
|
53
|
+
* `worker_unavailable` by default: recommending a worker for a `needs_human`
|
|
54
|
+
* park is the wrong answer, and guessing it is worse than saying nothing.
|
|
55
|
+
*/
|
|
56
|
+
parkCause?: ParkCause;
|
|
38
57
|
/** The open `f.human` question a parked authored run is waiting on. */
|
|
39
58
|
humanWait?: AuthoredHumanWait;
|
|
40
59
|
/** `flows answer` only: the answer it recorded. */
|
|
@@ -67,6 +86,14 @@ export interface RunLifecycleOptions {
|
|
|
67
86
|
onPtyReady?: (path: string) => void;
|
|
68
87
|
reuseFromRunId?: string;
|
|
69
88
|
onProgress?: (event: ProgressEvent) => void;
|
|
89
|
+
/** Stream the run's journal entries while it runs (YAML runs, via `run.start {watch}` / `run.watch`). */
|
|
90
|
+
onJournalEntry?: (entry: JournalEvent) => void;
|
|
91
|
+
/** An authored root was admitted: its id is known before its body runs. */
|
|
92
|
+
onRunStarted?: (run: {
|
|
93
|
+
runId: string;
|
|
94
|
+
flow: string;
|
|
95
|
+
resumed?: boolean;
|
|
96
|
+
}) => void;
|
|
70
97
|
localAgent?: boolean;
|
|
71
98
|
/** `--agent-capacity`: the local workers' concurrency; the default is `DEFAULT_LOCAL_AGENT_CAPACITY`. */
|
|
72
99
|
agentCapacity?: number;
|
|
@@ -129,6 +156,7 @@ export declare function authoredHumanParked(command: RunCommand, base: CheckRepo
|
|
|
129
156
|
export declare function authoredCompletion(command: RunCommand, base: RunReport, socketPath: string, result: {
|
|
130
157
|
name: string;
|
|
131
158
|
completionReason: LoweredCompletionReason;
|
|
159
|
+
completionDetail?: string;
|
|
132
160
|
journalSteps: readonly unknown[];
|
|
133
161
|
}, runId: string | undefined): RunExecution;
|
|
134
162
|
/**
|
package/dist/cli/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/run.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { onWorkerFailure } from '../worker-lease.js';
|
|
1
2
|
import { communicationInstruction } from '../communication/spec.js';
|
|
2
3
|
import { checkCommunicationEnvironment, CommunicationEnvironmentError } from '../communication/preflight.js';
|
|
3
4
|
import { parseHumanRecipient } from '../human-to.js';
|
|
@@ -12,11 +13,13 @@ import { socketPathFor } from '../daemon-connection.js';
|
|
|
12
13
|
import { ensureDaemon } from '../daemon-lifecycle.js';
|
|
13
14
|
import { isAuthoredFlowPath } from '../direct-input.js';
|
|
14
15
|
import { daemonRefusal } from './daemon-refusal.js';
|
|
16
|
+
import { authoredInput, authoredWorkerRemedy, localAgentRemedy, } from './local-agent-remedy.js';
|
|
15
17
|
import { inspectionHint, renderInspection, renderStepEvidence, stepFailureDetails } from './step-failure.js';
|
|
16
18
|
import { JournalClient, JournalProtocolError } from '../journal-client.js';
|
|
17
19
|
import { attachLocalAgent } from '../local-agent.js';
|
|
18
20
|
import { LlmWorker } from '../llm-worker.js';
|
|
19
21
|
import { readAuthoredRootMetadata, resumeDurableAuthoredFlow } from '../authored-root.js';
|
|
22
|
+
import { singleLineCompletionDetail, } from '../authored-completion.js';
|
|
20
23
|
import { DEFAULT_LOCAL_AGENT_CAPACITY } from '../worker-slots.js';
|
|
21
24
|
import { checkFlow, } from './check.js';
|
|
22
25
|
export async function runFlow(path, dataDir, options = {}) {
|
|
@@ -60,7 +63,9 @@ async function executeCheckedFlow(checked, dataDir, options) {
|
|
|
60
63
|
const { attachCommunicationWorkers } = await import('../communication/local.js');
|
|
61
64
|
communicationWorkers = await attachCommunicationWorkers(spec, socketPath, dataDir);
|
|
62
65
|
}
|
|
63
|
-
|
|
66
|
+
if (options.onJournalEntry !== undefined)
|
|
67
|
+
client.on('entry', options.onJournalEntry);
|
|
68
|
+
const outcome = await startWatched(client, spec, options);
|
|
64
69
|
const execution = await classifyOutcome(client, 'run', outcome, base, socketPath, { ...options, dataDir });
|
|
65
70
|
if (options.reuseFromRunId !== undefined) {
|
|
66
71
|
execution.report.reuse = await reuseSummary(client, outcome.run_id, options.reuseFromRunId);
|
|
@@ -81,6 +86,8 @@ async function executeCheckedFlow(checked, dataDir, options) {
|
|
|
81
86
|
return protocolFailure('run', base, socketPath, communicationWorkers?.failure ?? localAgent?.failure ?? error);
|
|
82
87
|
}
|
|
83
88
|
finally {
|
|
89
|
+
if (options.onJournalEntry !== undefined)
|
|
90
|
+
client.off('entry', options.onJournalEntry);
|
|
84
91
|
try {
|
|
85
92
|
await communicationWorkers?.close();
|
|
86
93
|
}
|
|
@@ -94,6 +101,26 @@ async function executeCheckedFlow(checked, dataDir, options) {
|
|
|
94
101
|
}
|
|
95
102
|
}
|
|
96
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* `run.start`, streaming the run's entries to `onJournalEntry` when one is
|
|
106
|
+
* given. A daemon that predates `watch` refuses the field while decoding,
|
|
107
|
+
* before any run exists, so starting again without it is the same request
|
|
108
|
+
* minus the observation — never a second run.
|
|
109
|
+
*/
|
|
110
|
+
async function startWatched(client, spec, options) {
|
|
111
|
+
const onEntry = options.onJournalEntry;
|
|
112
|
+
if (onEntry === undefined)
|
|
113
|
+
return client.runStart(spec, options.reuseFromRunId);
|
|
114
|
+
try {
|
|
115
|
+
return await client.runStart(spec, options.reuseFromRunId, undefined, true);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (!(error instanceof JournalProtocolError) || error.code !== 'bad_request'
|
|
119
|
+
|| !/unknown field `watch`/.test(error.message))
|
|
120
|
+
throw error;
|
|
121
|
+
return await client.runStart(spec, options.reuseFromRunId);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
97
124
|
export async function resumeFlow(runId, dataDir, options = {}) {
|
|
98
125
|
const socketPath = socketFor(dataDir);
|
|
99
126
|
const base = emptyReport('resume');
|
|
@@ -104,16 +131,32 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
104
131
|
let communicationWorkers;
|
|
105
132
|
let authoredAgent;
|
|
106
133
|
let authoredLlm;
|
|
134
|
+
let llmFailure;
|
|
107
135
|
let authoredLlmClient;
|
|
136
|
+
// Hoisted so the catch below can build the authored park remedy from the same
|
|
137
|
+
// metadata this resume was admitted against — the journal is the only place
|
|
138
|
+
// the flow path and the original `--input` survive a process boundary.
|
|
139
|
+
let authoredRoot;
|
|
108
140
|
const workerCapacity = options.agentCapacity ?? DEFAULT_LOCAL_AGENT_CAPACITY;
|
|
109
141
|
try {
|
|
110
|
-
|
|
142
|
+
authoredRoot = await readAuthoredRootMetadata(client, runId);
|
|
111
143
|
if (authoredRoot !== undefined) {
|
|
144
|
+
// Both worker-surface mismatches are refusals, not protocol failures.
|
|
145
|
+
// They used to throw bare `Error`s, which landed on `protocol_error`
|
|
146
|
+
// ("RUN <id> unknown") and told nobody what to do instead; and the
|
|
147
|
+
// second one is the exact complaint this change answers — `--local-agent`
|
|
148
|
+
// accepted on a run that cannot grow one is worse than rejected, because
|
|
149
|
+
// the run parks again with a message that has not changed.
|
|
112
150
|
if (authoredRoot.localAgentStream !== undefined && !options.localAgent) {
|
|
113
|
-
|
|
151
|
+
return localAgentRefusal(base, runId, socketPath, `Run "${runId}" was started with a local agent worker surface, so resuming it needs the same flag.`
|
|
152
|
+
+ ` To continue this run: ${resumeCommand(runId, dataDir, true)}.`);
|
|
114
153
|
}
|
|
115
154
|
if (authoredRoot.localAgentStream === undefined && options.localAgent) {
|
|
116
|
-
|
|
155
|
+
return localAgentRefusal(base, runId, socketPath, `Run "${runId}" was started without a local agent worker surface:`
|
|
156
|
+
+ ' --local-agent is admitted at run start; start a new run.'
|
|
157
|
+
+ localAgentRemedy(authoredWorkerRemedy('worker_unavailable', false, {
|
|
158
|
+
path: authoredRoot.flowPath, input: authoredInputArgument(authoredRoot), dataDir,
|
|
159
|
+
})));
|
|
117
160
|
}
|
|
118
161
|
if (options.localAgent) {
|
|
119
162
|
authoredAgent = await attachLocalAgent(client, dataDir, options.onPtyReady, authoredRoot.localAgentStream, workerCapacity);
|
|
@@ -121,6 +164,10 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
121
164
|
await authoredLlmClient.connect();
|
|
122
165
|
await authoredLlmClient.hello('flows-authored-resume-llm');
|
|
123
166
|
authoredLlm = new LlmWorker(authoredLlmClient, `${authoredAgent.stream}-llm`, workerCapacity);
|
|
167
|
+
authoredLlm.on('error', onWorkerFailure('resume-llm', error => {
|
|
168
|
+
llmFailure = error;
|
|
169
|
+
client.close();
|
|
170
|
+
}));
|
|
124
171
|
await authoredLlm.attach();
|
|
125
172
|
}
|
|
126
173
|
const result = await resumeDurableAuthoredFlow(runId, client, {
|
|
@@ -146,6 +193,13 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
146
193
|
communicationWorkers = await attachCommunicationWorkers(spec, socketPath, dataDir);
|
|
147
194
|
}
|
|
148
195
|
}
|
|
196
|
+
const onEntry = options.onJournalEntry;
|
|
197
|
+
if (onEntry !== undefined) {
|
|
198
|
+
client.on('entry', onEntry);
|
|
199
|
+
// Observation never decides a resume: a watch the daemon refuses leaves
|
|
200
|
+
// the run unprojected, and the resume below reports the run's own fate.
|
|
201
|
+
await client.runWatch(runId).catch(() => client.off('entry', onEntry));
|
|
202
|
+
}
|
|
149
203
|
let outcome = await client.runResume(runId, options.allowHumanInfluenced);
|
|
150
204
|
if (await resumeHelperEffect(client, runId, dataDir)) {
|
|
151
205
|
outcome = await client.runResume(runId, options.allowHumanInfluenced);
|
|
@@ -178,11 +232,38 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
178
232
|
if (error instanceof AuthoredFlowExecutionError && (error.code === 'step_failed' || error.code === 'gate_failed')) {
|
|
179
233
|
return authoredStepFailure('resume', base, socketPath, error, runId);
|
|
180
234
|
}
|
|
235
|
+
// An authored resume that parks for want of a worker is a park, reported
|
|
236
|
+
// like the run path's — and with the same remedy, because an authored root
|
|
237
|
+
// admits its worker at run start: resuming again cannot attach one, so the
|
|
238
|
+
// only honest instruction is a new run carrying the same `--input`.
|
|
239
|
+
// `runId` here is the CHILD run holding the evidence; the root this resume
|
|
240
|
+
// named stays separate, so `flows` can still collect it.
|
|
241
|
+
if (error instanceof AuthoredFlowExecutionError && (error.code === 'agent_parked' || error.code === 'llm_parked')) {
|
|
242
|
+
return {
|
|
243
|
+
exitCode: 3,
|
|
244
|
+
report: {
|
|
245
|
+
...base,
|
|
246
|
+
ok: false,
|
|
247
|
+
runId: error.runId ?? runId,
|
|
248
|
+
rootRunId: runId,
|
|
249
|
+
socketPath,
|
|
250
|
+
status: 'parked',
|
|
251
|
+
parkCause: error.parkCause,
|
|
252
|
+
diagnostics: [...base.diagnostics, {
|
|
253
|
+
severity: 'parked',
|
|
254
|
+
kind: 'run_parked',
|
|
255
|
+
message: error.message + localAgentRemedy(authoredWorkerRemedy(error.parkCause, options.localAgent === true, { path: authoredRoot?.flowPath, input: authoredInputArgument(authoredRoot), dataDir })),
|
|
256
|
+
}],
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
181
260
|
if (error instanceof AuthoredHumanParked) {
|
|
182
261
|
return authoredHumanParked('resume', base, socketPath, error, { dataDir, localAgent: options.localAgent === true });
|
|
183
262
|
}
|
|
184
263
|
if (!(error instanceof JournalProtocolError) || error.code !== 'run_not_found') {
|
|
185
|
-
|
|
264
|
+
const cause = error instanceof AuthoredFlowExecutionError
|
|
265
|
+
? error : llmFailure ?? authoredAgent?.failure ?? error;
|
|
266
|
+
return protocolFailure('resume', base, socketPath, cause, runId);
|
|
186
267
|
}
|
|
187
268
|
return {
|
|
188
269
|
exitCode: 2,
|
|
@@ -200,6 +281,8 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
200
281
|
}
|
|
201
282
|
finally {
|
|
202
283
|
try {
|
|
284
|
+
if (options.onJournalEntry !== undefined)
|
|
285
|
+
client.off('entry', options.onJournalEntry);
|
|
203
286
|
await communicationWorkers?.close();
|
|
204
287
|
await authoredLlm?.close();
|
|
205
288
|
authoredLlmClient?.close();
|
|
@@ -210,6 +293,42 @@ export async function resumeFlow(runId, dataDir, options = {}) {
|
|
|
210
293
|
}
|
|
211
294
|
}
|
|
212
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* A `--local-agent` mismatch, refused before the resume touches the journal.
|
|
298
|
+
*
|
|
299
|
+
* Exit 2 and `ok` left false by `emptyReport`: nothing ran, so this is the same
|
|
300
|
+
* shape as every other pre-journal refusal on this surface (docs/SURFACE.md §5).
|
|
301
|
+
* It returns rather than throwing so no worker is attached on the way out.
|
|
302
|
+
*/
|
|
303
|
+
function localAgentRefusal(base, runId, socketPath, message) {
|
|
304
|
+
return {
|
|
305
|
+
exitCode: 2,
|
|
306
|
+
report: { ...base, runId, socketPath,
|
|
307
|
+
diagnostics: [...base.diagnostics, { severity: 'refusal', kind: 'local_agent_unavailable', message }] },
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* The `--input` argument a new run of this authored root would have to repeat,
|
|
312
|
+
* rendered back from the journaled metadata.
|
|
313
|
+
*
|
|
314
|
+
* `absent` when the root recorded no input, and also when the recorded input is
|
|
315
|
+
* something `JSON.stringify` cannot render — the remedy formatter then says an
|
|
316
|
+
* input is required instead of printing a command that would be refused as
|
|
317
|
+
* `input_invalid`. What it must never do is substitute `{}`: that is a
|
|
318
|
+
* different invocation of the flow than the one that parked.
|
|
319
|
+
*
|
|
320
|
+
* Unlike `runDirectFlow`, this side has only the decoded value: the journal
|
|
321
|
+
* records the input, not the `--input` word that carried it, so a run started
|
|
322
|
+
* from a file comes back as inline JSON. `authoredInput` is what keeps that
|
|
323
|
+
* honest about its own size — a recorded input can be larger than a shell
|
|
324
|
+
* argument even when the file that supplied it was unremarkable.
|
|
325
|
+
*/
|
|
326
|
+
function authoredInputArgument(metadata) {
|
|
327
|
+
if (metadata === undefined || !metadata.inputPresent)
|
|
328
|
+
return { kind: 'absent' };
|
|
329
|
+
const rendered = JSON.stringify(metadata.input);
|
|
330
|
+
return authoredInput(typeof rendered === 'string' ? rendered : undefined);
|
|
331
|
+
}
|
|
213
332
|
/**
|
|
214
333
|
* A step that ran and failed, reported as the run failure it is.
|
|
215
334
|
*
|
|
@@ -302,8 +421,18 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
|
|
|
302
421
|
...fromBase(command, base),
|
|
303
422
|
...(runId === undefined ? {} : { runId }),
|
|
304
423
|
socketPath,
|
|
424
|
+
...(result.completionDetail === undefined ? {} : { completionDetail: result.completionDetail }),
|
|
305
425
|
completedSteps: result.journalSteps.length,
|
|
306
426
|
};
|
|
427
|
+
// Two spellings of the same fact, on purpose. `detail` is the structured
|
|
428
|
+
// one — the `StepFailedDetails` key the diagnostic already declares, here
|
|
429
|
+
// describing the AUTHOR's verdict rather than the daemon's account of a
|
|
430
|
+
// failing step — and keeps the body's own line breaks. `said` is the same
|
|
431
|
+
// text folded onto one line for the message, because Cloud renders a run's
|
|
432
|
+
// `error` through a view that elides the middle of a long one.
|
|
433
|
+
const detail = result.completionDetail;
|
|
434
|
+
const evidence = detail === undefined ? {} : { detail };
|
|
435
|
+
const said = detail === undefined ? '' : singleLineCompletionDetail(detail);
|
|
307
436
|
switch (result.completionReason) {
|
|
308
437
|
case 'success':
|
|
309
438
|
return {
|
|
@@ -317,7 +446,9 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
|
|
|
317
446
|
...common, ok: true, status: 'completed', completionReason: 'success',
|
|
318
447
|
diagnostics: [...base.diagnostics, {
|
|
319
448
|
severity: 'declined', kind: 'run_declined',
|
|
320
|
-
|
|
449
|
+
...evidence,
|
|
450
|
+
message: 'Flow deliberately chose not to act on this input.'
|
|
451
|
+
+ (detail === undefined ? '' : ` ${said}`),
|
|
321
452
|
}],
|
|
322
453
|
},
|
|
323
454
|
};
|
|
@@ -328,7 +459,9 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
|
|
|
328
459
|
...common, ok: false, status: 'parked',
|
|
329
460
|
diagnostics: [...base.diagnostics, {
|
|
330
461
|
severity: 'parked', kind: 'run_parked',
|
|
331
|
-
|
|
462
|
+
...evidence,
|
|
463
|
+
message: `Flow "${result.name}" needs_human; see the journal for accumulated blockers.`
|
|
464
|
+
+ (detail === undefined ? '' : ` ${said}`),
|
|
332
465
|
}],
|
|
333
466
|
},
|
|
334
467
|
};
|
|
@@ -344,9 +477,16 @@ export function authoredCompletion(command, base, socketPath, result, runId) {
|
|
|
344
477
|
...common, ok: false, status: 'failed', completionReason: 'step_failed',
|
|
345
478
|
diagnostics: [...base.diagnostics, {
|
|
346
479
|
severity: 'failure', kind: 'step_failed',
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
480
|
+
...evidence,
|
|
481
|
+
// With a detail, the flow's own account REPLACES the generic
|
|
482
|
+
// sentence: "no step-level evidence to inspect" is the only thing
|
|
483
|
+
// there is to say when the body said nothing, and saying it
|
|
484
|
+
// beside a real explanation would bury the explanation.
|
|
485
|
+
message: detail === undefined
|
|
486
|
+
? `Flow "${result.name}" declared done("step_failed"): its own checks did not pass. `
|
|
487
|
+
+ 'No step failed, so there is no step-level evidence to inspect; the journal holds '
|
|
488
|
+
+ 'every step the flow ran before it decided.'
|
|
489
|
+
: `Flow "${result.name}" declared done("step_failed"): ${said}`,
|
|
350
490
|
}],
|
|
351
491
|
},
|
|
352
492
|
};
|
|
@@ -540,31 +680,51 @@ export async function classifyOutcome(client, command, outcome, base, socketPath
|
|
|
540
680
|
report: {
|
|
541
681
|
...report,
|
|
542
682
|
parkedStep,
|
|
683
|
+
parkCause: needsHuman ? 'needs_human' : 'worker_unavailable',
|
|
543
684
|
diagnostics: [...report.diagnostics, {
|
|
544
685
|
severity: 'parked',
|
|
545
686
|
kind: 'run_parked',
|
|
546
687
|
message: needsHuman
|
|
547
688
|
? `Run "${current.run_id}" parked at step "${parkedStep.id}" (${parkedStep.type}): waiting for human recovery after the worker attempt failed.`
|
|
548
689
|
: `Run "${current.run_id}" parked at step "${parkedStep.id}" (${parkedStep.type}): no worker is attached for step type "${parkedStep.type}".`
|
|
549
|
-
|
|
550
|
-
// Authored TS flows require `--input`; the bare command below
|
|
551
|
-
// would be refused (Cursor Bugbot flagged as LOW on flows#293).
|
|
552
|
-
// For TS we omit the hint rather than fabricate a syntactically
|
|
553
|
-
// valid but semantically wrong command — the direct-run refusal
|
|
554
|
-
// for TS already names its own missing --input.
|
|
555
|
-
+ (command === 'run'
|
|
556
|
-
&& parkedStep.type === 'agent'
|
|
557
|
-
&& !options.localAgent
|
|
558
|
-
&& base.path !== undefined
|
|
559
|
-
&& !isAuthoredFlowPath(base.path)
|
|
560
|
-
? ` To start a new run with a local agent worker: flows run --local-agent '${base.path.replace(/'/g, "'\\''")}'. Declared workspace or stream surfaces require a worker that holds their pins.`
|
|
561
|
-
: ''),
|
|
690
|
+
+ localAgentRemedy(declarativeWorkerRemedy(command, current.run_id, parkedStep, base, options)),
|
|
562
691
|
}],
|
|
563
692
|
},
|
|
564
693
|
};
|
|
565
694
|
}
|
|
566
695
|
return protocolFailure(command, base, socketPath, new Error(`relayflowd returned status ${current.status} without a classifiable completion`), current.run_id);
|
|
567
696
|
}
|
|
697
|
+
/**
|
|
698
|
+
* Which remedy a worker park gets from the declarative classifier.
|
|
699
|
+
*
|
|
700
|
+
* An authored `.flow.ts` is deliberately SILENT here, and the suppression is
|
|
701
|
+
* tested first on purpose. Its remedy is a new run carrying the same `--input`,
|
|
702
|
+
* an argument this function does not have; `runDirectFlow` and `resumeFlow`
|
|
703
|
+
* render it once at the authored boundary where the input (or the journaled
|
|
704
|
+
* metadata holding it) is in hand. `classifyOutcome` also runs once per
|
|
705
|
+
* authored `f.agent` CHILD run, so answering here as well would append a
|
|
706
|
+
* remedy to every child message on the way out — and, on resume, a second
|
|
707
|
+
* contradictory one after the attached-worker branch below.
|
|
708
|
+
*
|
|
709
|
+
* `llm` parks get nothing, unchanged: the declarative verbs attach an
|
|
710
|
+
* agent-only worker (local-agent.ts advertises `['agent']`), so `--local-agent`
|
|
711
|
+
* is not a remedy for an `llm` step outside the authored path, which attaches
|
|
712
|
+
* an `LlmWorker` of its own.
|
|
713
|
+
*/
|
|
714
|
+
function declarativeWorkerRemedy(command, runId, parkedStep, base, options) {
|
|
715
|
+
const dataDir = options.dataDir;
|
|
716
|
+
if (parkedStep.type !== 'agent')
|
|
717
|
+
return { kind: 'none' };
|
|
718
|
+
if (base.path !== undefined && isAuthoredFlowPath(base.path))
|
|
719
|
+
return { kind: 'none' };
|
|
720
|
+
if (options.localAgent === true)
|
|
721
|
+
return { kind: 'attached' };
|
|
722
|
+
if (command === 'resume')
|
|
723
|
+
return { kind: 'spec-resume', runId, dataDir };
|
|
724
|
+
if (command === 'run' && base.path !== undefined)
|
|
725
|
+
return { kind: 'spec-run', path: base.path, dataDir };
|
|
726
|
+
return { kind: 'none' };
|
|
727
|
+
}
|
|
568
728
|
// Bound on re-polling a run that reports `running` with no identifiable step.
|
|
569
729
|
// 40 x 50ms = 2s, far longer than the sub-second window observed in #179, and
|
|
570
730
|
// short enough that a genuinely stuck run still reports rather than hangs.
|
|
@@ -593,6 +753,8 @@ async function inspectOutOfBandStep(client, runId) {
|
|
|
593
753
|
...(runningStep !== undefined ? { runningStep } : {}),
|
|
594
754
|
};
|
|
595
755
|
}
|
|
756
|
+
// Match kernel/relayflowd/src/server/client.rs: allow the lease sweep to dispatch a retry.
|
|
757
|
+
const LEASE_SWEEP_GRACE_MS = 5_000;
|
|
596
758
|
async function waitForRunningStep(client, runId, runningStep, options) {
|
|
597
759
|
let leaseDeadlineMs = runningStep.leaseDeadlineMs;
|
|
598
760
|
if (!Number.isFinite(leaseDeadlineMs)) {
|
|
@@ -606,7 +768,7 @@ async function waitForRunningStep(client, runId, runningStep, options) {
|
|
|
606
768
|
});
|
|
607
769
|
while (true) {
|
|
608
770
|
throwIfCanceled(options.signal, runningStep.id);
|
|
609
|
-
const remainingMs = leaseDeadlineMs - Date.now();
|
|
771
|
+
const remainingMs = leaseDeadlineMs + LEASE_SWEEP_GRACE_MS - Date.now();
|
|
610
772
|
if (remainingMs <= 0) {
|
|
611
773
|
throw new Error(`worker lease for step "${runningStep.id}" expired at ${leaseDeadlineMs} without completion`);
|
|
612
774
|
}
|