@relayflows/sdk 2.0.29 → 2.0.31
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 +64 -48
- 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-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 +48 -11
- package/dist/authored-worker-step.js.map +1 -1
- package/dist/bundle-extensions.d.ts.map +1 -1
- package/dist/bundle-extensions.js +4 -7
- package/dist/bundle-extensions.js.map +1 -1
- package/dist/bundle.d.ts.map +1 -1
- package/dist/bundle.js +41 -7
- package/dist/bundle.js.map +1 -1
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +18 -6
- package/dist/canonical.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 +19 -2
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +12 -4
- package/dist/cli/check.js.map +1 -1
- 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-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 +6 -0
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +2 -0
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +53 -42
- package/dist/cli.js.map +1 -1
- 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-extension-compat.d.ts.map +1 -1
- package/dist/flow-extension-compat.js +26 -8
- package/dist/flow-extension-compat.js.map +1 -1
- package/dist/flow-extension-loader.d.ts +7 -0
- package/dist/flow-extension-loader.d.ts.map +1 -1
- package/dist/flow-extension-loader.js +48 -22
- package/dist/flow-extension-loader.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/fs-descriptor.d.ts +17 -0
- package/dist/fs-descriptor.d.ts.map +1 -0
- package/dist/fs-descriptor.js +96 -0
- package/dist/fs-descriptor.js.map +1 -0
- 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-base-snapshot.d.ts +25 -0
- package/dist/hosted-base-snapshot.d.ts.map +1 -0
- package/dist/hosted-base-snapshot.js +278 -0
- package/dist/hosted-base-snapshot.js.map +1 -0
- package/dist/hosted-extension-declarations.d.ts +10 -0
- package/dist/hosted-extension-declarations.d.ts.map +1 -0
- package/dist/hosted-extension-declarations.js +272 -0
- package/dist/hosted-extension-declarations.js.map +1 -0
- package/dist/hosted-extension-isolation.d.ts +82 -0
- package/dist/hosted-extension-isolation.d.ts.map +1 -0
- package/dist/hosted-extension-isolation.js +322 -0
- package/dist/hosted-extension-isolation.js.map +1 -0
- package/dist/hosted-extension-manifest.d.ts +9 -0
- package/dist/hosted-extension-manifest.d.ts.map +1 -0
- package/dist/hosted-extension-manifest.js +235 -0
- package/dist/hosted-extension-manifest.js.map +1 -0
- package/dist/hosted-extension-protocol.d.ts +16 -0
- package/dist/hosted-extension-protocol.d.ts.map +1 -0
- package/dist/hosted-extension-protocol.js +224 -0
- package/dist/hosted-extension-protocol.js.map +1 -0
- package/dist/hosted-extension-runtime.d.ts +30 -0
- package/dist/hosted-extension-runtime.d.ts.map +1 -0
- package/dist/hosted-extension-runtime.js +167 -0
- package/dist/hosted-extension-runtime.js.map +1 -0
- package/dist/hosted-extension-sandbox-source.d.ts +9 -0
- package/dist/hosted-extension-sandbox-source.d.ts.map +1 -0
- package/dist/hosted-extension-sandbox-source.js +95 -0
- package/dist/hosted-extension-sandbox-source.js.map +1 -0
- package/dist/hosted-extension-sandbox.d.ts +39 -0
- package/dist/hosted-extension-sandbox.d.ts.map +1 -0
- package/dist/hosted-extension-sandbox.js +418 -0
- package/dist/hosted-extension-sandbox.js.map +1 -0
- package/dist/hosted-project.d.ts +3 -0
- package/dist/hosted-project.d.ts.map +1 -0
- package/dist/hosted-project.js +19 -0
- package/dist/hosted-project.js.map +1 -0
- package/dist/hosted-promise-safety.d.ts +12 -0
- package/dist/hosted-promise-safety.d.ts.map +1 -0
- package/dist/hosted-promise-safety.js +63 -0
- package/dist/hosted-promise-safety.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/intrinsic-array.d.ts +3 -0
- package/dist/intrinsic-array.d.ts.map +1 -0
- package/dist/intrinsic-array.js +14 -0
- package/dist/intrinsic-array.js.map +1 -0
- 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/json-value.d.ts +6 -1
- package/dist/json-value.d.ts.map +1 -1
- package/dist/json-value.js +155 -36
- package/dist/json-value.js.map +1 -1
- package/dist/llm-worker.d.ts +9 -0
- package/dist/llm-worker.d.ts.map +1 -1
- package/dist/llm-worker.js +16 -2
- 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/plugin-store.d.ts +8 -2
- package/dist/plugin-store.d.ts.map +1 -1
- package/dist/plugin-store.js +233 -56
- package/dist/plugin-store.js.map +1 -1
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +7 -0
- 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/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/semver-range.d.ts.map +1 -1
- package/dist/semver-range.js +27 -15
- package/dist/semver-range.js.map +1 -1
- 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 +101 -59
- 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-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 +60 -12
- package/src/bundle-extensions.ts +6 -5
- package/src/bundle.ts +52 -7
- package/src/canonical.ts +20 -6
- package/src/cli/check-worker-surface.ts +66 -0
- package/src/cli/check.ts +35 -4
- package/src/cli/cloud-format.ts +82 -0
- package/src/cli/cloud-live.ts +366 -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 +2 -0
- package/src/cli.ts +64 -44
- 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-extension-compat.ts +32 -7
- package/src/flow-extension-loader.ts +56 -21
- package/src/flow-requirements.ts +24 -9
- package/src/fs-descriptor.ts +127 -0
- package/src/gate-contract.ts +13 -1
- package/src/helper-preflight.ts +10 -3
- package/src/helper-reference.ts +130 -0
- package/src/hosted-base-snapshot.ts +351 -0
- package/src/hosted-extension-declarations.ts +387 -0
- package/src/hosted-extension-isolation.ts +457 -0
- package/src/hosted-extension-manifest.ts +249 -0
- package/src/hosted-extension-protocol.ts +262 -0
- package/src/hosted-extension-runtime.ts +266 -0
- package/src/hosted-extension-sandbox-source.ts +94 -0
- package/src/hosted-extension-sandbox.ts +489 -0
- package/src/hosted-project.ts +18 -0
- package/src/hosted-promise-safety.ts +68 -0
- package/src/index.ts +20 -0
- package/src/intrinsic-array.ts +14 -0
- package/src/journal-client.ts +19 -2
- package/src/journal-projection.ts +106 -0
- package/src/json-value.ts +184 -32
- package/src/llm-worker.ts +16 -2
- 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/plugin-store.ts +323 -56
- package/src/preflight.ts +7 -0
- package/src/protocol.ts +2 -0
- package/src/redact.ts +111 -0
- package/src/run-projection.ts +247 -0
- package/src/semver-range.ts +39 -14
- 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
package/src/cli/cloud-read.ts
CHANGED
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
// facts beneath it) so a reader who knows one knows the other.
|
|
14
14
|
|
|
15
15
|
import { canonicalize } from '../canonical.js';
|
|
16
|
-
import { CloudFlowError, type CloudConnectionOptions } from '../cloud-http.js';
|
|
17
16
|
import {
|
|
18
17
|
getCloudRunDetail, getCloudRunLog, getCloudRunSteps, listCloudRuns,
|
|
19
18
|
type CloudRunDetail, type CloudStep,
|
|
20
19
|
} from '../cloud-read.js';
|
|
21
20
|
import { parseAgentTranscript, renderAgentTranscript } from '../cloud-transcript.js';
|
|
22
21
|
import { redact } from '../redact.js';
|
|
23
|
-
import {
|
|
22
|
+
import { errorLines, instant, safe, thousands } from './cloud-format.js';
|
|
23
|
+
import { fail, refusalFor, RUN_ID_REQUIRED, type CloudReadOptions } from './cloud-refusal.js';
|
|
24
|
+
import { renderCloudStatus, scrubRun, scrubSteps } from './cloud-status-view.js';
|
|
24
25
|
import type { CliIo } from '../cli.js';
|
|
25
26
|
|
|
26
27
|
export interface RunsArgs {
|
|
@@ -35,17 +36,13 @@ export interface LogsArgs {
|
|
|
35
36
|
step: string | undefined;
|
|
36
37
|
raw: boolean;
|
|
37
38
|
json: boolean;
|
|
39
|
+
/** `--follow`: append new runner output until the run is terminal (cli/cloud-live.ts). */
|
|
40
|
+
follow: boolean;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
/** Enough runs to recognise the one you mean; `--limit` raises it. */
|
|
41
44
|
export const DEFAULT_RUN_LIMIT = 20;
|
|
42
45
|
|
|
43
|
-
/** Injected by tests; production takes the ambient clock and environment. */
|
|
44
|
-
export interface CloudReadOptions extends CloudConnectionOptions {
|
|
45
|
-
env?: NodeJS.ProcessEnv;
|
|
46
|
-
now?: () => number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
46
|
export function parseRunsArgs(args: readonly string[]): RunsArgs | undefined {
|
|
50
47
|
let limit: number | undefined;
|
|
51
48
|
let json = false;
|
|
@@ -69,6 +66,7 @@ export function parseLogsArgs(args: readonly string[]): LogsArgs | undefined {
|
|
|
69
66
|
let step: string | undefined;
|
|
70
67
|
let raw = false;
|
|
71
68
|
let json = false;
|
|
69
|
+
let follow = false;
|
|
72
70
|
const positionals: string[] = [];
|
|
73
71
|
for (let index = 0; index < args.length; index += 1) {
|
|
74
72
|
const argument = args[index]!;
|
|
@@ -78,6 +76,9 @@ export function parseLogsArgs(args: readonly string[]): LogsArgs | undefined {
|
|
|
78
76
|
} else if (argument === '--raw') {
|
|
79
77
|
if (raw) return undefined;
|
|
80
78
|
raw = true;
|
|
79
|
+
} else if (argument === '--follow') {
|
|
80
|
+
if (follow) return undefined;
|
|
81
|
+
follow = true;
|
|
81
82
|
} else if (argument === '--step') {
|
|
82
83
|
const value = args[++index];
|
|
83
84
|
if (step !== undefined || value === undefined || value.length === 0 || value.startsWith('-')) return undefined;
|
|
@@ -89,147 +90,7 @@ export function parseLogsArgs(args: readonly string[]): LogsArgs | undefined {
|
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
if (positionals.length !== 1) return undefined;
|
|
92
|
-
return { command: 'logs', runId: positionals[0]!, step, raw, json };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Every way these verbs can refuse, as a code and a sentence.
|
|
97
|
-
*
|
|
98
|
-
* Each one names the thing to do next. A missing credential names
|
|
99
|
-
* `agent-relay cloud login` because that is the command that fixes it; a 404
|
|
100
|
-
* names `flows runs` because the usual cause is a run id from another
|
|
101
|
-
* workspace, and the list is how you find yours.
|
|
102
|
-
*/
|
|
103
|
-
interface Refusal { code: string; message: string; exit: 1 | 2 }
|
|
104
|
-
|
|
105
|
-
function refusalFor(error: unknown, subject: string, env: NodeJS.ProcessEnv): Refusal {
|
|
106
|
-
const clean = (message: string): string => redact(message, env);
|
|
107
|
-
if (error instanceof CloudFlowError) {
|
|
108
|
-
if (error.code === 'configuration') {
|
|
109
|
-
switch (error.reason) {
|
|
110
|
-
case 'auth_missing':
|
|
111
|
-
return {
|
|
112
|
-
code: 'cloud_auth_missing', exit: 2,
|
|
113
|
-
message: 'No Cloud credential. Sign in with `agent-relay cloud login`, or set FLOWS_CLOUD_TOKEN to a '
|
|
114
|
-
+ 'Cloud API token with workflow:runs:read (and workflow:logs:read for `flows logs`).',
|
|
115
|
-
};
|
|
116
|
-
case 'auth_expired':
|
|
117
|
-
return { code: 'cloud_auth_expired', exit: 2, message: clean(error.message) };
|
|
118
|
-
case 'url_mismatch':
|
|
119
|
-
return { code: 'cloud_url_mismatch', exit: 2, message: clean(error.message) };
|
|
120
|
-
default:
|
|
121
|
-
return { code: 'cloud_configuration', exit: 2, message: clean(error.message) };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (error.code === 'http_error') {
|
|
125
|
-
if (error.status === 401) {
|
|
126
|
-
return {
|
|
127
|
-
code: 'cloud_auth_rejected', exit: 2,
|
|
128
|
-
message: 'Cloud rejected the credential (HTTP 401). The token is unknown or revoked; '
|
|
129
|
-
+ 'sign in again with `agent-relay cloud login`.',
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
if (error.status === 403) {
|
|
133
|
-
return {
|
|
134
|
-
code: 'cloud_forbidden', exit: 2,
|
|
135
|
-
message: `The credential is valid but not allowed to read ${subject} (HTTP 403). `
|
|
136
|
-
+ 'A run-scoped sandbox token may only read its own run; a workspace token needs '
|
|
137
|
-
+ 'workflow:runs:read, and workflow:logs:read or workflow:invoke:read for logs.',
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
if (error.status === 404) {
|
|
141
|
-
return {
|
|
142
|
-
code: 'cloud_run_not_found', exit: 2,
|
|
143
|
-
message: `Cloud has no ${subject} visible to this credential (HTTP 404). `
|
|
144
|
-
+ 'It may belong to another workspace; `flows runs` lists the ones this credential can read.',
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
return { code: 'cloud_http_error', exit: 1, message: clean(error.message) };
|
|
148
|
-
}
|
|
149
|
-
if (error.code === 'invalid_input') return { code: 'invalid_invocation', exit: 2, message: clean(error.message) };
|
|
150
|
-
if (error.code === 'transient_error' || error.code === 'transport_error') {
|
|
151
|
-
return { code: error.code === 'transient_error' ? 'cloud_unreachable' : 'cloud_transport_failed', exit: 1, message: clean(error.message) };
|
|
152
|
-
}
|
|
153
|
-
return { code: 'cloud_invalid_response', exit: 1, message: clean(error.message) };
|
|
154
|
-
}
|
|
155
|
-
return { code: 'cloud_read_failed', exit: 1, message: clean(error instanceof Error ? error.message : String(error)) };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function fail(refusal: Refusal, json: boolean, io: CliIo): 1 | 2 {
|
|
159
|
-
if (json) io.stdout(canonicalize({ v: 1, ok: false, code: refusal.code, message: refusal.message }));
|
|
160
|
-
else io.stderr(`REFUSED [${refusal.code}] ${refusal.message}`);
|
|
161
|
-
return refusal.exit;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function thousands(value: number): string {
|
|
165
|
-
return String(value).replace(/\B(?=(\d{3})+(?!\d))/gu, ',');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function dollars(value: number): string {
|
|
169
|
-
return `$${value.toFixed(6).replace(/0+$/u, '').replace(/\.$/u, '')}`;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Agent- and flow-authored names cannot inject terminal control sequences. */
|
|
173
|
-
function safe(text: string): string {
|
|
174
|
-
return text.replace(/[\u0000-\u001F\u007F-\u009F]/gu, '?');
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Render a run's `error` as readable lines rather than one control-char smear.
|
|
179
|
-
*
|
|
180
|
-
* Cloud stores the runner's terminal output in this field, newlines and all, so
|
|
181
|
-
* passing it through `safe()` alone turns a 200-line tail into a single line of
|
|
182
|
-
* `?` separators. Long runs are dominated by lease renewals — one line every
|
|
183
|
-
* 10s for the life of every agent step, differing only in the deadline — which
|
|
184
|
-
* are worth counting, not reading.
|
|
185
|
-
*
|
|
186
|
-
* Collapsing is deliberately narrow: two adjacent lines merge only when they
|
|
187
|
-
* are character-for-character identical once a trailing integer is masked. A
|
|
188
|
-
* shared prefix is NOT line identity — runner lines put the step name, reason
|
|
189
|
-
* or message after a long fixed prefix, so collapsing on a prefix would hide
|
|
190
|
-
* distinct diagnostics behind a similarity count. The final line never
|
|
191
|
-
* collapses into an earlier one, because that is where the failure is.
|
|
192
|
-
*/
|
|
193
|
-
const TRAILING_NUMBER = /\d+(?=\D{0,2}$)/u;
|
|
194
|
-
|
|
195
|
-
export function errorLines(text: string, indent: string): string[] {
|
|
196
|
-
const raw = text.split(/\r\n|\r|\n/u).map((line) => line.trimEnd()).filter((line) => line !== '');
|
|
197
|
-
if (raw.length === 0) return [];
|
|
198
|
-
|
|
199
|
-
const key = (line: string): string => line.replace(TRAILING_NUMBER, '#');
|
|
200
|
-
const collapsed: { line: string; count: number }[] = [];
|
|
201
|
-
raw.forEach((line, index) => {
|
|
202
|
-
const previous = collapsed.at(-1);
|
|
203
|
-
const isLast = index === raw.length - 1;
|
|
204
|
-
if (previous !== undefined && !isLast && key(previous.line) === key(line)) previous.count += 1;
|
|
205
|
-
else collapsed.push({ line, count: 1 });
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const rendered = collapsed.map(({ line, count }) =>
|
|
209
|
-
count === 1 ? safe(line) : `${safe(line)} (${count} times, differing only in a number)`);
|
|
210
|
-
|
|
211
|
-
const HEAD = 2;
|
|
212
|
-
const TAIL = 12;
|
|
213
|
-
if (rendered.length <= HEAD + TAIL + 1) return rendered.map((line) => `${indent}${line}`);
|
|
214
|
-
const elided = rendered.length - HEAD - TAIL;
|
|
215
|
-
return [
|
|
216
|
-
...rendered.slice(0, HEAD),
|
|
217
|
-
`… ${elided} more line${elided === 1 ? '' : 's'} (full text: --json)`,
|
|
218
|
-
...rendered.slice(-TAIL),
|
|
219
|
-
].map((line) => `${indent}${line}`);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/** ISO-8601 to the second: a list column, not a timestamp to do arithmetic on. */
|
|
223
|
-
function instant(value: string | null): string {
|
|
224
|
-
if (value === null) return 'unknown';
|
|
225
|
-
const parsed = Date.parse(value);
|
|
226
|
-
return Number.isFinite(parsed) ? new Date(parsed).toISOString().replace(/\.\d{3}Z$/u, 'Z') : 'unknown';
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function ago(value: string | null, now: number): string {
|
|
230
|
-
if (value === null) return 'unknown';
|
|
231
|
-
const parsed = Date.parse(value);
|
|
232
|
-
return Number.isFinite(parsed) ? `${formatDuration(now - parsed)} ago` : 'unknown';
|
|
93
|
+
return { command: 'logs', runId: positionals[0]!, step, raw, json, follow };
|
|
233
94
|
}
|
|
234
95
|
|
|
235
96
|
// ---------------------------------------------------------------- flows runs
|
|
@@ -361,113 +222,6 @@ export async function runCloudLogsCli(
|
|
|
361
222
|
|
|
362
223
|
// -------------------------------------------------------- flows status --cloud
|
|
363
224
|
|
|
364
|
-
const GLYPH: Record<string, string> = {
|
|
365
|
-
completed: '✓', succeeded: '✓', failed: '✗', cancelled: '✗', running: '↻', pending: '○', queued: '○',
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
function glyph(step: CloudStep): string {
|
|
369
|
-
if (step.status === 'completed' && step.completion_reason !== null && step.completion_reason !== 'success') return '✗';
|
|
370
|
-
return GLYPH[step.status] ?? '○';
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/** The `steps N: 3 done · 1 running` line, counted off whatever Cloud called each status. */
|
|
374
|
-
function stepCounts(steps: readonly CloudStep[]): string {
|
|
375
|
-
const counts = new Map<string, number>();
|
|
376
|
-
for (const step of steps) counts.set(step.status, (counts.get(step.status) ?? 0) + 1);
|
|
377
|
-
const parts = [...counts].map(([status, count]) => `${count} ${status}`);
|
|
378
|
-
return `steps ${steps.length}${parts.length === 0 ? '' : `: ${parts.join(' · ')}`}`;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
function renderStep(step: CloudStep, runId: string, idWidth: number): string[] {
|
|
382
|
-
const cells = [
|
|
383
|
-
safe(step.step_name).slice(0, 24).padEnd(idWidth),
|
|
384
|
-
step.step_type.padEnd(13),
|
|
385
|
-
step.status.padEnd(11),
|
|
386
|
-
];
|
|
387
|
-
const attempts = step.attempts.length;
|
|
388
|
-
if (attempts > 0) cells.push(`${attempts} attempt${attempts === 1 ? '' : 's'}`);
|
|
389
|
-
if (step.duration_ms !== null) cells.push(formatDuration(step.duration_ms));
|
|
390
|
-
if (step.completion_reason !== null) cells.push(safe(step.completion_reason));
|
|
391
|
-
if (step.gate !== null) cells.push(`gate: ${safe(step.gate.gate)} ${safe(step.gate.verdict)}`);
|
|
392
|
-
const lines = [` ${glyph(step)} ${cells.join(' ')}`.trimEnd()];
|
|
393
|
-
|
|
394
|
-
if (step.gate !== null && step.gate.verdict !== 'pass' && step.gate.detail.length > 0) {
|
|
395
|
-
lines.push(` gate: ${safe(step.gate.gate)} ${step.gate.verdict.toUpperCase()} — ${JSON.stringify(safe(step.gate.detail))}`);
|
|
396
|
-
}
|
|
397
|
-
const transcript = step.transcript;
|
|
398
|
-
if (transcript !== null) {
|
|
399
|
-
const facts = [
|
|
400
|
-
transcript.model === null ? null : safe(transcript.model),
|
|
401
|
-
transcript.num_turns === null ? null : `${transcript.num_turns} turn${transcript.num_turns === 1 ? '' : 's'}`,
|
|
402
|
-
transcript.total_calls === null ? null : `${transcript.total_calls} tool call${transcript.total_calls === 1 ? '' : 's'}`,
|
|
403
|
-
transcript.total_cost_usd === null ? null : dollars(transcript.total_cost_usd),
|
|
404
|
-
].filter((fact): fact is string => fact !== null);
|
|
405
|
-
lines.push(` transcript (attempt ${transcript.attempt ?? step.attempts.length})${facts.length === 0 ? '' : `: ${facts.join(' · ')}`}`);
|
|
406
|
-
if (transcript.frames_total !== null || transcript.bytes_total !== null) {
|
|
407
|
-
const frames = transcript.frames_total === null ? ''
|
|
408
|
-
: `${thousands(transcript.frames_kept ?? transcript.frames_total)} of ${thousands(transcript.frames_total)} frames`;
|
|
409
|
-
const bytes = transcript.bytes_total === null ? '' : `${thousands(transcript.bytes_total)} bytes`;
|
|
410
|
-
const cut = transcript.truncated ? ', truncated' : '';
|
|
411
|
-
lines.push(` ${[frames, bytes].filter((part) => part.length > 0).join(', ')}${cut}`);
|
|
412
|
-
}
|
|
413
|
-
if (transcript.tokens_in !== null || transcript.tokens_out !== null) {
|
|
414
|
-
const cache = [
|
|
415
|
-
transcript.cache_read === null ? null : `${thousands(transcript.cache_read)} cache read`,
|
|
416
|
-
transcript.cache_creation === null ? null : `${thousands(transcript.cache_creation)} cache write`,
|
|
417
|
-
].filter((part): part is string => part !== null);
|
|
418
|
-
lines.push(` ${thousands(transcript.tokens_in ?? 0)} in / ${thousands(transcript.tokens_out ?? 0)} out`
|
|
419
|
-
+ `${cache.length === 0 ? '' : ` · ${cache.join(' · ')}`}`);
|
|
420
|
-
}
|
|
421
|
-
if (transcript.tools.length > 0) {
|
|
422
|
-
lines.push(` tools: ${transcript.tools.map((tool) =>
|
|
423
|
-
`${safe(tool.name)} ×${tool.calls ?? 0}${tool.errors ? ` (${tool.errors} error${tool.errors === 1 ? '' : 's'})` : ''}`).join(', ')}`);
|
|
424
|
-
}
|
|
425
|
-
for (const call of transcript.last_calls) {
|
|
426
|
-
const excerpt = call.input_excerpt === null ? '' : ` ${safe(call.input_excerpt).slice(0, 120)}`;
|
|
427
|
-
lines.push(` call ${call.seq ?? '?'} ${safe(call.name)}${excerpt} → ${thousands(call.result_bytes ?? 0)} bytes`);
|
|
428
|
-
}
|
|
429
|
-
lines.push(` artifacts: ${transcript.artifacts.length === 0
|
|
430
|
-
? 'none' : transcript.artifacts.slice(0, 10).map(safe).join(', ')}`);
|
|
431
|
-
}
|
|
432
|
-
if (step.sandbox_id.length > 0) lines.push(` logs: flows logs ${runId} --step ${safe(step.sandbox_id)}`);
|
|
433
|
-
return lines;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function renderCloudStatus(run: CloudRunDetail, steps: readonly CloudStep[], now: number): string[] {
|
|
437
|
-
let tokensIn = 0;
|
|
438
|
-
let tokensOut = 0;
|
|
439
|
-
let cost = 0;
|
|
440
|
-
for (const step of steps) {
|
|
441
|
-
tokensIn += step.tokens_in ?? 0;
|
|
442
|
-
tokensOut += step.tokens_out ?? 0;
|
|
443
|
-
cost += step.cost_usd ?? 0;
|
|
444
|
-
}
|
|
445
|
-
// Summed from the step rows, because the run record carries no total. Cloud
|
|
446
|
-
// stores `costUsd` as a float, so this is a float sum — not the exact decimal
|
|
447
|
-
// addition the local journal fold does (run-state.ts `addDollars`). Shown to
|
|
448
|
-
// six places and labelled `spend`, the same word the local view uses.
|
|
449
|
-
const spend = `${thousands(tokensIn)} in / ${thousands(tokensOut)} out / ${dollars(cost)}`;
|
|
450
|
-
const finished = run.completion_reason === null ? '' : ` finished ${safe(run.completion_reason)}`;
|
|
451
|
-
const lines = [
|
|
452
|
-
`RUN ${run.run_id} ${safe(run.name)} ${run.status} started ${ago(run.created_at, now)}${finished} spend ${spend}`,
|
|
453
|
-
stepCounts(steps),
|
|
454
|
-
];
|
|
455
|
-
if (run.authority !== null) {
|
|
456
|
-
const facts = [
|
|
457
|
-
run.authority.surface_version === null ? null : `surface ${run.authority.surface_version}`,
|
|
458
|
-
run.authority.artifact_sha256 === null ? null : `artifact ${run.authority.artifact_sha256.slice(0, 12)}`,
|
|
459
|
-
run.authority.source_commit === null ? null : `commit ${run.authority.source_commit.slice(0, 12)}`,
|
|
460
|
-
].filter((fact): fact is string => fact !== null);
|
|
461
|
-
if (facts.length > 0) lines.push(`authority ${facts.join(' · ')}`);
|
|
462
|
-
}
|
|
463
|
-
if (run.pull_request_url !== null) lines.push(`pr ${run.pull_request_url}`);
|
|
464
|
-
if (run.error !== null) lines.push('error', ...errorLines(run.error, ' '));
|
|
465
|
-
lines.push('');
|
|
466
|
-
const idWidth = Math.max(4, ...steps.map((step) => Math.min(24, step.step_name.length)));
|
|
467
|
-
for (const step of steps) lines.push(...renderStep(step, run.run_id, idWidth));
|
|
468
|
-
return lines;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
225
|
export async function runCloudStatusCli(
|
|
472
226
|
args: { runId?: string; json: boolean },
|
|
473
227
|
io: CliIo,
|
|
@@ -475,13 +229,7 @@ export async function runCloudStatusCli(
|
|
|
475
229
|
): Promise<0 | 1 | 2> {
|
|
476
230
|
const env = options.env ?? process.env;
|
|
477
231
|
const now = (options.now ?? Date.now)();
|
|
478
|
-
if (args.runId === undefined || args.runId.length === 0)
|
|
479
|
-
return fail({
|
|
480
|
-
code: 'run_unknown', exit: 2,
|
|
481
|
-
message: '`flows status --cloud` needs the hosted run id; `flows runs` lists them. '
|
|
482
|
-
+ '(Without --cloud the run id defaults to RELAYFLOW_RUN_ID inside a step.)',
|
|
483
|
-
}, args.json, io);
|
|
484
|
-
}
|
|
232
|
+
if (args.runId === undefined || args.runId.length === 0) return fail(RUN_ID_REQUIRED, args.json, io);
|
|
485
233
|
let run: CloudRunDetail;
|
|
486
234
|
let steps: CloudStep[];
|
|
487
235
|
try {
|
|
@@ -490,25 +238,8 @@ export async function runCloudStatusCli(
|
|
|
490
238
|
} catch (error) {
|
|
491
239
|
return fail(refusalFor(error, `run ${args.runId}`, env), args.json, io);
|
|
492
240
|
}
|
|
493
|
-
const scrubbed
|
|
494
|
-
|
|
495
|
-
name: redact(run.name, env),
|
|
496
|
-
error: run.error === null ? null : redact(run.error, env),
|
|
497
|
-
};
|
|
498
|
-
const scrubbedSteps = steps.map((step) => ({
|
|
499
|
-
...step,
|
|
500
|
-
output_summary: step.output_summary === null ? null : redact(step.output_summary, env),
|
|
501
|
-
gate: step.gate === null ? null : { ...step.gate, detail: redact(step.gate.detail, env) },
|
|
502
|
-
transcript: step.transcript === null ? null : {
|
|
503
|
-
...step.transcript,
|
|
504
|
-
model: step.transcript.model === null ? null : redact(step.transcript.model, env),
|
|
505
|
-
last_calls: step.transcript.last_calls.map((call) => ({
|
|
506
|
-
...call,
|
|
507
|
-
input_excerpt: call.input_excerpt === null ? null : redact(call.input_excerpt, env),
|
|
508
|
-
})),
|
|
509
|
-
artifacts: step.transcript.artifacts.map((path) => redact(path, env)),
|
|
510
|
-
},
|
|
511
|
-
}));
|
|
241
|
+
const scrubbed = scrubRun(run, env);
|
|
242
|
+
const scrubbedSteps = scrubSteps(steps, env);
|
|
512
243
|
if (args.json) {
|
|
513
244
|
io.stdout(canonicalize({ v: 1, ok: true, run: scrubbed, steps: scrubbedSteps, now_ms: now }));
|
|
514
245
|
return 0;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Every way a hosted read can refuse, as a code, a sentence and an exit.
|
|
2
|
+
//
|
|
3
|
+
// Moved out of `cli/cloud-read.ts` when the live views needed to refuse in
|
|
4
|
+
// exactly the same words: `flows status --cloud --watch` that meets a 404 must
|
|
5
|
+
// say what `flows status --cloud` says, or a reader would have to learn two
|
|
6
|
+
// vocabularies for one failure. A dependency-only module — it imports no other
|
|
7
|
+
// Cloud CLI module, so the one-shot and live entry points can both use it with
|
|
8
|
+
// no import cycle between them.
|
|
9
|
+
|
|
10
|
+
import { canonicalize } from '../canonical.js';
|
|
11
|
+
import { CloudFlowError, type CloudConnectionOptions } from '../cloud-http.js';
|
|
12
|
+
import { redact } from '../redact.js';
|
|
13
|
+
import type { CliIo } from '../cli.js';
|
|
14
|
+
|
|
15
|
+
/** Injected by tests; production takes the ambient clock and environment. */
|
|
16
|
+
export interface CloudReadOptions extends CloudConnectionOptions {
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
18
|
+
now?: () => number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Every way these verbs can refuse, as a code and a sentence.
|
|
23
|
+
*
|
|
24
|
+
* Each one names the thing to do next. A missing credential names
|
|
25
|
+
* `agent-relay cloud login` because that is the command that fixes it; a 404
|
|
26
|
+
* names `flows runs` because the usual cause is a run id from another
|
|
27
|
+
* workspace, and the list is how you find yours.
|
|
28
|
+
*/
|
|
29
|
+
export interface Refusal { code: string; message: string; exit: 1 | 2 }
|
|
30
|
+
|
|
31
|
+
export function refusalFor(error: unknown, subject: string, env: NodeJS.ProcessEnv): Refusal {
|
|
32
|
+
const clean = (message: string): string => redact(message, env);
|
|
33
|
+
if (error instanceof CloudFlowError) {
|
|
34
|
+
if (error.code === 'configuration') {
|
|
35
|
+
switch (error.reason) {
|
|
36
|
+
case 'auth_missing':
|
|
37
|
+
return {
|
|
38
|
+
code: 'cloud_auth_missing', exit: 2,
|
|
39
|
+
message: 'No Cloud credential. Sign in with `agent-relay cloud login`, or set FLOWS_CLOUD_TOKEN to a '
|
|
40
|
+
+ 'Cloud API token with workflow:runs:read (and workflow:logs:read for `flows logs`).',
|
|
41
|
+
};
|
|
42
|
+
case 'auth_expired':
|
|
43
|
+
return { code: 'cloud_auth_expired', exit: 2, message: clean(error.message) };
|
|
44
|
+
case 'url_mismatch':
|
|
45
|
+
return { code: 'cloud_url_mismatch', exit: 2, message: clean(error.message) };
|
|
46
|
+
default:
|
|
47
|
+
return { code: 'cloud_configuration', exit: 2, message: clean(error.message) };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (error.code === 'http_error') {
|
|
51
|
+
if (error.status === 401) {
|
|
52
|
+
return {
|
|
53
|
+
code: 'cloud_auth_rejected', exit: 2,
|
|
54
|
+
message: 'Cloud rejected the credential (HTTP 401). The token is unknown or revoked; '
|
|
55
|
+
+ 'sign in again with `agent-relay cloud login`.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (error.status === 403) {
|
|
59
|
+
return {
|
|
60
|
+
code: 'cloud_forbidden', exit: 2,
|
|
61
|
+
message: `The credential is valid but not allowed to read ${subject} (HTTP 403). `
|
|
62
|
+
+ 'A run-scoped sandbox token may only read its own run; a workspace token needs '
|
|
63
|
+
+ 'workflow:runs:read, and workflow:logs:read or workflow:invoke:read for logs.',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (error.status === 404) {
|
|
67
|
+
return {
|
|
68
|
+
code: 'cloud_run_not_found', exit: 2,
|
|
69
|
+
message: `Cloud has no ${subject} visible to this credential (HTTP 404). `
|
|
70
|
+
+ 'It may belong to another workspace; `flows runs` lists the ones this credential can read.',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { code: 'cloud_http_error', exit: 1, message: clean(error.message) };
|
|
74
|
+
}
|
|
75
|
+
if (error.code === 'invalid_input') return { code: 'invalid_invocation', exit: 2, message: clean(error.message) };
|
|
76
|
+
if (error.code === 'transient_error' || error.code === 'transport_error') {
|
|
77
|
+
return { code: error.code === 'transient_error' ? 'cloud_unreachable' : 'cloud_transport_failed', exit: 1, message: clean(error.message) };
|
|
78
|
+
}
|
|
79
|
+
return { code: 'cloud_invalid_response', exit: 1, message: clean(error.message) };
|
|
80
|
+
}
|
|
81
|
+
return { code: 'cloud_read_failed', exit: 1, message: clean(error instanceof Error ? error.message : String(error)) };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function fail(refusal: Refusal, json: boolean, io: CliIo): 1 | 2 {
|
|
85
|
+
if (json) io.stdout(canonicalize({ v: 1, ok: false, code: refusal.code, message: refusal.message }));
|
|
86
|
+
else io.stderr(`REFUSED [${refusal.code}] ${refusal.message}`);
|
|
87
|
+
return refusal.exit;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* `flows status --cloud` with no run id.
|
|
92
|
+
*
|
|
93
|
+
* Shared by the one-shot and watched forms so both name the same remedy: a
|
|
94
|
+
* hosted run has no ambient id the way a step inside a local run does.
|
|
95
|
+
*/
|
|
96
|
+
export const RUN_ID_REQUIRED: Refusal = {
|
|
97
|
+
code: 'run_unknown', exit: 2,
|
|
98
|
+
message: '`flows status --cloud` needs the hosted run id; `flows runs` lists them. '
|
|
99
|
+
+ '(Without --cloud the run id defaults to RELAYFLOW_RUN_ID inside a step.)',
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A read that a poll can retry rather than end on.
|
|
104
|
+
*
|
|
105
|
+
* The same set `waitForCloudFlowRun` retries: the failure says the request did
|
|
106
|
+
* not complete, not that the request was wrong. Anything else — a 404, a
|
|
107
|
+
* rejected credential, a response this client cannot trust — ends the command
|
|
108
|
+
* through `refusalFor`, exactly as it ends a one-shot read.
|
|
109
|
+
*/
|
|
110
|
+
export function isTransientRead(error: unknown): boolean {
|
|
111
|
+
return error instanceof CloudFlowError && (error.code === 'transient_error'
|
|
112
|
+
|| (error.code === 'http_error' && [408, 429, 500, 502, 503, 504].includes(error.status ?? 0)));
|
|
113
|
+
}
|