@boardwalk-labs/runner 0.1.2

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.
Files changed (97) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +68 -0
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +214 -0
  5. package/dist/contract.d.ts +154 -0
  6. package/dist/contract.js +196 -0
  7. package/dist/daemon/daemon.d.ts +45 -0
  8. package/dist/daemon/daemon.js +129 -0
  9. package/dist/daemon/identity.d.ts +15 -0
  10. package/dist/daemon/identity.js +44 -0
  11. package/dist/daemon/index.d.ts +3 -0
  12. package/dist/daemon/index.js +4 -0
  13. package/dist/daemon/pool_client.d.ts +31 -0
  14. package/dist/daemon/pool_client.js +101 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +8 -0
  17. package/dist/runtime/agent/budget.d.ts +123 -0
  18. package/dist/runtime/agent/budget.js +174 -0
  19. package/dist/runtime/agent/events.d.ts +46 -0
  20. package/dist/runtime/agent/events.js +8 -0
  21. package/dist/runtime/agent/model_rates.d.ts +7 -0
  22. package/dist/runtime/agent/model_rates.js +21 -0
  23. package/dist/runtime/agent/secret_redactor.d.ts +42 -0
  24. package/dist/runtime/agent/secret_redactor.js +98 -0
  25. package/dist/runtime/broker_artifact_store.d.ts +17 -0
  26. package/dist/runtime/broker_artifact_store.js +46 -0
  27. package/dist/runtime/broker_child_dispatcher.d.ts +31 -0
  28. package/dist/runtime/broker_child_dispatcher.js +88 -0
  29. package/dist/runtime/broker_event_publisher.d.ts +25 -0
  30. package/dist/runtime/broker_event_publisher.js +69 -0
  31. package/dist/runtime/broker_tool_host.d.ts +49 -0
  32. package/dist/runtime/broker_tool_host.js +240 -0
  33. package/dist/runtime/cancel_watcher.d.ts +31 -0
  34. package/dist/runtime/cancel_watcher.js +77 -0
  35. package/dist/runtime/credit_watcher.d.ts +30 -0
  36. package/dist/runtime/credit_watcher.js +78 -0
  37. package/dist/runtime/direct_inference.d.ts +29 -0
  38. package/dist/runtime/direct_inference.js +78 -0
  39. package/dist/runtime/index.d.ts +85 -0
  40. package/dist/runtime/index.js +525 -0
  41. package/dist/runtime/inference_transport.d.ts +5 -0
  42. package/dist/runtime/inference_transport.js +9 -0
  43. package/dist/runtime/leaf_executor.d.ts +104 -0
  44. package/dist/runtime/leaf_executor.js +333 -0
  45. package/dist/runtime/lease_renewer.d.ts +31 -0
  46. package/dist/runtime/lease_renewer.js +80 -0
  47. package/dist/runtime/main.d.ts +1 -0
  48. package/dist/runtime/main.js +7 -0
  49. package/dist/runtime/phase_tracker.d.ts +26 -0
  50. package/dist/runtime/phase_tracker.js +45 -0
  51. package/dist/runtime/program_log_capture.d.ts +20 -0
  52. package/dist/runtime/program_log_capture.js +79 -0
  53. package/dist/runtime/program_runner.d.ts +82 -0
  54. package/dist/runtime/program_runner.js +116 -0
  55. package/dist/runtime/program_worker.d.ts +177 -0
  56. package/dist/runtime/program_worker.js +272 -0
  57. package/dist/runtime/recording_secret_resolver.d.ts +9 -0
  58. package/dist/runtime/recording_secret_resolver.js +22 -0
  59. package/dist/runtime/run_abort.d.ts +16 -0
  60. package/dist/runtime/run_abort.js +38 -0
  61. package/dist/runtime/run_event_emitter.d.ts +24 -0
  62. package/dist/runtime/run_event_emitter.js +63 -0
  63. package/dist/runtime/runner_control_client.d.ts +184 -0
  64. package/dist/runtime/runner_control_client.js +501 -0
  65. package/dist/runtime/runtime_flusher.d.ts +41 -0
  66. package/dist/runtime/runtime_flusher.js +90 -0
  67. package/dist/runtime/sandbox_config.d.ts +21 -0
  68. package/dist/runtime/sandbox_config.js +34 -0
  69. package/dist/runtime/support/index.d.ts +53 -0
  70. package/dist/runtime/support/index.js +114 -0
  71. package/dist/runtime/suspension.d.ts +141 -0
  72. package/dist/runtime/suspension.js +120 -0
  73. package/dist/runtime/testing_artifact_build.d.ts +27 -0
  74. package/dist/runtime/testing_artifact_build.js +96 -0
  75. package/dist/runtime/tools/artifacts.d.ts +146 -0
  76. package/dist/runtime/tools/artifacts.js +125 -0
  77. package/dist/runtime/tools/types.d.ts +114 -0
  78. package/dist/runtime/tools/types.js +61 -0
  79. package/dist/runtime/tools/web_search.d.ts +66 -0
  80. package/dist/runtime/tools/web_search.js +165 -0
  81. package/dist/runtime/wire/artifact_storage.d.ts +37 -0
  82. package/dist/runtime/wire/artifact_storage.js +93 -0
  83. package/dist/runtime/wire/artifact_verify.d.ts +1 -0
  84. package/dist/runtime/wire/artifact_verify.js +8 -0
  85. package/dist/runtime/wire/human_input.d.ts +62 -0
  86. package/dist/runtime/wire/human_input.js +156 -0
  87. package/dist/runtime/wire/inference_proxy.d.ts +70 -0
  88. package/dist/runtime/wire/inference_proxy.js +157 -0
  89. package/dist/runtime/wire/manifest.d.ts +16 -0
  90. package/dist/runtime/wire/manifest.js +18 -0
  91. package/dist/runtime/wire/run.d.ts +54 -0
  92. package/dist/runtime/wire/run.js +2 -0
  93. package/dist/runtime/workflow_host.d.ts +194 -0
  94. package/dist/runtime/workflow_host.js +382 -0
  95. package/dist/runtime/workspace_store.d.ts +73 -0
  96. package/dist/runtime/workspace_store.js +118 -0
  97. package/package.json +70 -0
@@ -0,0 +1,22 @@
1
+ // RecordingSecretResolver — the redaction feeder (MASTER_SPEC §12, plan #9).
2
+ //
3
+ // Decorates any SecretResolver so EVERY value a run resolves — whether the workflow program asked
4
+ // via `secrets.get(name)` or a tool asked via `ctx.secrets.resolve(ref)` — is recorded into the
5
+ // run's SecretRedactor. The leaf executor then scrubs those known values out of all LLM-bound
6
+ // content. Wrapping at the resolver level means there is exactly one chokepoint: a value cannot be
7
+ // resolved without becoming redactable.
8
+ //
9
+ // A failed resolve (FORBIDDEN/NOT_FOUND) records nothing — the error propagates unchanged.
10
+ export class RecordingSecretResolver {
11
+ inner;
12
+ redactor;
13
+ constructor(inner, redactor) {
14
+ this.inner = inner;
15
+ this.redactor = redactor;
16
+ }
17
+ async resolve(ref) {
18
+ const value = await this.inner.resolve(ref);
19
+ this.redactor.record(value);
20
+ return value;
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ /** Why a run was aborted mid-flight. Extensible — user-initiated cancel will add to this.
2
+ * `lease_lost`: another worker reclaimed this run (our lease expired + a sweep re-dispatched it),
3
+ * so we must stop WITHOUT finalizing — the new owner owns the terminal write. */
4
+ export type AbortReason = "credit_exhausted" | "cancelled" | "lease_lost";
5
+ /** Thrown by WorkflowHost hooks once the run's AbortSignal has fired, so the program unwinds. A plain
6
+ * Error subclass (no AppError/model coupling) carrying the machine-readable reason. */
7
+ export declare class RunAbortedError extends Error {
8
+ readonly reason: AbortReason;
9
+ constructor(reason: AbortReason);
10
+ }
11
+ /** The reason an aborted signal carries (set via `controller.abort(new RunAbortedError(reason))`), or
12
+ * null when the signal isn't aborted / wasn't aborted with a RunAbortedError. */
13
+ export declare function abortReason(signal: AbortSignal): AbortReason | null;
14
+ /** Throw if the signal has already aborted — the guard every WorkflowHost hook calls at entry. Re-uses
15
+ * the signal's own RunAbortedError when present, so the reason propagates verbatim. */
16
+ export declare function throwIfAborted(signal: AbortSignal | undefined): void;
@@ -0,0 +1,38 @@
1
+ // run_abort — the provider-agnostic cooperative-cancellation substrate for a run (docs/RUNNER_BROKER.md
2
+ // §15 credit watching; the foundation user-initiated cancel will reuse).
3
+ //
4
+ // The cancellation primitive is a Web-standard `AbortSignal` — NOT a Strands/model concept. The worker
5
+ // owns one `AbortController` per run session; a watcher (credit, later user-cancel) calls
6
+ // `controller.abort(new RunAbortedError(reason))`. The WorkflowHost honors that signal at every hook
7
+ // boundary (`agent`/`sleep`/`workflows.call`/…), unwinding the program. The ONLY place that translates
8
+ // the signal into a model-specific stop is the Strands leaf (signal → `agent.cancel()`); a future
9
+ // non-Strands leaf honors the SAME `AbortSignal` its own way. So nothing here, in the host, or in the
10
+ // program-facing SDK depends on the model backend.
11
+ //
12
+ // `signal.aborted` is AUTHORITATIVE at the orchestrator: a program that catches RunAbortedError and
13
+ // keeps going still stops, because every subsequent host hook re-throws and the orchestrator finalizes
14
+ // the run terminal based on the signal regardless of how the program returned.
15
+ /** Thrown by WorkflowHost hooks once the run's AbortSignal has fired, so the program unwinds. A plain
16
+ * Error subclass (no AppError/model coupling) carrying the machine-readable reason. */
17
+ export class RunAbortedError extends Error {
18
+ reason;
19
+ constructor(reason) {
20
+ super(`Run aborted: ${reason}`);
21
+ this.reason = reason;
22
+ this.name = "RunAbortedError";
23
+ }
24
+ }
25
+ /** The reason an aborted signal carries (set via `controller.abort(new RunAbortedError(reason))`), or
26
+ * null when the signal isn't aborted / wasn't aborted with a RunAbortedError. */
27
+ export function abortReason(signal) {
28
+ const r = signal.reason;
29
+ return r instanceof RunAbortedError ? r.reason : null;
30
+ }
31
+ /** Throw if the signal has already aborted — the guard every WorkflowHost hook calls at entry. Re-uses
32
+ * the signal's own RunAbortedError when present, so the reason propagates verbatim. */
33
+ export function throwIfAborted(signal) {
34
+ if (signal?.aborted === true) {
35
+ const r = signal.reason;
36
+ throw r instanceof RunAbortedError ? r : new RunAbortedError("cancelled");
37
+ }
38
+ }
@@ -0,0 +1,24 @@
1
+ import type { RunEvent, RunEventBody, RedisPublisher } from "./agent/events.js";
2
+ export interface RunEventEmitterOptions {
3
+ runId: string;
4
+ publisher: RedisPublisher;
5
+ /** The durable store's max cursor at claim (0 ⇒ fresh run). Restart resumes in the next block. */
6
+ resumeAfterCursor?: number;
7
+ /** Injected clock for deterministic tests. Defaults to Date.now. */
8
+ now?: () => number;
9
+ }
10
+ export declare class WorkerRunEventEmitter {
11
+ private readonly runId;
12
+ private readonly publisher;
13
+ private readonly now;
14
+ private turn;
15
+ private seq;
16
+ constructor(opts: RunEventEmitterOptions);
17
+ /** Stamp + publish a run-level or agent frame. Agent frames pass their turnId. */
18
+ emit(body: RunEventBody, turnId?: string): RunEvent;
19
+ /** Restart resume: jump past the previous session's frames (claim carries the store max). */
20
+ resumeAfter(maxCursor: number): void;
21
+ /** Open a new agent stride block and emit its opening `turn_started` frame (built by the caller,
22
+ * which names the leaf). */
23
+ beginTurn(turnId: string, started: RunEventBody): void;
24
+ }
@@ -0,0 +1,63 @@
1
+ // WorkerRunEventEmitter — the run's SINGLE event envelope counter, engine-parity
2
+ // (boardwalk-labs/boardwalk supervisor semantics):
3
+ //
4
+ // * One shared `{turn, seq}` per run session. Every emit bumps `seq` (1-based);
5
+ // `cursor = makeCursor(turn, seq)` is run-globally monotonic.
6
+ // * `beginTurn(turnId)` opens a new agent stride block: `turn += 1`, `seq = 0`, then emits
7
+ // the block's opening `turn_started` frame.
8
+ // * Run-level frames (run_status / phase / output / program_output) carry `turnId = runId`
9
+ // and ride the CURRENT block — there is no separate "program band", which is what keeps
10
+ // cursors monotonic when program logs interleave with agent turns.
11
+ // * Resume (crash-restart re-runs the program from the top): the claim response carries the
12
+ // store's max cursor; the emitter starts in the NEXT stride block so new frames always
13
+ // order after the previous session's.
14
+ //
15
+ // Frames publish as the stored row shape `{cursor, event}` (JSON) on `run:<id>` — the broker's
16
+ // telemetry endpoint fans out + appends verbatim. Publishing is best-effort (telemetry must
17
+ // never fail a run); the publisher (BrokerEventPublisher) batches.
18
+ import { makeCursor, TURN_CURSOR_STRIDE } from "./agent/events.js";
19
+ export class WorkerRunEventEmitter {
20
+ runId;
21
+ publisher;
22
+ now;
23
+ turn;
24
+ seq;
25
+ constructor(opts) {
26
+ this.runId = opts.runId;
27
+ this.publisher = opts.publisher;
28
+ this.now = opts.now ?? Date.now;
29
+ const max = opts.resumeAfterCursor ?? 0;
30
+ this.turn = max > 0 ? Math.floor(max / TURN_CURSOR_STRIDE) + 1 : 0;
31
+ this.seq = 0;
32
+ }
33
+ /** Stamp + publish a run-level or agent frame. Agent frames pass their turnId. */
34
+ emit(body, turnId) {
35
+ this.seq += 1;
36
+ const event = {
37
+ ...body,
38
+ runId: this.runId,
39
+ turnId: turnId ?? this.runId,
40
+ seq: this.seq,
41
+ t: this.now(),
42
+ };
43
+ const cursor = makeCursor(this.turn, this.seq);
44
+ this.publisher
45
+ .publish(`run:${this.runId}`, JSON.stringify({ cursor, event }))
46
+ .catch(() => undefined); // best-effort; the publisher logs its own failures
47
+ return event;
48
+ }
49
+ /** Restart resume: jump past the previous session's frames (claim carries the store max). */
50
+ resumeAfter(maxCursor) {
51
+ if (maxCursor > 0) {
52
+ this.turn = Math.floor(maxCursor / TURN_CURSOR_STRIDE) + 1;
53
+ this.seq = 0;
54
+ }
55
+ }
56
+ /** Open a new agent stride block and emit its opening `turn_started` frame (built by the caller,
57
+ * which names the leaf). */
58
+ beginTurn(turnId, started) {
59
+ this.turn += 1;
60
+ this.seq = 0;
61
+ this.emit(started, turnId);
62
+ }
63
+ }
@@ -0,0 +1,184 @@
1
+ import type { McpTokenResult } from "@boardwalk-labs/engine/core";
2
+ import type { Run } from "./wire/run.js";
3
+ import { type JournalKind, type JournalLookup, type JournalSeam, type SuspendSignal } from "./suspension.js";
4
+ import type { WebSearchOutput } from "./tools/web_search.js";
5
+ import type { ArtifactCommitInput, ArtifactPresignInput, ArtifactPresignResult, ArtifactSignResult, ArtifactSummary, ArtifactWriteInput, ArtifactWriteResult } from "./tools/artifacts.js";
6
+ import { type InferenceFrame, type InferenceProxyRequest } from "./wire/inference_proxy.js";
7
+ export interface RunnerControlClientConfig {
8
+ /** Base URL of the Runner Control API (BOARDWALK_CONTROL_PLANE_URL). */
9
+ baseUrl: string;
10
+ /** The per-run bearer token (BOARDWALK_RUN_TOKEN). */
11
+ runToken: string;
12
+ /** The run this client (and token) is bound to. */
13
+ runId: string;
14
+ /** Injected fetch (defaults to global fetch). */
15
+ fetchImpl?: typeof fetch;
16
+ }
17
+ /** The pinned program's download reference (the worker fetches + verifies + extracts it). */
18
+ export interface BrokerProgram {
19
+ entry: string;
20
+ digest: string;
21
+ sdkVersion: string;
22
+ downloadUrl: string;
23
+ }
24
+ export interface BrokerVersion {
25
+ manifest: unknown;
26
+ program: BrokerProgram;
27
+ }
28
+ /** The schedule spec the worker sends for `workflows.schedule` (exactly one of cron/rate/at). `at`
29
+ * is a ms epoch or ISO string — a Date is serialized to ISO by the host before it reaches here. */
30
+ export interface BrokerScheduleSpec {
31
+ cron?: string;
32
+ rate?: string;
33
+ at?: string | number;
34
+ timezone?: string;
35
+ idempotencyKey?: string;
36
+ }
37
+ /** A child run's terminal-relevant state, as returned by the `children` create/poll endpoints. */
38
+ export interface BrokerChild {
39
+ childRunId: string;
40
+ status: string;
41
+ output: unknown;
42
+ }
43
+ export declare class RunnerControlClient {
44
+ private readonly cfg;
45
+ private readonly base;
46
+ private readonly fetchImpl;
47
+ constructor(cfg: RunnerControlClientConfig);
48
+ /** Claim the run's lease. Returns the run on success, or null when it isn't claimable (409 —
49
+ * another worker has it, or it isn't pending), which the worker treats as "claim lost". */
50
+ claim(workerId: string, leaseSeconds: number): Promise<{
51
+ run: Run;
52
+ lastEventCursor: number;
53
+ lastJournalSeq: number;
54
+ } | null>;
55
+ /** Heartbeat: extend our lease so a long run isn't reclaimed mid-flight. Returns the new
56
+ * `leaseUntil`, or null when the lease was lost (409 — another worker reclaimed the run), which
57
+ * the worker treats as "stop". */
58
+ renewLease(workerId: string, leaseSeconds: number): Promise<number | null>;
59
+ /** Mark the run terminal. `workerId` lets the broker reject a finalize from a DISPLACED worker (one
60
+ * whose lease expired and whose run was reclaimed + re-dispatched to a new owner), so a
61
+ * hung/partitioned worker that later recovers can't clobber the live run or revive a terminal one. */
62
+ finalize(status: "completed" | "failed", output: unknown, workerId: string): Promise<void>;
63
+ /** Look up a durable-seam journal entry by its seq (docs/SUSPENSION.md), or null on a replay miss
64
+ * (404). The broker joins a parked agent leaf's answers into the result server-side. */
65
+ journalGet(seq: number): Promise<JournalLookup | null>;
66
+ /** Record a RESOLVED seam result (idempotent on the run + seq server-side; a resolved entry is
67
+ * immutable). The broker writes the memoized value the next replay returns. */
68
+ journalPut(entry: {
69
+ seq: number;
70
+ kind: JournalKind;
71
+ fingerprint: string;
72
+ label: string;
73
+ result: unknown;
74
+ }): Promise<void>;
75
+ /** Persist a durable SUSPENSION: the broker records the wake condition (a pending/suspended journal
76
+ * entry + a human-input request row for HITL, or the wake time for a long sleep), flips the run to
77
+ * its suspended status, and releases the lease — transactionally. No finalize; a wake re-dispatches. */
78
+ suspend(signal: SuspendSignal, workerId: string): Promise<void>;
79
+ /** The {@link JournalSeam} the worker host reads/writes — a thin adapter over the broker methods. */
80
+ journalSeam(): JournalSeam;
81
+ /** Fetch the run's pinned manifest + program source, or null when the version is missing (404). */
82
+ getVersion(): Promise<BrokerVersion | null>;
83
+ /** Book a runtime-seconds DELTA (the worker's RuntimeFlusher → broker). `identifier` makes a
84
+ * retried/duplicate flush idempotent; distinct per-flush ids sum into the run's runtime total. */
85
+ reportUsage(runtimeSeconds: number, identifier: string): Promise<void>;
86
+ /** Report a token-usage delta for incremental in-run metering (the usage flusher → broker). The
87
+ * broker gates on the run's per-connection `billed_by_boardwalk` server-side + meters to Stripe;
88
+ * `identifier` makes a retried/duplicate flush idempotent. Satisfies {@link TokenUsageReporter}. */
89
+ meterTokens(input: {
90
+ inputTokens: number;
91
+ outputTokens: number;
92
+ model?: string;
93
+ identifier: string;
94
+ /** Cache-served input tokens — display-only annotation (omitted when zero/unknown). */
95
+ cachedReadTokens?: number;
96
+ cachedWriteTokens?: number;
97
+ }): Promise<void>;
98
+ /** Check whether the run's org is still funded (the CreditWatcher → broker). The broker reads the
99
+ * live Stripe balance server-side; `false` means out of credit (the watcher then aborts the run). */
100
+ checkCredit(): Promise<boolean>;
101
+ /** Check whether the run has been asked to cancel (the CancelWatcher → broker). `true` once the user
102
+ * cancelled the run (the broker flipped it to `cancelling`/`cancelled`); the watcher then aborts the
103
+ * run. Brokered because the runner holds no DB/Redis — this replaces the unreachable Redis channel. */
104
+ checkCancelled(): Promise<boolean>;
105
+ /** Mint a presigned GET URL to restore this workflow's last `/workspace` snapshot (workspace
106
+ * persistence, §5). `null` when the run isn't eligible (not opted-in, or self-hosted). */
107
+ workspaceHydrateUrl(): Promise<string | null>;
108
+ /** Mint a presigned PUT URL to snapshot this workflow's `/workspace` (the worker uploads the tarball
109
+ * straight to S3). `null` when the run isn't eligible. `sizeBytes` is the archive's on-disk size
110
+ * (the worker tars BEFORE requesting the URL) — the broker records it for the org storage counter +
111
+ * daily meter; the snapshot overwrites one per-workflow key, so it's the workflow's full footprint. */
112
+ workspacePersistUrl(sizeBytes: number): Promise<{
113
+ url: string;
114
+ contentType: string;
115
+ } | null>;
116
+ /** Download bytes from a presigned S3 URL (workspace hydrate). `null` on 404 (no snapshot yet —
117
+ * e.g. the workflow's first run); throws on any other non-2xx. Goes straight to S3, not the broker. */
118
+ downloadBytes(url: string): Promise<Uint8Array | null>;
119
+ /** Request an OIDC run id-token for `audience` (§OIDC). The broker mints an asymmetric,
120
+ * third-party-verifiable token (gated server-side on `permissions.id_token: "write"`) — used to
121
+ * federate into the org's OWN cloud (AWS/GCP). DIFFERENT from this client's run token. */
122
+ requestOidcToken(audience: string): Promise<{
123
+ token: string;
124
+ expiresIn: number;
125
+ }>;
126
+ /** Publish a batch of live agent-event frames (the SSE live-tail source) — the broker publishes
127
+ * them to the run's Redis channel server-side, so the runner holds no Redis credential. */
128
+ publishTelemetry(frames: string[]): Promise<void>;
129
+ /** Store a run artifact through the broker (which holds the S3 credential + neutralizes the served
130
+ * content type server-side). Returns the catalog id + a signed download URL. */
131
+ writeArtifact(input: ArtifactWriteInput): Promise<ArtifactWriteResult>;
132
+ /** Phase 1 of the LARGE-artifact path (docs/RUNNER_BROKER.md §7 step 4): presign an S3 PUT. The
133
+ * broker derives the S3 key + neutralizes/pins the served content type; it returns the upload URL +
134
+ * required headers + the `s3Key` to echo back at commit. No catalog row exists yet. */
135
+ presignArtifact(input: ArtifactPresignInput): Promise<ArtifactPresignResult>;
136
+ /** Upload bytes to a presigned S3 URL (the large-artifact path). The `headers` come from the
137
+ * presign response and MUST be sent verbatim — the content type is pinned into the signature, so
138
+ * S3 rejects a mismatch. This call goes straight to S3, not the broker. */
139
+ uploadBytes(url: string, headers: Record<string, string>, body: Uint8Array): Promise<void>;
140
+ /** Phase 2 of the LARGE-artifact path: register the catalog row AFTER the bytes have landed in S3
141
+ * (called only on a successful {@link uploadBytes}, so a failed upload leaves no dangling row). The
142
+ * broker re-validates the run prefix + re-neutralizes the content type, then returns the catalog id
143
+ * + a signed download URL. */
144
+ commitArtifact(input: ArtifactCommitInput): Promise<ArtifactWriteResult>;
145
+ /** List the artifacts this run has produced. */
146
+ listArtifacts(): Promise<ArtifactSummary[]>;
147
+ /** Mint a fresh signed download URL for one of this run's artifacts. */
148
+ signArtifactUrl(artifactId: string, ttlSeconds: number): Promise<ArtifactSignResult>;
149
+ /** Resolve an org secret the run's manifest allows (the program's `secrets.get`). The broker
150
+ * enforces the allowlist + returns the value; a forbidden/missing secret surfaces as a throw. */
151
+ resolveSecret(name: string): Promise<string>;
152
+ /** Broker a short-lived OAuth bearer for a hosted MCP server (the engine's `mcpToken` hook, called
153
+ * reactively after a 401). The broker vends from the org's connection vault and re-checks egress.
154
+ * A 403 (no active connection / non-allowlisted host) degrades to `{ accessToken: null, hint }` so
155
+ * the engine surfaces a clean failure instead of a thrown 500 mid-run; the token is never logged. */
156
+ mcpToken(serverUrl: string, invalidateToken?: string): Promise<McpTokenResult>;
157
+ /** Proxy a web_search through the broker (which holds the Tavily key) — the runner sends the
158
+ * query, the broker calls Tavily and returns the results. */
159
+ webSearch(input: unknown): Promise<WebSearchOutput>;
160
+ /** Create (or idempotently re-attach to) a child run for `workflows.call`. */
161
+ startChild(slug: string, input: unknown): Promise<BrokerChild>;
162
+ /** Provision a durable schedule for `workflows.schedule`; returns the new schedule's id. */
163
+ scheduleWorkflow(slug: string, input: unknown, spec: BrokerScheduleSpec): Promise<string>;
164
+ /** Poll a child run's status/output, or null when it isn't this run's child (404). */
165
+ getChild(childRunId: string): Promise<{
166
+ id: string;
167
+ status: string;
168
+ output: unknown;
169
+ } | null>;
170
+ /**
171
+ * Proxy one model turn through the broker (docs/RUNNER_BROKER.md §4 — Inference). POSTs the
172
+ * neutral conversation; the broker resolves the REAL model server-side (the runner holds no model
173
+ * creds), invokes the matching engine adapter, and relays the model's stream back as NDJSON
174
+ * `InferenceFrame`s (delta / result / error). Yields each frame; the engine-backed leaf surfaces
175
+ * deltas via `providerIo.onDelta`, takes the terminal `result` as the turn, and throws on `error`.
176
+ *
177
+ * Backs {@link InferenceProxyTransport} (inference_transport.ts) — the model swap is invisible to
178
+ * the engine loop, which keeps the runner provider-agnostic (the broker owns model invocation). A
179
+ * non-200 (a failure BEFORE the stream began) throws the broker's already-classified message.
180
+ */
181
+ streamInference(req: InferenceProxyRequest): AsyncGenerator<InferenceFrame, void, undefined>;
182
+ private url;
183
+ private headers;
184
+ }