@pumped-fn/agent-sdk 1.0.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/index.cjs ADDED
@@ -0,0 +1,1336 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _pumped_fn_lite = require("@pumped-fn/lite");
3
+ let _pumped_fn_lite_extension_suspense = require("@pumped-fn/lite-extension-suspense");
4
+ //#region src/index.ts
5
+ const step = (0, _pumped_fn_lite.tag)({
6
+ label: "agent.step",
7
+ default: {}
8
+ });
9
+ const materialKind = (0, _pumped_fn_lite.tag)({ label: "agent.materialKind" });
10
+ const workers = (0, _pumped_fn_lite.tag)({ label: "agent.workerRegistry" });
11
+ var WorkerRegistry = class {
12
+ flows = /* @__PURE__ */ new Map();
13
+ register(flow, name = flow.name) {
14
+ if (!name) throw new Error("Worker flow must have a name");
15
+ this.flows.set(name, flow);
16
+ return this;
17
+ }
18
+ get(name) {
19
+ const found = this.flows.get(name);
20
+ if (!found) throw new Error(`Worker "${name}" not registered`);
21
+ return found;
22
+ }
23
+ list() {
24
+ return [...this.flows.keys()];
25
+ }
26
+ };
27
+ function workerRegistry(flows = []) {
28
+ const registry = new WorkerRegistry();
29
+ for (const workerFlow of flows) registry.register(workerFlow);
30
+ return registry;
31
+ }
32
+ function formatStepKey(key) {
33
+ return (0, _pumped_fn_lite_extension_suspense.formatSuspenseStepKey)(key);
34
+ }
35
+ const workflowRun = (0, _pumped_fn_lite.tag)({ label: "workflow.run" });
36
+ const workflow = (0, _pumped_fn_lite.tag)({ label: "workflow.runtime" });
37
+ const runtime = (0, _pumped_fn_lite.tag)({ label: "agent.runtime" });
38
+ const abortSignal = (0, _pumped_fn_lite.tag)({ label: "workflow.abortSignal" });
39
+ const activeWorkflowEvent = (0, _pumped_fn_lite.tag)({ label: "workflow.event" });
40
+ async function delegateWorker(ctx, name, input) {
41
+ const registry = registryOf(ctx);
42
+ if (!registry) throw new Error("Worker registry not found");
43
+ const target = registry.get(name);
44
+ return ctx.exec({
45
+ flow: target,
46
+ input
47
+ });
48
+ }
49
+ function workflowExtension(options) {
50
+ const base = createWorkflowExtension({
51
+ name: "workflow",
52
+ options,
53
+ shouldHandle: shouldHandleWorkflowTarget,
54
+ run: (event, next) => runTimer(event.target, event.ctx, next)
55
+ });
56
+ return {
57
+ ...base,
58
+ async wrapExec(next, target, ctx) {
59
+ const wrapExec = base.wrapExec;
60
+ if (!wrapExec) return withRuntimeTag(ctx, workflow, workflowRuntimeOf(ctx, options), next);
61
+ return withRuntimeTag(ctx, workflow, workflowRuntimeOf(ctx, options), () => wrapExec(next, target, ctx));
62
+ }
63
+ };
64
+ }
65
+ function extension(options = {}) {
66
+ return {
67
+ name: "agent-sdk",
68
+ async wrapExec(next, target, ctx) {
69
+ return withRuntimeTag(ctx, runtime, runtimeOf(ctx), async () => {
70
+ if (stepOf(target, ctx).remote !== true) return next();
71
+ if (!options.remoteRunner) throw new Error("Remote step requires remoteRunner");
72
+ return options.remoteRunner.run(execEvent(target, ctx), next);
73
+ });
74
+ }
75
+ };
76
+ }
77
+ function createWorkflowExtension(options) {
78
+ return (0, _pumped_fn_lite_extension_suspense.extension)({
79
+ name: options.name,
80
+ log: options.options.log,
81
+ defaultTaskId: options.options.defaultTaskId,
82
+ defaultRunId: options.options.defaultRunId,
83
+ getKey: (ctx) => nextWorkflowKey(ctx, options.options),
84
+ shouldHandle: options.shouldHandle,
85
+ shouldSuspend: (event) => {
86
+ const config = stepOf(event.target, event.ctx);
87
+ return config.durable === true && config.remote !== true;
88
+ },
89
+ createPendingEntry: (event) => ({
90
+ status: "pending",
91
+ key: event.key,
92
+ targetName: event.targetName,
93
+ input: event.input,
94
+ kind: "durable"
95
+ }),
96
+ run: (event, next) => {
97
+ const previous = event.ctx.data.getTag(activeWorkflowEvent);
98
+ event.ctx.data.setTag(activeWorkflowEvent, event);
99
+ return options.run(event, next).finally(() => {
100
+ if (previous) event.ctx.data.setTag(activeWorkflowEvent, previous);
101
+ else event.ctx.data.deleteTag(activeWorkflowEvent);
102
+ });
103
+ }
104
+ });
105
+ }
106
+ function registryOf(ctx) {
107
+ return ctx.data.seekTag(workers);
108
+ }
109
+ function execEvent(target, ctx) {
110
+ return ctx.data.seekTag(activeWorkflowEvent) ?? {
111
+ target,
112
+ ctx,
113
+ targetName: targetNameOf(target, ctx),
114
+ input: ctx.input
115
+ };
116
+ }
117
+ function nextWorkflowKey(ctx, options) {
118
+ const config = ctx.data.seekTag(workflowRun);
119
+ const foundTaskId = config?.taskId ?? options.defaultTaskId ?? "default-task";
120
+ const foundRunId = config?.runId ?? options.defaultRunId ?? "default-run";
121
+ let counter = ctx.data.seekTag(_pumped_fn_lite_extension_suspense.stepCounter);
122
+ if (!counter) {
123
+ counter = { next: 0 };
124
+ rootContext(ctx).data.setTag(_pumped_fn_lite_extension_suspense.stepCounter, counter);
125
+ }
126
+ return {
127
+ taskId: foundTaskId,
128
+ runId: foundRunId,
129
+ step: counter.next++
130
+ };
131
+ }
132
+ function workflowRuntimeOf(ctx, options) {
133
+ const config = ctx.data.seekTag(workflowRun);
134
+ return {
135
+ taskId: config?.taskId ?? options.defaultTaskId ?? "default-task",
136
+ runId: config?.runId ?? options.defaultRunId ?? "default-run"
137
+ };
138
+ }
139
+ function runtimeOf(ctx) {
140
+ const config = ctx.data.seekTag(workflow);
141
+ if (!config) throw new Error("agent extension requires workflow extension");
142
+ return {
143
+ taskId: config.taskId,
144
+ runId: config.runId,
145
+ delegate: (name, input) => delegateWorker(ctx, name, input)
146
+ };
147
+ }
148
+ function withRuntimeTag(ctx, runtimeTag, value, next) {
149
+ const hadPrevious = ctx.data.hasTag(runtimeTag);
150
+ const previous = ctx.data.getTag(runtimeTag);
151
+ ctx.data.setTag(runtimeTag, value);
152
+ return next().finally(() => {
153
+ if (hadPrevious) ctx.data.setTag(runtimeTag, previous);
154
+ else ctx.data.deleteTag(runtimeTag);
155
+ });
156
+ }
157
+ function shouldHandleWorkflowTarget(target, ctx) {
158
+ const config = stepOf(target, ctx);
159
+ return config.workflow === true || config.durable === true || config.timeoutMs !== void 0;
160
+ }
161
+ function rootContext(ctx) {
162
+ let current = ctx;
163
+ while (current.parent) current = current.parent;
164
+ return current;
165
+ }
166
+ function targetNameOf(target, ctx) {
167
+ const name = ctx.name || target.name;
168
+ if (!name) throw new Error("Agent target must have a name");
169
+ return name;
170
+ }
171
+ function runTimer(target, ctx, next) {
172
+ const timeoutMs = stepOf(target, ctx).timeoutMs;
173
+ if (timeoutMs === void 0) return next();
174
+ const controller = new AbortController();
175
+ let timer;
176
+ return withRuntimeTag(ctx, abortSignal, controller.signal, () => Promise.race([next(), new Promise((_, reject) => {
177
+ timer = setTimeout(() => {
178
+ const error = /* @__PURE__ */ new Error(`Workflow step timed out after ${timeoutMs}ms`);
179
+ controller.abort(error);
180
+ reject(error);
181
+ }, timeoutMs);
182
+ })])).finally(() => {
183
+ if (timer) clearTimeout(timer);
184
+ });
185
+ }
186
+ function stepOf(target, ctx) {
187
+ return {
188
+ ...typeof target === "function" ? {} : step.find(target),
189
+ ...ctx.data.seekTag(step) ?? {}
190
+ };
191
+ }
192
+ const materialPatches = /* @__PURE__ */ new WeakMap();
193
+ var MaterialConflictError = class extends Error {
194
+ expectedRevision;
195
+ currentRevision;
196
+ name = "MaterialConflictError";
197
+ constructor(expectedRevision, currentRevision) {
198
+ super(`Material revision conflict: expected ${expectedRevision}, current ${currentRevision}`);
199
+ this.expectedRevision = expectedRevision;
200
+ this.currentRevision = currentRevision;
201
+ }
202
+ };
203
+ function material(name, options) {
204
+ return (0, _pumped_fn_lite.atom)({
205
+ keepAlive: options.keepAlive ?? true,
206
+ tags: [materialKind(options.kind), ...options.tags ?? []],
207
+ factory: () => ({
208
+ name,
209
+ kind: options.kind,
210
+ revision: 0,
211
+ state: clone(options.initialState)
212
+ })
213
+ });
214
+ }
215
+ async function patchMaterial(ctx, target, ops, options = {}) {
216
+ return queueMaterialPatch(ctx, target, async () => {
217
+ const ctrl = ctx.scope.controller(target);
218
+ if (ctrl.state === "idle") await ctrl.resolve();
219
+ const current = ctrl.get();
220
+ if (current.kind !== "json") throw new Error(`Material "${current.name}" does not accept JSON Patch`);
221
+ if (options.expectedRevision !== void 0 && options.expectedRevision !== current.revision) throw new MaterialConflictError(options.expectedRevision, current.revision);
222
+ ctrl.set({
223
+ ...current,
224
+ revision: current.revision + 1,
225
+ state: applyJsonPatch(current.state, ops)
226
+ });
227
+ return ctrl.get();
228
+ });
229
+ }
230
+ function derivedMaterial(name, source, derive, options) {
231
+ return (0, _pumped_fn_lite.atom)({
232
+ keepAlive: options.keepAlive ?? true,
233
+ deps: { source },
234
+ tags: [materialKind(options.kind), ...options.tags ?? []],
235
+ factory: (_ctx, deps) => ({
236
+ name,
237
+ kind: options.kind,
238
+ revision: deps.source.revision,
239
+ state: derive(deps.source.state)
240
+ })
241
+ });
242
+ }
243
+ function queueMaterialPatch(ctx, target, run) {
244
+ let scopePatches = materialPatches.get(ctx.scope);
245
+ if (!scopePatches) {
246
+ scopePatches = /* @__PURE__ */ new WeakMap();
247
+ materialPatches.set(ctx.scope, scopePatches);
248
+ }
249
+ const current = (scopePatches.get(target) ?? Promise.resolve()).catch(() => void 0).then(run);
250
+ const lock = current.then(() => void 0, () => void 0);
251
+ scopePatches.set(target, lock);
252
+ lock.then(() => {
253
+ if (scopePatches.get(target) === lock) scopePatches.delete(target);
254
+ });
255
+ return current;
256
+ }
257
+ function applyJsonPatch(source, ops) {
258
+ let document = clone(source);
259
+ for (const op of ops) {
260
+ if (op.path === "") {
261
+ if (op.op === "remove") document = null;
262
+ else document = clone(op.value);
263
+ continue;
264
+ }
265
+ const parts = splitPointer(op.path);
266
+ const key = parts.at(-1);
267
+ if (key === void 0) throw new Error("JSON Patch path cannot be empty");
268
+ const parent = findPatchParent(document, parts.slice(0, -1));
269
+ if (op.op === "remove") removeValue(parent, key);
270
+ else setValue(parent, key, clone(op.value), op.op);
271
+ }
272
+ return document;
273
+ }
274
+ function splitPointer(path) {
275
+ if (!path.startsWith("/")) throw new Error(`Invalid JSON Pointer "${path}"`);
276
+ return path.slice(1).split("/").map((part) => part.replace(/~1/g, "/").replace(/~0/g, "~"));
277
+ }
278
+ function findPatchParent(document, parts) {
279
+ let current = document;
280
+ for (const part of parts) {
281
+ if (Array.isArray(current)) {
282
+ current = current[Number(part)];
283
+ continue;
284
+ }
285
+ if (isRecord(current)) {
286
+ current = current[part];
287
+ continue;
288
+ }
289
+ throw new Error(`Cannot traverse JSON Patch path at "${part}"`);
290
+ }
291
+ return current;
292
+ }
293
+ function setValue(parent, key, value, op) {
294
+ if (Array.isArray(parent)) {
295
+ if (key === "-") {
296
+ parent.push(value);
297
+ return;
298
+ }
299
+ const index = Number(key);
300
+ if (op === "add") parent.splice(index, 0, value);
301
+ else parent[index] = value;
302
+ return;
303
+ }
304
+ if (!isRecord(parent)) throw new Error(`Cannot set JSON Patch path "${key}"`);
305
+ parent[key] = value;
306
+ }
307
+ function removeValue(parent, key) {
308
+ if (Array.isArray(parent)) {
309
+ parent.splice(Number(key), 1);
310
+ return;
311
+ }
312
+ if (!isRecord(parent)) throw new Error(`Cannot remove JSON Patch path "${key}"`);
313
+ delete parent[key];
314
+ }
315
+ function isRecord(value) {
316
+ return typeof value === "object" && value !== null && !Array.isArray(value);
317
+ }
318
+ function clone(value) {
319
+ return structuredClone(value);
320
+ }
321
+ var CliWorkerError = class extends Error {
322
+ result;
323
+ name = "CliWorkerError";
324
+ constructor(message, result) {
325
+ super(message);
326
+ this.result = result;
327
+ }
328
+ };
329
+ function cliWorker(options) {
330
+ const config = { kind: options.kind ?? "cli" };
331
+ if (options.timeoutMs !== void 0) config.timeoutMs = options.timeoutMs;
332
+ const tags = [step(config), ...options.tags ?? []];
333
+ const factory = async (ctx) => {
334
+ const input = ctx.input;
335
+ const result = await runCli({
336
+ command: resolveRequiredValue(options.command, input, ctx),
337
+ args: resolveValue(options.args ?? [], input, ctx),
338
+ stdin: resolveValue(options.stdin, input, ctx),
339
+ cwd: resolveValue(options.cwd, input, ctx),
340
+ env: resolveValue(options.env, input, ctx),
341
+ isolate: resolveValue(options.isolate, input, ctx),
342
+ timeoutMs: options.timeoutMs,
343
+ signal: ctx.data.seekTag(abortSignal)
344
+ });
345
+ return options.parseOutput ? options.parseOutput(result, input) : result.stdout.trim();
346
+ };
347
+ const flowOptions = {
348
+ name: options.name,
349
+ tags,
350
+ factory
351
+ };
352
+ return typeof options.parse === "function" ? (0, _pumped_fn_lite.flow)({
353
+ ...flowOptions,
354
+ parse: options.parse
355
+ }) : (0, _pumped_fn_lite.flow)({
356
+ ...flowOptions,
357
+ parse: options.parse ?? (0, _pumped_fn_lite.typed)()
358
+ });
359
+ }
360
+ async function runCli(options) {
361
+ const { execFile } = await import("node:child_process");
362
+ const prepared = await prepareCli(options);
363
+ return new Promise((resolve, reject) => {
364
+ execFile(prepared.command, [...prepared.args], {
365
+ cwd: prepared.cwd,
366
+ env: prepared.env,
367
+ timeout: options.timeoutMs,
368
+ signal: options.signal
369
+ }, async (error, stdout, stderr) => {
370
+ await prepared.cleanup();
371
+ const execError = error;
372
+ const exitCode = typeof execError?.code === "number" ? execError.code : error ? null : 0;
373
+ const signal = execError?.signal ?? null;
374
+ const result = {
375
+ stdout: String(stdout),
376
+ stderr: String(stderr),
377
+ exitCode,
378
+ signal
379
+ };
380
+ if (execError?.killed && options.timeoutMs !== void 0) {
381
+ reject(new CliWorkerError(`CLI command timed out after ${options.timeoutMs}ms`, result));
382
+ return;
383
+ }
384
+ if (execError?.name === "AbortError") {
385
+ reject(new CliWorkerError("CLI command aborted", result));
386
+ return;
387
+ }
388
+ if (error) {
389
+ reject(new CliWorkerError(exitCode === null ? error.message : `CLI command failed with exit code ${exitCode}`, result));
390
+ return;
391
+ }
392
+ resolve(result);
393
+ }).stdin?.end(options.stdin);
394
+ });
395
+ }
396
+ async function prepareCli(options) {
397
+ if (!options.isolate) return {
398
+ command: options.command,
399
+ args: options.args ?? [],
400
+ cwd: options.cwd,
401
+ env: {
402
+ ...process.env,
403
+ ...options.env
404
+ },
405
+ cleanup: async () => void 0
406
+ };
407
+ return prepareIsolatedCli(options, typeof options.isolate === "boolean" ? {} : options.isolate);
408
+ }
409
+ async function prepareIsolatedCli(options, isolate) {
410
+ const { mkdtemp, rm, realpath } = await import("node:fs/promises");
411
+ const { existsSync } = await import("node:fs");
412
+ const { dirname, join, resolve } = await import("node:path");
413
+ const { tmpdir } = await import("node:os");
414
+ const hostCwd = resolve(options.cwd ?? process.cwd());
415
+ const workdir = isolate.workdir ?? "/workspace";
416
+ const tempDirs = [];
417
+ const home = isolate.home ?? await mkdtemp(join(tmpdir(), "pumped-fn-home-"));
418
+ if (!isolate.home) tempDirs.push(home);
419
+ const binds = /* @__PURE__ */ new Map();
420
+ addBind(binds, hostCwd, workdir, isolate.writable === true ? "rw" : "ro");
421
+ addBind(binds, home, "/home/agent", "rw");
422
+ if (isolate.codexHome) addBind(binds, isolate.codexHome, "/codex-home", "rw");
423
+ const commandPath = await commandPathOf(options.command, process.env["PATH"] ?? "", existsSync, realpath);
424
+ const nodePath = await realpath(process.execPath);
425
+ for (const dir of defaultCliDirs(existsSync)) addBind(binds, dir, dir, "ro");
426
+ for (const dir of defaultCliCertDirs(existsSync)) addBind(binds, dir, dir, "ro");
427
+ for (const file of defaultCliFiles(existsSync)) addBind(binds, file, file, "ro");
428
+ if (commandPath) {
429
+ addBind(binds, dirname(commandPath), dirname(commandPath), "ro");
430
+ addBind(binds, dirname(dirname(commandPath)), dirname(dirname(commandPath)), "ro");
431
+ }
432
+ addBind(binds, dirname(nodePath), dirname(nodePath), "ro");
433
+ addBind(binds, dirname(dirname(nodePath)), dirname(dirname(nodePath)), "ro");
434
+ for (const bind of isolate.bind ?? []) addBind(binds, bind.source, bind.target ?? bind.source, bind.mode ?? "ro");
435
+ const env = {
436
+ PATH: isolatedPathEnv(commandPath, nodePath, dirname),
437
+ HOME: "/home/agent",
438
+ TMPDIR: "/tmp",
439
+ ...isolate.codexHome ? { CODEX_HOME: "/codex-home" } : {},
440
+ ...options.env,
441
+ ...isolate.env
442
+ };
443
+ return {
444
+ command: isolate.bwrap ?? "bwrap",
445
+ args: [
446
+ "--die-with-parent",
447
+ "--unshare-all",
448
+ ...isolate.network === true ? ["--share-net"] : [],
449
+ "--proc",
450
+ "/proc",
451
+ "--dev",
452
+ "/dev",
453
+ "--tmpfs",
454
+ "/tmp",
455
+ "--dir",
456
+ "/etc",
457
+ "--dir",
458
+ "/home",
459
+ ...Object.entries(env).flatMap(([key, value]) => value === void 0 ? [] : [
460
+ "--setenv",
461
+ key,
462
+ value
463
+ ]),
464
+ ...[...binds.values()].flatMap((bind) => [
465
+ bind.mode === "rw" ? "--bind" : "--ro-bind",
466
+ bind.source,
467
+ bind.target
468
+ ]),
469
+ "--chdir",
470
+ workdir,
471
+ "--",
472
+ commandPath ?? options.command,
473
+ ...options.args ?? []
474
+ ],
475
+ env: { PATH: process.env["PATH"] },
476
+ cleanup: async () => {
477
+ await Promise.all(tempDirs.map((dir) => rm(dir, {
478
+ recursive: true,
479
+ force: true
480
+ })));
481
+ }
482
+ };
483
+ }
484
+ function addBind(binds, source, target, mode) {
485
+ binds.set(`${source}\u0000${target}`, {
486
+ source,
487
+ target,
488
+ mode
489
+ });
490
+ }
491
+ function defaultCliDirs(exists) {
492
+ return [
493
+ "/usr/bin",
494
+ "/bin",
495
+ "/usr/lib",
496
+ "/usr/lib64",
497
+ "/lib",
498
+ "/lib64"
499
+ ].filter((path, index, items) => items.indexOf(path) === index && exists(path));
500
+ }
501
+ function defaultCliCertDirs(exists) {
502
+ return [
503
+ "/etc/ssl",
504
+ "/etc/pki",
505
+ "/etc/ca-certificates",
506
+ "/usr/share/ca-certificates",
507
+ "/usr/local/share/ca-certificates"
508
+ ].filter((path, index, items) => items.indexOf(path) === index && exists(path));
509
+ }
510
+ function defaultCliFiles(exists) {
511
+ return ["/etc/hosts", "/etc/resolv.conf"].filter((path, index, items) => items.indexOf(path) === index && exists(path));
512
+ }
513
+ function isolatedPathEnv(commandPath, nodePath, dirname) {
514
+ return [
515
+ commandPath ? dirname(commandPath) : void 0,
516
+ dirname(nodePath),
517
+ "/usr/bin",
518
+ "/bin"
519
+ ].filter((path, index, items) => path !== void 0 && items.indexOf(path) === index).join(":");
520
+ }
521
+ async function commandPathOf(command, pathEnv, exists, realpath) {
522
+ if (command.includes("/")) return realpath(command);
523
+ const found = pathEnv.split(":").filter(Boolean).map((dir) => `${dir}/${command}`).find((path) => exists(path));
524
+ return found ? realpath(found) : void 0;
525
+ }
526
+ function resolveValue(value, input, ctx) {
527
+ if (typeof value === "function") return value(input, ctx);
528
+ return value;
529
+ }
530
+ function resolveRequiredValue(value, input, ctx) {
531
+ if (typeof value === "function") return value(input, ctx);
532
+ return value;
533
+ }
534
+ function guard(name, text = "") {
535
+ return material(name, {
536
+ kind: "json",
537
+ initialState: { text }
538
+ });
539
+ }
540
+ function claudeCliWorker(options = {}) {
541
+ assertNoClaudeBare(options.extraArgs ?? []);
542
+ return cliWorker({
543
+ name: options.name ?? "claude",
544
+ command: options.command ?? "claude",
545
+ args: (input) => cliPromptArgs(["-p", ...options.extraArgs ?? []], input.prompt),
546
+ isolate: options.isolate,
547
+ timeoutMs: options.timeoutMs,
548
+ kind: "llm",
549
+ tags: options.tags
550
+ });
551
+ }
552
+ function codexCliWorker(options = {}) {
553
+ return cliWorker({
554
+ name: options.name ?? "codex",
555
+ command: options.command ?? "codex",
556
+ args: (input) => cliPromptArgs([
557
+ "exec",
558
+ "-s",
559
+ options.sandbox ?? "read-only",
560
+ ...options.extraArgs ?? []
561
+ ], input.prompt),
562
+ isolate: options.isolate,
563
+ timeoutMs: options.timeoutMs,
564
+ kind: "llm",
565
+ tags: options.tags
566
+ });
567
+ }
568
+ function claudeHarness(options = {}) {
569
+ return cliHarnessModel(claudeCliWorker({
570
+ name: options.name ?? "claude-harness",
571
+ command: options.command,
572
+ extraArgs: ["--no-session-persistence", ...options.extraArgs ?? []],
573
+ isolate: options.isolate ?? { network: true },
574
+ timeoutMs: options.timeoutMs,
575
+ tags: options.tags
576
+ }), {
577
+ guard: options.guard === void 0 ? guard(`${options.name ?? "claude-harness"}-guard`) : options.guard,
578
+ prompt: options.prompt,
579
+ parse: options.parse
580
+ });
581
+ }
582
+ function codexHarness(options = {}) {
583
+ return cliHarnessModel(codexCliWorker({
584
+ name: options.name ?? "codex-harness",
585
+ command: options.command,
586
+ sandbox: options.sandbox,
587
+ extraArgs: [
588
+ "--ephemeral",
589
+ "--ignore-user-config",
590
+ ...options.extraArgs ?? []
591
+ ],
592
+ isolate: options.isolate ?? { network: true },
593
+ timeoutMs: options.timeoutMs,
594
+ tags: options.tags
595
+ }), {
596
+ guard: options.guard === void 0 ? guard(`${options.name ?? "codex-harness"}-guard`) : options.guard,
597
+ prompt: options.prompt,
598
+ parse: options.parse
599
+ });
600
+ }
601
+ function cliHarnessModel(worker, config) {
602
+ return { complete: async (ctx, request) => {
603
+ const current = config.guard ? await ctx.resolve(config.guard) : void 0;
604
+ const state = current?.state ?? { text: "" };
605
+ const output = await ctx.exec({
606
+ flow: worker,
607
+ input: { prompt: config.prompt ? config.prompt(request, state) : modelPrompt(request, state) }
608
+ });
609
+ const response = config.parse ? config.parse(output) : parseModelOutput(output);
610
+ if (config.guard && current) await collectGuard(ctx, config.guard, current, response);
611
+ return response;
612
+ } };
613
+ }
614
+ async function collectGuard(ctx, store, current, response) {
615
+ const text = guardTextOf(response.guard);
616
+ if (!text || current.state.text) return;
617
+ await patchMaterial(ctx, store, [{
618
+ op: "replace",
619
+ path: "/text",
620
+ value: text
621
+ }], { expectedRevision: current.revision });
622
+ }
623
+ function modelPrompt(request, guard) {
624
+ return [
625
+ "Return JSON only.",
626
+ "Schema: {\"content\":string,\"stop\"?:boolean,\"guard\"?:string,\"skillCalls\"?:array,\"toolCalls\"?:array,\"subagentCalls\"?:array}.",
627
+ guard.text ? `Guard:\n${guard.text}` : "First run only: set guard to the anti-goal that should prevent this agent from drifting.",
628
+ `Agent: ${request.agentName}`,
629
+ request.instructions ? `Instructions:\n${request.instructions}` : void 0,
630
+ request.skills.length ? `Available skills:\n${request.skills.map(formatCapability).join("\n")}` : void 0,
631
+ request.loadedSkills.length ? `Loaded skills:\n${request.loadedSkills.map(formatLoadedSkill).join("\n\n")}` : void 0,
632
+ request.tools.length ? `Available tools:\n${request.tools.map(formatCapability).join("\n")}` : void 0,
633
+ request.subagents.length ? `Available subagents:\n${request.subagents.map(formatCapability).join("\n")}` : void 0,
634
+ `Round: ${request.round}`,
635
+ `Messages:\n${request.messages.map(formatMessage).join("\n")}`
636
+ ].filter((item) => item !== void 0).join("\n\n");
637
+ }
638
+ function parseModelOutput(output) {
639
+ const value = readJson(output);
640
+ if (!isRecord(value)) return {
641
+ content: output,
642
+ stop: true
643
+ };
644
+ const response = {
645
+ content: typeof value["content"] === "string" ? value["content"] : output,
646
+ stop: typeof value["stop"] === "boolean" ? value["stop"] : true
647
+ };
648
+ const guard = guardTextOf(value["guard"] ?? value["antiGoal"]);
649
+ const skillCalls = skillCallsOf(value["skillCalls"]);
650
+ const toolCalls = toolCallsOf(value["toolCalls"]);
651
+ const subagentCalls = subagentCallsOf(value["subagentCalls"]);
652
+ if (guard) response.guard = guard;
653
+ if (skillCalls) response.skillCalls = skillCalls;
654
+ if (toolCalls) response.toolCalls = toolCalls;
655
+ if (subagentCalls) response.subagentCalls = subagentCalls;
656
+ return response;
657
+ }
658
+ function readJson(output) {
659
+ const trimmed = output.trim();
660
+ if (!trimmed) return void 0;
661
+ try {
662
+ return JSON.parse(trimmed);
663
+ } catch {
664
+ const start = trimmed.indexOf("{");
665
+ const end = trimmed.lastIndexOf("}");
666
+ if (start === -1 || end <= start) return void 0;
667
+ try {
668
+ return JSON.parse(trimmed.slice(start, end + 1));
669
+ } catch {
670
+ return;
671
+ }
672
+ }
673
+ }
674
+ function skillCallsOf(value) {
675
+ if (!Array.isArray(value)) return void 0;
676
+ const calls = value.flatMap((item) => {
677
+ if (!isRecord(item) || typeof item["name"] !== "string") return [];
678
+ return [{
679
+ name: item["name"],
680
+ ...typeof item["id"] === "string" ? { id: item["id"] } : {}
681
+ }];
682
+ });
683
+ return calls.length ? calls : void 0;
684
+ }
685
+ function toolCallsOf(value) {
686
+ if (!Array.isArray(value)) return void 0;
687
+ const calls = value.flatMap((item) => {
688
+ if (!isRecord(item) || typeof item["name"] !== "string") return [];
689
+ return [{
690
+ name: item["name"],
691
+ input: item["input"],
692
+ ...typeof item["id"] === "string" ? { id: item["id"] } : {}
693
+ }];
694
+ });
695
+ return calls.length ? calls : void 0;
696
+ }
697
+ function subagentCallsOf(value) {
698
+ if (!Array.isArray(value)) return void 0;
699
+ const calls = value.flatMap((item) => {
700
+ if (!isRecord(item) || typeof item["name"] !== "string") return [];
701
+ return [{
702
+ name: item["name"],
703
+ input: turnInputOf(item["input"]),
704
+ ...typeof item["id"] === "string" ? { id: item["id"] } : {}
705
+ }];
706
+ });
707
+ return calls.length ? calls : void 0;
708
+ }
709
+ function turnInputOf(value) {
710
+ if (isRecord(value)) return value;
711
+ return { prompt: stringifyAgentValue(value) };
712
+ }
713
+ function guardTextOf(value) {
714
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
715
+ }
716
+ function formatCapability(capability) {
717
+ return `- ${capability.name}: ${capability.description}`;
718
+ }
719
+ function formatLoadedSkill(skill) {
720
+ return `## ${skill.name}\n${skill.content}`;
721
+ }
722
+ function formatMessage(message) {
723
+ return message.name ? `${message.role}(${message.name}): ${message.content}` : `${message.role}: ${message.content}`;
724
+ }
725
+ function assertNoClaudeBare(args) {
726
+ if (args.some((arg) => arg === "--bare" || arg.startsWith("--bare="))) throw new Error("Claude harness must not use --bare");
727
+ }
728
+ function cliPromptArgs(args, prompt) {
729
+ if (args.includes("--")) throw new Error("CLI helper extraArgs cannot include --");
730
+ return [
731
+ ...args,
732
+ "--",
733
+ prompt
734
+ ];
735
+ }
736
+ const events = (0, _pumped_fn_lite.resource)({
737
+ name: "agent.events",
738
+ ownership: "boundary",
739
+ factory: () => {
740
+ let next = 0;
741
+ const events = [];
742
+ return {
743
+ get events() {
744
+ return events;
745
+ },
746
+ record(event) {
747
+ const stored = {
748
+ ...event,
749
+ index: next++
750
+ };
751
+ events.push(stored);
752
+ return stored;
753
+ }
754
+ };
755
+ }
756
+ });
757
+ const model = (0, _pumped_fn_lite.tag)({ label: "agent.model" });
758
+ const sandbox = (0, _pumped_fn_lite.tag)({ label: "agent.sandbox" });
759
+ function session(name, options = {}) {
760
+ return material(name, {
761
+ kind: "json",
762
+ initialState: { messages: options.messages ?? [] },
763
+ tags: options.tags,
764
+ keepAlive: options.keepAlive
765
+ });
766
+ }
767
+ function tool(options) {
768
+ const name = options.name ?? options.flow.name;
769
+ if (!name) throw new Error("Agent tool requires a name");
770
+ return {
771
+ name,
772
+ description: options.description,
773
+ flow: options.flow
774
+ };
775
+ }
776
+ function skill(options) {
777
+ if (options.load) return {
778
+ name: options.name,
779
+ description: options.description,
780
+ load: options.load
781
+ };
782
+ const content = options.content ?? "";
783
+ return {
784
+ name: options.name,
785
+ description: options.description,
786
+ load: () => content
787
+ };
788
+ }
789
+ function sub(options) {
790
+ return {
791
+ name: options.name ?? options.agent.name,
792
+ description: options.description,
793
+ agent: options.agent
794
+ };
795
+ }
796
+ function agent(options) {
797
+ const tools = options.tools ?? [];
798
+ const skills = options.skills ?? [];
799
+ const subagents = options.subagents ?? [];
800
+ const maxRounds = options.maxRounds ?? 4;
801
+ let agent;
802
+ const turn = (0, _pumped_fn_lite.flow)({
803
+ name: options.name,
804
+ parse: (0, _pumped_fn_lite.typed)(),
805
+ deps: { model: _pumped_fn_lite.tags.required(model) },
806
+ tags: agentStepTags({
807
+ workflow: true,
808
+ kind: "agent"
809
+ }, options.tags),
810
+ factory: (ctx, deps) => executeAgentTurn(ctx, agent, deps.model)
811
+ });
812
+ agent = {
813
+ name: options.name,
814
+ description: options.description,
815
+ instructions: options.instructions ?? "",
816
+ tools,
817
+ skills,
818
+ subagents,
819
+ turn,
820
+ maxRounds
821
+ };
822
+ return agent;
823
+ }
824
+ function execTurn(ctx, agent, input, tags = []) {
825
+ return ctx.exec({
826
+ flow: agent.turn,
827
+ input,
828
+ name: agent.name,
829
+ tags: [...tags]
830
+ });
831
+ }
832
+ async function send(ctx, session, agent, input) {
833
+ const current = await ctx.resolve(session);
834
+ const result = await execTurn(ctx, agent, {
835
+ ...input,
836
+ messages: [...current.state.messages, ...input.messages ?? []]
837
+ });
838
+ await patchMaterial(ctx, session, [{
839
+ op: "replace",
840
+ path: "/messages",
841
+ value: serializeMessages(result.messages)
842
+ }], { expectedRevision: current.revision });
843
+ return result;
844
+ }
845
+ function channel(options) {
846
+ const flowOptions = {
847
+ name: options.name,
848
+ tags: agentStepTags({
849
+ workflow: true,
850
+ kind: "channel"
851
+ }, options.tags),
852
+ factory: async (ctx) => execTurn(ctx, options.agent, await options.input(ctx))
853
+ };
854
+ return typeof options.parse === "function" ? (0, _pumped_fn_lite.flow)({
855
+ ...flowOptions,
856
+ parse: options.parse
857
+ }) : (0, _pumped_fn_lite.flow)({
858
+ ...flowOptions,
859
+ parse: options.parse
860
+ });
861
+ }
862
+ function schedule(options) {
863
+ return (0, _pumped_fn_lite.flow)({
864
+ name: options.name,
865
+ tags: agentStepTags({
866
+ workflow: true,
867
+ kind: "schedule"
868
+ }, options.tags),
869
+ factory: async (ctx) => execTurn(ctx, options.agent, await options.input(ctx))
870
+ });
871
+ }
872
+ function judge(options) {
873
+ return options;
874
+ }
875
+ function suite(options) {
876
+ const judges = options.judges ?? [];
877
+ assertJudgeQuorum(judges);
878
+ return {
879
+ name: options.name,
880
+ agent: options.agent,
881
+ cases: options.cases,
882
+ judges
883
+ };
884
+ }
885
+ function includes(text) {
886
+ return (result) => ({
887
+ name: `output includes "${text}"`,
888
+ passed: result.content.includes(text)
889
+ });
890
+ }
891
+ function used(name) {
892
+ return (result) => ({
893
+ name: `tool used "${name}"`,
894
+ passed: result.toolResults.some((call) => call.name === name)
895
+ });
896
+ }
897
+ function loaded(name) {
898
+ return (result) => ({
899
+ name: `skill loaded "${name}"`,
900
+ passed: result.skillResults.some((call) => call.name === name)
901
+ });
902
+ }
903
+ function delegated(name) {
904
+ return (result) => ({
905
+ name: `subagent used "${name}"`,
906
+ passed: result.subagentResults.some((call) => call.name === name)
907
+ });
908
+ }
909
+ async function runEval(ctx, target) {
910
+ assertJudgeQuorum(target.judges);
911
+ const cases = [];
912
+ for (const item of target.cases) {
913
+ const result = await execTurn(ctx, target.agent, item.input);
914
+ const checks = await runEvalChecks(result, item.checks ?? []);
915
+ const judges = await runEvalJudges(ctx, result, target.judges);
916
+ cases.push({
917
+ name: item.name,
918
+ result,
919
+ checks,
920
+ judges,
921
+ passed: checks.every((check) => check.passed) && judges.every((judge) => judge.passed)
922
+ });
923
+ }
924
+ return {
925
+ name: target.name,
926
+ cases,
927
+ passed: cases.every((item) => item.passed)
928
+ };
929
+ }
930
+ async function inspect(log, query) {
931
+ const entries = (await log.entries(query)).filter((entry) => entry.key.taskId === query.taskId && entry.key.runId === query.runId);
932
+ if (!entries[0]) throw new Error("Run not found");
933
+ const steps = entries.map(runStep);
934
+ return {
935
+ taskId: query.taskId,
936
+ runId: query.runId,
937
+ status: steps.some((item) => item.status === "pending") ? "pending" : "completed",
938
+ steps
939
+ };
940
+ }
941
+ function summary(report) {
942
+ return jsonValue({
943
+ name: report.name,
944
+ passed: report.passed,
945
+ cases: report.cases.map((item) => ({
946
+ name: item.name,
947
+ passed: item.passed,
948
+ output: item.result.content,
949
+ checks: item.checks,
950
+ judges: item.judges,
951
+ tools: item.result.toolResults.map((call) => ({
952
+ name: call.name,
953
+ output: call.output
954
+ })),
955
+ skills: item.result.skillResults.map((call) => ({ name: call.name })),
956
+ subagents: item.result.subagentResults.map((call) => ({
957
+ name: call.name,
958
+ output: call.output.content
959
+ })),
960
+ events: item.result.events.map((event) => ({
961
+ type: event.type,
962
+ agentName: event.agentName,
963
+ targetName: event.targetName,
964
+ round: event.round
965
+ }))
966
+ }))
967
+ });
968
+ }
969
+ function http(options) {
970
+ return (0, _pumped_fn_lite.flow)({
971
+ name: options.name ?? `${options.agent.name}-http`,
972
+ parse: (0, _pumped_fn_lite.typed)(),
973
+ tags: agentStepTags({
974
+ workflow: true,
975
+ kind: "channel"
976
+ }),
977
+ factory: async (ctx) => {
978
+ const request = ctx.input;
979
+ const input = options.input ? await options.input(request) : await request.json();
980
+ const tags = options.tags ? await options.tags(request) : [];
981
+ return Response.json(jsonValue(await execTurn(ctx, options.agent, input, tags)));
982
+ }
983
+ });
984
+ }
985
+ async function executeAgentTurn(ctx, agent, model) {
986
+ const messages = initialMessages(ctx.input);
987
+ const loadedSkills = [];
988
+ const skillResults = [];
989
+ const toolResults = [];
990
+ const subagentResults = [];
991
+ const maxRounds = ctx.input.maxRounds ?? agent.maxRounds;
992
+ let content = "";
993
+ let rounds = 0;
994
+ const startIndex = (await ctx.resolve(events)).events.length;
995
+ await recordAgentEvent(ctx, {
996
+ type: "agent_start",
997
+ agentName: agent.name,
998
+ input: ctx.input
999
+ });
1000
+ for (let round = 0; round < maxRounds; round++) {
1001
+ rounds = round + 1;
1002
+ await recordAgentEvent(ctx, {
1003
+ type: "agent_model_start",
1004
+ agentName: agent.name,
1005
+ round,
1006
+ input: messages
1007
+ });
1008
+ const response = await model.complete(ctx, {
1009
+ agentName: agent.name,
1010
+ instructions: agent.instructions,
1011
+ messages,
1012
+ tools: agent.tools.map(agentToolCapability),
1013
+ skills: agent.skills.map(agentSkillCapability),
1014
+ loadedSkills,
1015
+ subagents: agent.subagents.map(agentSubagentCapability),
1016
+ round
1017
+ });
1018
+ content = response.content;
1019
+ await recordAgentEvent(ctx, {
1020
+ type: "agent_model_end",
1021
+ agentName: agent.name,
1022
+ round,
1023
+ output: response
1024
+ });
1025
+ const skillCalls = response.skillCalls ?? [];
1026
+ const toolCalls = response.toolCalls ?? [];
1027
+ const subagentCalls = response.subagentCalls ?? [];
1028
+ if (response.content) messages.push({
1029
+ role: "assistant",
1030
+ content: response.content
1031
+ });
1032
+ if (response.stop === true || skillCalls.length === 0 && toolCalls.length === 0 && subagentCalls.length === 0) break;
1033
+ for (const call of skillCalls) {
1034
+ const result = await executeAgentSkill(ctx, agent, call);
1035
+ loadedSkills.push({
1036
+ name: result.name,
1037
+ content: result.content,
1038
+ description: findByName(agent.skills, result.name, "skill").description
1039
+ });
1040
+ skillResults.push(result);
1041
+ messages.push({
1042
+ role: "skill",
1043
+ name: result.name,
1044
+ content: result.content
1045
+ });
1046
+ }
1047
+ for (const call of toolCalls) {
1048
+ const result = await executeAgentTool(ctx, agent, call);
1049
+ toolResults.push(result);
1050
+ messages.push({
1051
+ role: "tool",
1052
+ name: result.name,
1053
+ content: stringifyAgentValue(result.output)
1054
+ });
1055
+ }
1056
+ for (const call of subagentCalls) {
1057
+ const result = await executeAgentSubagent(ctx, agent, call);
1058
+ subagentResults.push(result);
1059
+ messages.push({
1060
+ role: "subagent",
1061
+ name: result.name,
1062
+ content: result.output.content
1063
+ });
1064
+ }
1065
+ }
1066
+ await recordAgentEvent(ctx, {
1067
+ type: "agent_end",
1068
+ agentName: agent.name,
1069
+ output: content
1070
+ });
1071
+ const buffer = await ctx.resolve(events);
1072
+ return {
1073
+ agentName: agent.name,
1074
+ content,
1075
+ messages,
1076
+ skillResults,
1077
+ toolResults,
1078
+ subagentResults,
1079
+ rounds,
1080
+ events: buffer.events.slice(startIndex)
1081
+ };
1082
+ }
1083
+ async function executeAgentSkill(ctx, agent, call) {
1084
+ const target = findByName(agent.skills, call.name, "skill");
1085
+ await recordAgentEvent(ctx, {
1086
+ type: "agent_skill_start",
1087
+ agentName: agent.name,
1088
+ targetName: target.name
1089
+ });
1090
+ const content = await ctx.exec({
1091
+ fn: (skillCtx) => target.load(skillCtx),
1092
+ params: [],
1093
+ name: target.name,
1094
+ tags: [agentStepTag({
1095
+ workflow: true,
1096
+ kind: "skill"
1097
+ })]
1098
+ });
1099
+ await recordAgentEvent(ctx, {
1100
+ type: "agent_skill_end",
1101
+ agentName: agent.name,
1102
+ targetName: target.name,
1103
+ output: content
1104
+ });
1105
+ return {
1106
+ name: target.name,
1107
+ id: call.id,
1108
+ content
1109
+ };
1110
+ }
1111
+ async function executeAgentTool(ctx, agent, call) {
1112
+ const target = findByName(agent.tools, call.name, "tool");
1113
+ await recordAgentEvent(ctx, {
1114
+ type: "agent_tool_start",
1115
+ agentName: agent.name,
1116
+ targetName: target.name,
1117
+ input: call.input
1118
+ });
1119
+ const output = await ctx.exec({
1120
+ flow: target.flow,
1121
+ rawInput: call.input,
1122
+ name: target.name,
1123
+ tags: [agentStepTag({
1124
+ workflow: true,
1125
+ kind: "tool"
1126
+ }, target.flow.tags)]
1127
+ });
1128
+ await recordAgentEvent(ctx, {
1129
+ type: "agent_tool_end",
1130
+ agentName: agent.name,
1131
+ targetName: target.name,
1132
+ output
1133
+ });
1134
+ return {
1135
+ name: target.name,
1136
+ id: call.id,
1137
+ input: call.input,
1138
+ output
1139
+ };
1140
+ }
1141
+ async function executeAgentSubagent(ctx, agent, call) {
1142
+ const target = findByName(agent.subagents, call.name, "subagent");
1143
+ await recordAgentEvent(ctx, {
1144
+ type: "agent_subagent_start",
1145
+ agentName: agent.name,
1146
+ targetName: target.name,
1147
+ input: call.input
1148
+ });
1149
+ const output = await ctx.exec({
1150
+ flow: target.agent.turn,
1151
+ input: call.input,
1152
+ name: target.name,
1153
+ tags: [agentStepTag({
1154
+ workflow: true,
1155
+ kind: "subagent"
1156
+ }, target.agent.turn.tags)]
1157
+ });
1158
+ await recordAgentEvent(ctx, {
1159
+ type: "agent_subagent_end",
1160
+ agentName: agent.name,
1161
+ targetName: target.name,
1162
+ output
1163
+ });
1164
+ return {
1165
+ name: target.name,
1166
+ id: call.id,
1167
+ input: call.input,
1168
+ output
1169
+ };
1170
+ }
1171
+ async function recordAgentEvent(ctx, event) {
1172
+ return (await ctx.resolve(events)).record(event);
1173
+ }
1174
+ function initialMessages(input) {
1175
+ return [...input.messages ?? [], ...input.prompt ? [{
1176
+ role: "user",
1177
+ content: input.prompt
1178
+ }] : []];
1179
+ }
1180
+ function agentStepTags(defaults, source = []) {
1181
+ return [agentStepTag(defaults, source), ...source.filter((tagged) => tagged.key !== step.key)];
1182
+ }
1183
+ function agentStepTag(defaults, source = []) {
1184
+ return step(Object.assign({}, defaults, ...step.collect(source)));
1185
+ }
1186
+ function agentToolCapability(tool) {
1187
+ return {
1188
+ name: tool.name,
1189
+ description: tool.description
1190
+ };
1191
+ }
1192
+ function agentSkillCapability(skill) {
1193
+ return {
1194
+ name: skill.name,
1195
+ description: skill.description ?? ""
1196
+ };
1197
+ }
1198
+ function agentSubagentCapability(subagent) {
1199
+ return {
1200
+ name: subagent.name,
1201
+ description: subagent.description
1202
+ };
1203
+ }
1204
+ function findByName(items, name, kind) {
1205
+ const found = items.find((item) => item.name === name);
1206
+ if (!found) throw new Error(`Agent ${kind} "${name}" not found`);
1207
+ return found;
1208
+ }
1209
+ function runStep(entry) {
1210
+ if (entry.status === "pending") return {
1211
+ key: entry.key,
1212
+ status: entry.status,
1213
+ targetName: entry.targetName,
1214
+ input: entry.input,
1215
+ kind: entry.kind
1216
+ };
1217
+ if (entry.status === "resolved") return {
1218
+ key: entry.key,
1219
+ status: entry.status,
1220
+ targetName: entry.targetName,
1221
+ output: entry.value
1222
+ };
1223
+ return {
1224
+ key: entry.key,
1225
+ status: entry.status,
1226
+ targetName: entry.targetName,
1227
+ output: entry.result
1228
+ };
1229
+ }
1230
+ function stringifyAgentValue(value) {
1231
+ if (typeof value === "string") return value;
1232
+ if (value === void 0) return String(value);
1233
+ if (typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") return String(value);
1234
+ const seen = /* @__PURE__ */ new WeakSet();
1235
+ return JSON.stringify(value, (_key, item) => {
1236
+ if (typeof item === "bigint" || typeof item === "symbol" || typeof item === "function") return String(item);
1237
+ if (typeof item === "object" && item !== null) {
1238
+ if (seen.has(item)) return "[Circular]";
1239
+ seen.add(item);
1240
+ }
1241
+ return item;
1242
+ }) ?? String(value);
1243
+ }
1244
+ function jsonValue(value, seen = /* @__PURE__ */ new WeakSet()) {
1245
+ if (value === null) return null;
1246
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
1247
+ if (value === void 0 || typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") return String(value);
1248
+ if (Array.isArray(value)) return value.map((item) => jsonValue(item, seen));
1249
+ if (typeof value === "object") {
1250
+ if (seen.has(value)) return "[Circular]";
1251
+ seen.add(value);
1252
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonValue(item, seen)]));
1253
+ }
1254
+ return String(value);
1255
+ }
1256
+ function serializeMessages(messages) {
1257
+ return messages.map((message) => {
1258
+ const serialized = {
1259
+ role: message.role,
1260
+ content: message.content
1261
+ };
1262
+ if (message.name !== void 0) serialized["name"] = message.name;
1263
+ return serialized;
1264
+ });
1265
+ }
1266
+ async function runEvalChecks(result, checks) {
1267
+ const results = [];
1268
+ for (const check of checks) results.push(await check(result));
1269
+ return results;
1270
+ }
1271
+ function assertJudgeQuorum(judges) {
1272
+ if (judges.length === 1) throw new Error("Agent evals require zero judges or at least two judges");
1273
+ }
1274
+ async function runEvalJudges(ctx, result, judges) {
1275
+ const results = [];
1276
+ for (const judge of judges) results.push(await judge.evaluate(ctx, result));
1277
+ return results;
1278
+ }
1279
+ //#endregion
1280
+ exports.CliWorkerError = CliWorkerError;
1281
+ exports.MaterialConflictError = MaterialConflictError;
1282
+ Object.defineProperty(exports, "SuspendSignal", {
1283
+ enumerable: true,
1284
+ get: function() {
1285
+ return _pumped_fn_lite_extension_suspense.SuspendSignal;
1286
+ }
1287
+ });
1288
+ Object.defineProperty(exports, "SuspenseSignal", {
1289
+ enumerable: true,
1290
+ get: function() {
1291
+ return _pumped_fn_lite_extension_suspense.SuspenseSignal;
1292
+ }
1293
+ });
1294
+ exports.WorkerRegistry = WorkerRegistry;
1295
+ exports.abortSignal = abortSignal;
1296
+ exports.agent = agent;
1297
+ exports.channel = channel;
1298
+ exports.claudeCliWorker = claudeCliWorker;
1299
+ exports.claudeHarness = claudeHarness;
1300
+ exports.cliWorker = cliWorker;
1301
+ exports.codexCliWorker = codexCliWorker;
1302
+ exports.codexHarness = codexHarness;
1303
+ exports.delegated = delegated;
1304
+ exports.derivedMaterial = derivedMaterial;
1305
+ exports.events = events;
1306
+ exports.extension = extension;
1307
+ exports.formatStepKey = formatStepKey;
1308
+ exports.guard = guard;
1309
+ exports.http = http;
1310
+ exports.includes = includes;
1311
+ exports.inspect = inspect;
1312
+ exports.judge = judge;
1313
+ exports.loaded = loaded;
1314
+ exports.material = material;
1315
+ exports.materialKind = materialKind;
1316
+ exports.model = model;
1317
+ exports.patchMaterial = patchMaterial;
1318
+ exports.runCli = runCli;
1319
+ exports.runEval = runEval;
1320
+ exports.runtime = runtime;
1321
+ exports.sandbox = sandbox;
1322
+ exports.schedule = schedule;
1323
+ exports.send = send;
1324
+ exports.session = session;
1325
+ exports.skill = skill;
1326
+ exports.step = step;
1327
+ exports.sub = sub;
1328
+ exports.suite = suite;
1329
+ exports.summary = summary;
1330
+ exports.tool = tool;
1331
+ exports.used = used;
1332
+ exports.workerRegistry = workerRegistry;
1333
+ exports.workers = workers;
1334
+ exports.workflow = workflow;
1335
+ exports.workflowExtension = workflowExtension;
1336
+ exports.workflowRun = workflowRun;