@foldrun/core 2.4.0 → 2.6.0
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/src/agent-activity.d.ts +5 -0
- package/dist/src/agent-activity.js +31 -0
- package/dist/src/agent-import.js +2 -2
- package/dist/src/agent-tools.js +2 -2
- package/dist/src/agents-md.d.ts +5 -1
- package/dist/src/agents-md.js +42 -18
- package/dist/src/alerts.d.ts +60 -0
- package/dist/src/alerts.js +161 -0
- package/dist/src/browser-pod.js +4 -0
- package/dist/src/capture.d.ts +23 -0
- package/dist/src/capture.js +80 -0
- package/dist/src/compare.d.ts +57 -0
- package/dist/src/compare.js +116 -0
- package/dist/src/completions.js +26 -3
- package/dist/src/deploy.d.ts +36 -1
- package/dist/src/deploy.js +237 -13
- package/dist/src/egress.d.ts +16 -1
- package/dist/src/evals.d.ts +27 -2
- package/dist/src/evals.js +62 -19
- package/dist/src/flow-lint.d.ts +14 -0
- package/dist/src/flow-lint.js +35 -0
- package/dist/src/flow-patterns.js +29 -14
- package/dist/src/frontmatter-fields.d.ts +27 -0
- package/dist/src/frontmatter-fields.js +60 -3
- package/dist/src/frontmatter-guard.d.ts +19 -0
- package/dist/src/frontmatter-guard.js +67 -0
- package/dist/src/frontmatter-schema.d.ts +2 -2
- package/dist/src/frontmatter-schema.js +33 -2
- package/dist/src/frontmatter-text.d.ts +31 -0
- package/dist/src/frontmatter-text.js +102 -0
- package/dist/src/history.d.ts +4 -0
- package/dist/src/history.js +15 -0
- package/dist/src/hooks.js +1 -1
- package/dist/src/insights.d.ts +30 -0
- package/dist/src/insights.js +152 -0
- package/dist/src/issues.d.ts +140 -0
- package/dist/src/issues.js +302 -0
- package/dist/src/judge-verdict.d.ts +19 -0
- package/dist/src/judge-verdict.js +54 -0
- package/dist/src/library.js +1 -1
- package/dist/src/limits.d.ts +8 -0
- package/dist/src/limits.js +36 -5
- package/dist/src/linkable.js +1 -1
- package/dist/src/matter.d.ts +42 -0
- package/dist/src/matter.js +132 -0
- package/dist/src/model-credential.d.ts +14 -0
- package/dist/src/model-credential.js +40 -0
- package/dist/src/network.d.ts +12 -1
- package/dist/src/network.js +35 -8
- package/dist/src/notify.d.ts +16 -0
- package/dist/src/notify.js +17 -7
- package/dist/src/okf.js +1 -1
- package/dist/src/online-checks.d.ts +76 -0
- package/dist/src/online-checks.js +432 -0
- package/dist/src/operator.d.ts +277 -0
- package/dist/src/operator.js +176 -2
- package/dist/src/otel-config.d.ts +18 -0
- package/dist/src/otel-config.js +69 -0
- package/dist/src/otel.d.ts +38 -0
- package/dist/src/otel.js +85 -0
- package/dist/src/outcome.d.ts +40 -0
- package/dist/src/outcome.js +77 -0
- package/dist/src/package.js +9 -2
- package/dist/src/platform.d.ts +1 -1
- package/dist/src/prompt-layers.d.ts +30 -0
- package/dist/src/prompt-layers.js +77 -0
- package/dist/src/provider-health.js +2 -2
- package/dist/src/providers.d.ts +5 -0
- package/dist/src/providers.js +2 -2
- package/dist/src/run-container.d.ts +25 -2
- package/dist/src/run-container.js +61 -6
- package/dist/src/runner.d.ts +53 -2
- package/dist/src/runner.js +471 -102
- package/dist/src/runs-filter.d.ts +48 -0
- package/dist/src/runs-filter.js +73 -0
- package/dist/src/scan.d.ts +30 -1
- package/dist/src/scan.js +145 -14
- package/dist/src/starter.js +27 -2
- package/dist/src/step-exec.d.ts +39 -3
- package/dist/src/step-exec.js +118 -15
- package/dist/src/store.d.ts +144 -3
- package/dist/src/store.js +150 -7
- package/dist/src/tokens.d.ts +38 -0
- package/dist/src/tokens.js +57 -0
- package/dist/src/tool-names.js +1 -1
- package/dist/src/tool-programs.js +1 -1
- package/dist/src/trace-tree.d.ts +40 -0
- package/dist/src/trace-tree.js +156 -0
- package/dist/src/translator.d.ts +8 -0
- package/dist/src/translator.js +7 -2
- package/dist/src/trigger-log.d.ts +1 -1
- package/dist/src/workspace-check.d.ts +18 -0
- package/dist/src/workspace-check.js +34 -0
- package/package.json +2 -2
- package/src/agent-activity.ts +32 -0
- package/src/agent-import.ts +2 -2
- package/src/agent-tools.ts +2 -2
- package/src/agents-md.ts +39 -14
- package/src/alerts.ts +190 -0
- package/src/browser-pod.ts +3 -0
- package/src/capture.ts +88 -0
- package/src/compare.ts +146 -0
- package/src/completions.ts +27 -3
- package/src/deploy.ts +238 -12
- package/src/egress.ts +12 -2
- package/src/evals.ts +64 -19
- package/src/flow-lint.ts +36 -0
- package/src/flow-patterns.ts +26 -13
- package/src/frontmatter-fields.ts +83 -3
- package/src/frontmatter-guard.ts +70 -0
- package/src/frontmatter-schema.ts +33 -4
- package/src/frontmatter-text.ts +109 -0
- package/src/history.ts +13 -0
- package/src/hooks.ts +1 -1
- package/src/insights.ts +174 -0
- package/src/issues.ts +396 -0
- package/src/judge-verdict.ts +52 -0
- package/src/library.ts +1 -1
- package/src/limits.ts +38 -5
- package/src/linkable.ts +1 -1
- package/src/matter.ts +145 -0
- package/src/model-credential.ts +45 -0
- package/src/network.ts +35 -7
- package/src/notify.ts +22 -7
- package/src/okf.ts +1 -1
- package/src/online-checks.ts +450 -0
- package/src/operator.ts +213 -3
- package/src/otel-config.ts +67 -0
- package/src/otel.ts +100 -0
- package/src/outcome.ts +90 -0
- package/src/package.ts +8 -2
- package/src/platform.ts +1 -1
- package/src/prompt-layers.ts +90 -0
- package/src/provider-health.ts +2 -2
- package/src/providers.ts +7 -2
- package/src/run-container.ts +77 -8
- package/src/runner.ts +477 -79
- package/src/runs-filter.ts +88 -0
- package/src/scan.ts +153 -14
- package/src/starter.ts +27 -2
- package/src/step-exec.ts +168 -17
- package/src/store.ts +268 -9
- package/src/tokens.ts +68 -0
- package/src/tool-names.ts +1 -1
- package/src/tool-programs.ts +1 -1
- package/src/trace-tree.ts +187 -0
- package/src/translator.ts +13 -2
- package/src/trigger-log.ts +1 -0
- package/src/workspace-check.ts +41 -0
package/src/provider-health.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { accountModelBlock } from "./model-credential.ts";
|
|
22
22
|
import fs from "node:fs";
|
|
23
23
|
import path from "node:path";
|
|
24
|
-
import
|
|
24
|
+
import { configMatter } from "./matter.ts";
|
|
25
25
|
import { getSecret } from "./secrets.ts";
|
|
26
26
|
import { noteSecretUse, healthKey } from "./secret-health.ts";
|
|
27
27
|
import { accountDir, workspaceDir, listWorkspaces, listAgents, parseProvider, type ProviderSpec } from "./store.ts";
|
|
@@ -205,7 +205,7 @@ function cheapestModel(spec: ProviderSpec): string {
|
|
|
205
205
|
|
|
206
206
|
function frontmatterOf(file: string): Record<string, unknown> {
|
|
207
207
|
try {
|
|
208
|
-
return (
|
|
208
|
+
return (configMatter(fs.readFileSync(file, "utf8")).data ?? {}) as Record<string, unknown>;
|
|
209
209
|
} catch {
|
|
210
210
|
return {};
|
|
211
211
|
}
|
package/src/providers.ts
CHANGED
|
@@ -54,6 +54,11 @@ export interface ProviderPreset {
|
|
|
54
54
|
* Off means the translator drops thinking rather than send a parameter
|
|
55
55
|
* the endpoint would reject. */
|
|
56
56
|
reasoningEffort?: boolean;
|
|
57
|
+
/** Whether the endpoint takes `prompt_cache_key` — a hint that requests
|
|
58
|
+
* with the same key share a prompt prefix, so its cache can be routed
|
|
59
|
+
* to. Only set where the parameter is documented; an endpoint that does
|
|
60
|
+
* not know it may refuse the request. */
|
|
61
|
+
promptCacheKey?: boolean;
|
|
57
62
|
/** One line a person should read before relying on it. */
|
|
58
63
|
note?: string;
|
|
59
64
|
/** A tool loop was driven through this endpoint from this runtime. */
|
|
@@ -427,7 +432,7 @@ export const PROVIDERS: readonly ProviderPreset[] = [
|
|
|
427
432
|
|
|
428
433
|
// ------------------------------------------- Chat-Completions, translated
|
|
429
434
|
{ name: "openai", title: "OpenAI", format: "openai", baseUrl: "https://api.openai.com/v1", auth: "bearer", verified: true,
|
|
430
|
-
maxTokensParam: "max_completion_tokens", reasoningEffort: true,
|
|
435
|
+
maxTokensParam: "max_completion_tokens", reasoningEffort: true, promptCacheKey: true,
|
|
431
436
|
note: "Reached over Chat Completions, which OpenAI keeps supporting; the Responses API is not spoken here, so a reasoning model's reasoning does not carry across tool calls." , search: "openai" },
|
|
432
437
|
{ name: "gemini", title: "Google Gemini", format: "openai", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", auth: "bearer",
|
|
433
438
|
note: "Google's OpenAI-compatible route. Unknown parameters are ignored silently; reasoning cannot be switched off on the newest models." },
|
|
@@ -435,7 +440,7 @@ export const PROVIDERS: readonly ProviderPreset[] = [
|
|
|
435
440
|
maxTokensParam: "max_completion_tokens", reasoningEffort: true },
|
|
436
441
|
{ name: "groq", title: "Groq", format: "openai", baseUrl: "https://api.groq.com/openai/v1", auth: "bearer",
|
|
437
442
|
maxTokensParam: "max_completion_tokens", reasoningEffort: true },
|
|
438
|
-
{ name: "mistral", title: "Mistral", format: "openai", baseUrl: "https://api.mistral.ai/v1", auth: "bearer" },
|
|
443
|
+
{ name: "mistral", title: "Mistral", format: "openai", baseUrl: "https://api.mistral.ai/v1", auth: "bearer", promptCacheKey: true },
|
|
439
444
|
{ name: "together", title: "Together AI", format: "openai", baseUrl: "https://api.together.ai/v1", auth: "bearer" },
|
|
440
445
|
{ name: "cerebras", title: "Cerebras", format: "openai", baseUrl: "https://api.cerebras.ai/v1", auth: "bearer",
|
|
441
446
|
maxTokensParam: "max_completion_tokens", reasoningEffort: true },
|
package/src/run-container.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
// The runner image bundles @foldrun/core itself, so the driver runs the same
|
|
19
19
|
// executeStep the server would — one implementation, two homes.
|
|
20
20
|
|
|
21
|
+
import type { PeerInfo } from "./operator.ts";
|
|
21
22
|
import { isHookRecord, type HookRecord } from "./hooks.ts";
|
|
22
23
|
import fs from "node:fs";
|
|
23
24
|
import os from "node:os";
|
|
@@ -25,9 +26,9 @@ import path from "node:path";
|
|
|
25
26
|
import crypto from "node:crypto";
|
|
26
27
|
import { spawn, spawnSync } from "node:child_process";
|
|
27
28
|
import type { McpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
|
28
|
-
import { isPlatformPath, type ApiSpec, type Effort } from "./store.ts";
|
|
29
|
+
import { CAPTURE_CAP, isPlatformPath, type ApiSpec, type Effort, type ModelCall } from "./store.ts";
|
|
29
30
|
import { divertedSummary, isDivertedPath, overlayTestWrites } from "./test-mode.ts";
|
|
30
|
-
import type { EventExtra, ExecUsage } from "./step-exec.ts";
|
|
31
|
+
import type { CallIo, EventExtra, ExecUsage } from "./step-exec.ts";
|
|
31
32
|
import type { TokenPrice } from "./catalog.ts";
|
|
32
33
|
import { isFileValue, fileContent } from "./secrets.ts";
|
|
33
34
|
import { safeTenantSegment, systemInstallSh, SYSTEM_FROM_INPUT_SH, INSTALL_SOCKET, type RuntimeSpec } from "./runtime.ts";
|
|
@@ -72,11 +73,16 @@ export interface ContainerStepInput {
|
|
|
72
73
|
budgetNote?: string;
|
|
73
74
|
price?: TokenPrice | null;
|
|
74
75
|
verify?: string;
|
|
76
|
+
/** The model `verify: judge:` grades with (the workspace's `judge:`). */
|
|
77
|
+
judgeModel?: string;
|
|
78
|
+
judgeEffort?: string;
|
|
75
79
|
/** `output: json` — checked inside, where the reply is. */
|
|
76
80
|
output?: "json";
|
|
77
81
|
/** `schema:` and `max_turns:`, resolved host-side — see ExecOptions. */
|
|
78
82
|
schema?: Record<string, unknown> | boolean;
|
|
79
83
|
maxTurns?: number;
|
|
84
|
+
/** `capture:` resolved host-side (FOL-54 step 4) — see ExecOptions. */
|
|
85
|
+
capture?: "metadata" | "full";
|
|
80
86
|
/** `limits:` resolved host-side, and the SDK-name → foldrun-name map the
|
|
81
87
|
* count reads (limits.ts) — enforced in the pod by the same hook. */
|
|
82
88
|
limits?: Record<string, number>;
|
|
@@ -93,6 +99,10 @@ export interface ContainerStepInput {
|
|
|
93
99
|
desks?: RunDigest[];
|
|
94
100
|
/** tools: [ask] — ask_person, and how long it may wait for an answer. */
|
|
95
101
|
ask?: { timeoutSec: number };
|
|
102
|
+
/** tools: [peers] — this step's agent and the other steps of its
|
|
103
|
+
* parallel group, gathered host-side at launch. The driver rebuilds the
|
|
104
|
+
* colleagues' tools in here over the lease's /peers door. */
|
|
105
|
+
peers?: { self: string; siblings: PeerInfo[] };
|
|
96
106
|
/** A Chat-Completions provider: the driver starts the runtime's translator
|
|
97
107
|
* on loopback and points the SDK at it. Null or absent: the env's
|
|
98
108
|
* ANTHROPIC_BASE_URL is spoken to directly. */
|
|
@@ -549,7 +559,8 @@ export function runtimeCacheMount(
|
|
|
549
559
|
|
|
550
560
|
// ---------- the runner image ----------
|
|
551
561
|
|
|
552
|
-
|
|
562
|
+
/** The runner container's entrypoint, as JS text: written into the image as driver.mjs, so it must be plain JS — a TypeScript cast here broke every step on v2026.10.21.5 (tests/run-container.test.ts checks it). */
|
|
563
|
+
export const DRIVER = `// The runner container's entrypoint. Reads one step, executes it with the
|
|
553
564
|
// same core the server uses, speaks JSONL on stdout, exits.
|
|
554
565
|
import fs from "node:fs";
|
|
555
566
|
const input = JSON.parse(fs.readFileSync("/opt/runner/job/input.json", "utf8"));
|
|
@@ -614,7 +625,7 @@ try {
|
|
|
614
625
|
const { buildScriptTools } = await import("@foldrun/core/script-tools");
|
|
615
626
|
const { buildConsultTools } = await import("@foldrun/core/agent-tools");
|
|
616
627
|
const { buildSearchTools, buildHistoryTools, buildDeskTools } = await import("@foldrun/core/context-tools");
|
|
617
|
-
const { httpChannel, buildAskTool, inboxReader } = await import("@foldrun/core/operator");
|
|
628
|
+
const { httpChannel, buildAskTool, buildPeerTools, inboxReader } = await import("@foldrun/core/operator");
|
|
618
629
|
const { startTranslator } = await import("@foldrun/core/translator");
|
|
619
630
|
const { prepareRuntime } = await import("@foldrun/core/runtime");
|
|
620
631
|
const { materializeFileSecrets } = await import("@foldrun/core/secret-files");
|
|
@@ -678,11 +689,18 @@ try {
|
|
|
678
689
|
// A long result is kept in a file only when the agent can read it back.
|
|
679
690
|
// (tool-output.ts canReadBack, inlined: the driver imports core by subpath.)
|
|
680
691
|
const keepIn = { dir: agentDir, readable: () => (input.allowed ?? []).some((t) => t === "Read" || t === "Grep") };
|
|
681
|
-
|
|
692
|
+
// A declared secret named like a model variable crosses as
|
|
693
|
+
// FOLDRUN_DECLARED_<NAME> (runner.ts, FOL-19): the model keeps its own
|
|
694
|
+
// settings, and the agent's API and script tools and verify: get the value
|
|
695
|
+
// back under the name it declared. Built here, after the runtime and any
|
|
696
|
+
// mid-step install have added their paths to env.
|
|
697
|
+
const toolEnv = { ...env };
|
|
698
|
+
for (const [k, v] of Object.entries(env)) if (k.startsWith("FOLDRUN_DECLARED_")) toolEnv[k.slice("FOLDRUN_DECLARED_".length)] = v;
|
|
699
|
+
const api = buildApiTools("", input.apis, undefined, { env: toolEnv, missing: [] }, keepIn);
|
|
682
700
|
const script = buildScriptTools(
|
|
683
701
|
agentDir,
|
|
684
702
|
input.scripts,
|
|
685
|
-
|
|
703
|
+
toolEnv,
|
|
686
704
|
"/library/scripts",
|
|
687
705
|
runtime.interpreters,
|
|
688
706
|
null,
|
|
@@ -705,6 +723,7 @@ try {
|
|
|
705
723
|
// ask_person when tools: [ask], and the run's inbox after every tool call.
|
|
706
724
|
const channel = httpChannel(env.FOLDRUN_EGRESS);
|
|
707
725
|
const ask = input.ask ? buildAskTool({ channel, timeoutSec: input.ask.timeoutSec, emit }) : { server: null };
|
|
726
|
+
const peers = input.peers ? buildPeerTools({ channel, self: input.peers.self, siblings: input.peers.siblings, emit }) : { server: null };
|
|
708
727
|
const inbox = channel ? inboxReader(channel, emit) : undefined;
|
|
709
728
|
|
|
710
729
|
mark("tools");
|
|
@@ -726,6 +745,7 @@ try {
|
|
|
726
745
|
...(history.server ? { foldrun_history: history.server } : {}),
|
|
727
746
|
...(desks.server ? { foldrun_desks: desks.server } : {}),
|
|
728
747
|
...(ask.server ? { foldrun_ask: ask.server } : {}),
|
|
748
|
+
...(peers.server ? { foldrun_peers: peers.server } : {}),
|
|
729
749
|
...(install.server ? { foldrun_install: install.server } : {}),
|
|
730
750
|
...input.mcpServers,
|
|
731
751
|
},
|
|
@@ -737,10 +757,13 @@ try {
|
|
|
737
757
|
budgetNote: input.budgetNote,
|
|
738
758
|
price: input.price,
|
|
739
759
|
verify: input.verify,
|
|
740
|
-
verifyEnv:
|
|
760
|
+
verifyEnv: toolEnv,
|
|
761
|
+
...(typeof input.judgeModel === "string" ? { judgeModel: input.judgeModel } : {}),
|
|
762
|
+
...(typeof input.judgeEffort === "string" ? { judgeEffort: input.judgeEffort } : {}),
|
|
741
763
|
output: input.output,
|
|
742
764
|
schema: input.schema,
|
|
743
765
|
maxTurns: input.maxTurns,
|
|
766
|
+
...(input.capture === "metadata" || input.capture === "full" ? { capture: input.capture } : {}),
|
|
744
767
|
...(input.limits && Object.keys(input.limits).length ? { limits: input.limits, toolOwners: input.toolOwners ?? {} } : {}),
|
|
745
768
|
...(input.hookNames?.length ? { hookNames: input.hookNames, hookBase: input.hookBase ?? {} } : {}),
|
|
746
769
|
// Slim browsing: the platform put this step on the slim image to browse
|
|
@@ -1190,9 +1213,47 @@ export function buildFailureSummary(log: string, opts: { tail?: number; maxLines
|
|
|
1190
1213
|
|
|
1191
1214
|
// ---------- running one step ----------
|
|
1192
1215
|
|
|
1216
|
+
const num = (v: unknown) => (typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0);
|
|
1217
|
+
|
|
1218
|
+
/** A tool call's content from the sandbox, as far as it is well-formed and
|
|
1219
|
+
* within the cap; anything else is dropped (FOL-54 step 4). */
|
|
1220
|
+
function callIoOf(v: unknown): CallIo | null {
|
|
1221
|
+
if (!v || typeof v !== "object") return null;
|
|
1222
|
+
const o = v as Record<string, unknown>;
|
|
1223
|
+
// The cap plus the slack the runner masks inside before it cuts.
|
|
1224
|
+
const text = (x: unknown) => (typeof x === "string" ? x.slice(0, CAPTURE_CAP + 4096) : undefined);
|
|
1225
|
+
const io: CallIo = {
|
|
1226
|
+
...(text(o.input) !== undefined ? { input: text(o.input) } : {}),
|
|
1227
|
+
...(text(o.output) !== undefined ? { output: text(o.output) } : {}),
|
|
1228
|
+
...(typeof o.inputChars === "number" ? { inputChars: num(o.inputChars) } : {}),
|
|
1229
|
+
...(typeof o.outputChars === "number" ? { outputChars: num(o.outputChars) } : {}),
|
|
1230
|
+
...(o.truncated === true ? { truncated: true } : {}),
|
|
1231
|
+
};
|
|
1232
|
+
return io.input !== undefined || io.output !== undefined ? io : null;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/** One model call from the sandbox, well-formed or dropped. */
|
|
1236
|
+
function modelCallOf(v: unknown): ModelCall | null {
|
|
1237
|
+
if (!v || typeof v !== "object") return null;
|
|
1238
|
+
const o = v as Record<string, unknown>;
|
|
1239
|
+
const t = (o.tokens ?? {}) as Record<string, unknown>;
|
|
1240
|
+
if (typeof o.id !== "string" || !o.id || o.id.length > 128 || typeof o.at !== "string" || Number.isNaN(Date.parse(o.at))) return null;
|
|
1241
|
+
return {
|
|
1242
|
+
id: o.id,
|
|
1243
|
+
n: Math.max(1, Math.floor(num(o.n))),
|
|
1244
|
+
at: o.at,
|
|
1245
|
+
ms: num(o.ms),
|
|
1246
|
+
...(typeof o.model === "string" ? { model: o.model.slice(0, 128) } : {}),
|
|
1247
|
+
...(typeof o.stop === "string" ? { stop: o.stop.slice(0, 64) } : {}),
|
|
1248
|
+
tokens: { input: num(t.input), output: num(t.output), cacheRead: num(t.cacheRead), cacheWrite: num(t.cacheWrite) },
|
|
1249
|
+
tools: Math.floor(num(o.tools)),
|
|
1250
|
+
...(typeof o.subagent === "string" && /^[a-z0-9-]{1,64}$/.test(o.subagent) ? { subagent: o.subagent } : {}),
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1193
1254
|
export function parseDriverLine(
|
|
1194
1255
|
line: string,
|
|
1195
|
-
): { e: "event"; type: "text" | "tool" | "info" | "error"; text: string; call?: string; ms?: number; err?: boolean; bytes?: number; operator?: OperatorEvent; subagent?: string; check?: boolean; hook?: HookRecord } | { e: "done" } & ContainerStepOutcome | null {
|
|
1256
|
+
): { e: "event"; type: "text" | "tool" | "info" | "error"; text: string; call?: string; ms?: number; err?: boolean; bytes?: number; operator?: OperatorEvent; subagent?: string; check?: boolean; hook?: HookRecord; io?: CallIo; turn?: ModelCall; inCall?: string; responding?: true } | { e: "done" } & ContainerStepOutcome | null {
|
|
1196
1257
|
const trimmed = line.trim();
|
|
1197
1258
|
if (!trimmed.startsWith("{")) return null;
|
|
1198
1259
|
try {
|
|
@@ -1210,6 +1271,10 @@ export function parseDriverLine(
|
|
|
1210
1271
|
...(typeof parsed.subagent === "string" && /^[a-z0-9-]{1,64}$/.test(parsed.subagent) ? { subagent: parsed.subagent } : {}),
|
|
1211
1272
|
...(parsed.check === true ? { check: true } : {}),
|
|
1212
1273
|
...(isHookRecord(parsed.hook) ? { hook: parsed.hook } : {}),
|
|
1274
|
+
...(callIoOf(parsed.io) ? { io: callIoOf(parsed.io)! } : {}),
|
|
1275
|
+
...(typeof parsed.inCall === "string" && parsed.inCall.length <= 128 ? { inCall: parsed.inCall } : {}),
|
|
1276
|
+
...(modelCallOf(parsed.turn) ? { turn: modelCallOf(parsed.turn)! } : {}),
|
|
1277
|
+
...(parsed.responding === true ? { responding: true as const } : {}),
|
|
1213
1278
|
};
|
|
1214
1279
|
}
|
|
1215
1280
|
if (parsed.e === "done") {
|
|
@@ -1299,6 +1364,10 @@ export interface RunInContainerArgs {
|
|
|
1299
1364
|
* without it, "stop" could only mean "stop after this step", and a
|
|
1300
1365
|
* browser step has fifteen minutes left to spend. */
|
|
1301
1366
|
runId?: string;
|
|
1367
|
+
/** Whether a person has stopped the run, read from the record. A step that
|
|
1368
|
+
* waits for room before its sandbox exists asks this, since there is no
|
|
1369
|
+
* sandbox yet for the stop to destroy. */
|
|
1370
|
+
stopRequested?: () => boolean;
|
|
1302
1371
|
/** The reservation class — which limits this step's sandbox holds. */
|
|
1303
1372
|
size?: "small" | "large" | "heavy";
|
|
1304
1373
|
/** Re-attach to a sandbox a previous driver started, instead of creating
|