@agentfield/sdk 0.1.136 → 0.1.137-rc.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.
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
+ import { spawn } from 'child_process';
2
+ import os, { constants } from 'os';
1
3
  import { createRequire } from 'module';
2
4
  import * as path4 from 'path';
3
5
  import path4__default, { resolve, dirname } from 'path';
4
6
  import fs, { promises, readFileSync } from 'fs';
5
- import { spawn } from 'child_process';
6
7
  import express from 'express';
7
8
  import rateLimit from 'express-rate-limit';
8
9
  import crypto2, { randomUUID, createHash } from 'crypto';
@@ -19,12 +20,11 @@ import { createGroq } from '@ai-sdk/groq';
19
20
  import { createXai } from '@ai-sdk/xai';
20
21
  import { createDeepSeek } from '@ai-sdk/deepseek';
21
22
  import { createCohere } from '@ai-sdk/cohere';
22
- import os from 'os';
23
+ import { readFile } from 'fs/promises';
23
24
  import WebSocket from 'ws';
24
25
  import { Buffer as Buffer$1 } from 'buffer';
25
26
  import { zodToJsonSchema } from 'zod-to-json-schema';
26
27
  import { generateKeyPair, exportJWK, importJWK, CompactEncrypt, compactDecrypt } from 'jose';
27
- import { readFile } from 'fs/promises';
28
28
  import { fileURLToPath } from 'url';
29
29
 
30
30
  var __defProp = Object.defineProperty;
@@ -150,250 +150,17 @@ var init_openrouterAttribution = __esm({
150
150
  }
151
151
  });
152
152
 
153
- // src/harness/modelVariant.ts
154
- function splitModelVariant(model) {
155
- if (typeof model !== "string" || !model.trim()) {
156
- return {};
157
- }
158
- const sepIndex = model.indexOf(MODEL_VARIANT_SEP);
159
- const base = sepIndex === -1 ? model : model.slice(0, sepIndex);
160
- const variant = sepIndex === -1 ? "" : model.slice(sepIndex + 1);
161
- return {
162
- model: base.trim() || void 0,
163
- variant: variant.trim() || void 0
164
- };
165
- }
166
- function resolveModelAndVariant(options) {
167
- const { model, variant } = splitModelVariant(options.model);
168
- const explicit = options.variant;
169
- if (typeof explicit === "string" && explicit.trim()) {
170
- return { model, variant: explicit.trim() };
171
- }
172
- return { model, variant };
173
- }
174
- var MODEL_VARIANT_SEP;
175
- var init_modelVariant = __esm({
176
- "src/harness/modelVariant.ts"() {
177
- MODEL_VARIANT_SEP = "#";
178
- }
179
- });
180
- function isRecord2(value) {
181
- return typeof value === "object" && value !== null && !Array.isArray(value);
182
- }
183
- function isZod4Schema(value) {
184
- if (!isRecord2(value) || !("_zod" in value) || !isRecord2(value._zod)) {
185
- return false;
186
- }
187
- return isRecord2(value._zod.def);
188
- }
189
- function getZod4Converter() {
190
- if (zod4Converter !== void 0) {
191
- return zod4Converter;
192
- }
193
- const requires = [];
194
- try {
195
- requires.push(createRequire(path4__default.join(process.cwd(), "package.json")));
196
- } catch {
197
- }
198
- requires.push(createRequire(import.meta.url));
199
- for (const req of requires) {
200
- for (const moduleName of ["zod", "zod/v4"]) {
201
- try {
202
- const mod = req(moduleName);
203
- if (typeof mod.toJSONSchema === "function") {
204
- zod4Converter = mod.toJSONSchema;
205
- return zod4Converter;
206
- }
207
- } catch {
208
- }
209
- }
210
- }
211
- zod4Converter = null;
212
- return zod4Converter;
213
- }
214
- function zod4ToJsonSchema(schema) {
215
- const converter = getZod4Converter();
216
- if (converter === null) {
217
- throw new TypeError(
218
- 'Cannot convert a Zod 4 schema: install the "zod" package with its "zod/v4" entry point available.'
219
- );
220
- }
221
- return converter(schema);
222
- }
223
- var zod4Converter;
224
- var init_zod_schema = __esm({
225
- "src/utils/zod-schema.ts"() {
226
- }
227
- });
228
- function getZodConverter() {
229
- if (zodConverter !== void 0) {
230
- return zodConverter;
231
- }
232
- try {
233
- const require2 = createRequire(import.meta.url);
234
- const mod = require2("zod-to-json-schema");
235
- zodConverter = mod.zodToJsonSchema ?? mod.default ?? null;
236
- } catch {
237
- zodConverter = null;
238
- }
239
- return zodConverter;
240
- }
241
- function isRecord3(value) {
242
- return typeof value === "object" && value !== null && !Array.isArray(value);
243
- }
244
- function hasJsonSchema(value) {
245
- return isRecord3(value) && typeof value.jsonSchema === "function";
246
- }
247
- function hasParse(value) {
248
- return isRecord3(value) && typeof value.parse === "function";
249
- }
250
- function estimateTokens(text2) {
251
- return Math.floor(text2.length / 4);
252
- }
253
- function writeSchemaFile(schemaJson, cwd) {
254
- const filePath = getSchemaPath(cwd);
255
- fs.mkdirSync(path4__default.dirname(filePath), { recursive: true });
256
- const fd = fs.openSync(filePath, "w", 384);
257
- try {
258
- fs.writeFileSync(fd, schemaJson, "utf8");
259
- } finally {
260
- fs.closeSync(fd);
261
- }
262
- return filePath;
263
- }
264
- function validateAgainstSchema(data, schema) {
265
- if (hasParse(schema)) {
266
- return schema.parse(data);
267
- }
268
- return data;
269
- }
270
- function getOutputPath(cwd) {
271
- return path4__default.join(cwd, OUTPUT_FILENAME);
272
- }
273
- function getSchemaPath(cwd) {
274
- return path4__default.join(cwd, SCHEMA_FILENAME);
275
- }
276
- function schemaToJsonSchema(schema) {
277
- if (isZod4Schema(schema)) {
278
- return zod4ToJsonSchema(schema);
279
- }
280
- if (isRecord3(schema)) {
281
- if ("type" in schema || "properties" in schema || "$schema" in schema) {
282
- return schema;
283
- }
284
- if (hasJsonSchema(schema)) {
285
- return schema.jsonSchema();
286
- }
287
- }
288
- const converter = getZodConverter();
289
- if (converter !== null) {
290
- return converter(schema);
291
- }
292
- throw new TypeError(
293
- 'Unsupported schema type. Expected a Zod schema (requires "zod-to-json-schema" for Zod 3 or "zod" for Zod 4), JSON schema object, or jsonSchema() provider.'
294
- );
295
- }
296
- function isLargeSchema(schemaJson) {
297
- return estimateTokens(schemaJson) > LARGE_SCHEMA_TOKEN_THRESHOLD;
298
- }
299
- function buildPromptSuffix(schema, cwd) {
300
- const jsonSchema2 = schemaToJsonSchema(schema);
301
- const schemaJson = JSON.stringify(jsonSchema2, null, 2);
302
- const outputPath = getOutputPath(cwd);
303
- if (isLargeSchema(schemaJson)) {
304
- const schemaPath = writeSchemaFile(schemaJson, cwd);
305
- return `
306
-
307
- ---
308
- OUTPUT REQUIREMENTS:
309
- Read the JSON Schema at: ${schemaPath}
310
- Write your final answer as valid JSON conforming to that schema to: ${outputPath}
311
- Do not include any text outside the JSON in that file. Do not wrap in markdown fences.`;
312
- }
313
- return `
314
-
315
- ---
316
- OUTPUT REQUIREMENTS:
317
- Write your final answer as valid JSON to the file: ${outputPath}
318
- The JSON must conform to this schema:
319
- ${schemaJson}
320
- Do not include any text outside the JSON in that file. Do not wrap in markdown fences.`;
321
- }
322
- function cosmeticRepair(raw) {
323
- let text2 = raw.trim();
324
- const fenceMatch = text2.match(/^```(?:json)?\s*\n([\s\S]*?)```\s*$/);
325
- if (fenceMatch) {
326
- text2 = fenceMatch[1].trim();
327
- }
328
- if (text2.length > 0 && text2[0] !== "{" && text2[0] !== "[") {
329
- const firstJsonCharIndex = [...text2].findIndex((char) => char === "{" || char === "[");
330
- if (firstJsonCharIndex >= 0) {
331
- text2 = text2.slice(firstJsonCharIndex);
332
- }
333
- }
334
- text2 = text2.replace(/,\s*([}\]])/g, "$1");
335
- const openBraces = (text2.match(/{/g)?.length ?? 0) - (text2.match(/}/g)?.length ?? 0);
336
- const openBrackets = (text2.match(/\[/g)?.length ?? 0) - (text2.match(/\]/g)?.length ?? 0);
337
- if (openBraces > 0 || openBrackets > 0) {
338
- text2 += "]".repeat(openBrackets) + "}".repeat(openBraces);
339
- }
340
- return text2;
341
- }
342
- function readAndParse(filePath) {
343
- try {
344
- const content = fs.readFileSync(filePath, "utf8");
345
- if (content.trim().length === 0) {
346
- return null;
347
- }
348
- return JSON.parse(content);
349
- } catch {
350
- return null;
351
- }
352
- }
353
- function readRepairAndParse(filePath) {
354
- try {
355
- const content = fs.readFileSync(filePath, "utf8");
356
- if (content.trim().length === 0) {
357
- return null;
358
- }
359
- return JSON.parse(cosmeticRepair(content));
360
- } catch {
361
- return null;
362
- }
363
- }
364
- function parseAndValidate(filePath, schema) {
365
- const parsed = readAndParse(filePath);
366
- if (parsed !== null) {
367
- try {
368
- return validateAgainstSchema(parsed, schema);
369
- } catch {
370
- }
371
- }
372
- const repaired = readRepairAndParse(filePath);
373
- if (repaired !== null) {
374
- try {
375
- return validateAgainstSchema(repaired, schema);
376
- } catch {
377
- return null;
378
- }
379
- }
380
- return null;
381
- }
382
- function cleanupTempFiles(cwd) {
383
- for (const filename of [OUTPUT_FILENAME, SCHEMA_FILENAME]) {
384
- try {
385
- fs.unlinkSync(path4__default.join(cwd, filename));
386
- } catch {
153
+ // src/harness/providers/base.ts
154
+ function resolveRoot(options) {
155
+ for (const value of [options.projectDir, options.project_dir, options.cwd]) {
156
+ if (typeof value === "string" && value.length > 0) {
157
+ return value;
387
158
  }
388
159
  }
160
+ return void 0;
389
161
  }
390
- var OUTPUT_FILENAME, SCHEMA_FILENAME, LARGE_SCHEMA_TOKEN_THRESHOLD, zodConverter;
391
- var init_schema = __esm({
392
- "src/harness/schema.ts"() {
393
- init_zod_schema();
394
- OUTPUT_FILENAME = ".agentfield_output.json";
395
- SCHEMA_FILENAME = ".agentfield_schema.json";
396
- LARGE_SCHEMA_TOKEN_THRESHOLD = 4e3;
162
+ var init_base = __esm({
163
+ "src/harness/providers/base.ts"() {
397
164
  }
398
165
  });
399
166
 
@@ -490,13 +257,18 @@ function runCli(cmd, options) {
490
257
  clearInterval(idleTimer);
491
258
  }
492
259
  }
493
- proc.on("close", (code) => {
260
+ proc.on("close", (code, signal) => {
494
261
  if (settled) {
495
262
  return;
496
263
  }
497
264
  settled = true;
498
265
  cleanup();
499
- resolve3({ stdout, stderr, exitCode: code ?? 0 });
266
+ const signalNumber = signal ? constants.signals[signal] : void 0;
267
+ resolve3({
268
+ stdout,
269
+ stderr,
270
+ exitCode: code ?? (signalNumber === void 0 ? 0 : -signalNumber)
271
+ });
500
272
  });
501
273
  proc.on("error", (err) => {
502
274
  if (settled) {
@@ -557,19 +329,47 @@ var init_cli = __esm({
557
329
  }
558
330
  });
559
331
 
560
- // src/harness/providers/aforge.ts
561
- var aforge_exports = {};
562
- __export(aforge_exports, {
563
- AFORGE_DEFAULT_MODEL: () => AFORGE_DEFAULT_MODEL,
564
- AforgeProvider: () => AforgeProvider
565
- });
566
- function resolveMaxConcurrent() {
567
- const parsed = Number.parseInt(process.env.AFORGE_MAX_CONCURRENT ?? "", 10);
568
- return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;
569
- }
570
- function stripOpenRouterPrefix(model) {
571
- return model.startsWith("openrouter/") ? model.slice("openrouter/".length) : model;
572
- }
332
+ // src/harness/modelVariant.ts
333
+ function splitModelVariant(model) {
334
+ if (typeof model !== "string" || !model.trim()) {
335
+ return {};
336
+ }
337
+ const sepIndex = model.indexOf(MODEL_VARIANT_SEP);
338
+ const base = sepIndex === -1 ? model : model.slice(0, sepIndex);
339
+ const variant = sepIndex === -1 ? "" : model.slice(sepIndex + 1);
340
+ return {
341
+ model: base.trim() || void 0,
342
+ variant: variant.trim() || void 0
343
+ };
344
+ }
345
+ function resolveModelAndVariant(options) {
346
+ const { model, variant } = splitModelVariant(options.model);
347
+ const explicit = options.variant;
348
+ if (typeof explicit === "string" && explicit.trim()) {
349
+ return { model, variant: explicit.trim() };
350
+ }
351
+ return { model, variant };
352
+ }
353
+ var MODEL_VARIANT_SEP;
354
+ var init_modelVariant = __esm({
355
+ "src/harness/modelVariant.ts"() {
356
+ MODEL_VARIANT_SEP = "#";
357
+ }
358
+ });
359
+
360
+ // src/harness/providers/aforge.ts
361
+ var aforge_exports = {};
362
+ __export(aforge_exports, {
363
+ AFORGE_DEFAULT_MODEL: () => AFORGE_DEFAULT_MODEL,
364
+ AforgeProvider: () => AforgeProvider
365
+ });
366
+ function resolveMaxConcurrent() {
367
+ const parsed = Number.parseInt(process.env.AFORGE_MAX_CONCURRENT ?? "", 10);
368
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_CONCURRENT;
369
+ }
370
+ function stripOpenRouterPrefix(model) {
371
+ return model.startsWith("openrouter/") ? model.slice("openrouter/".length) : model;
372
+ }
573
373
  function parseEnvelope(stdout) {
574
374
  try {
575
375
  const value = JSON.parse(stdout.trim());
@@ -634,6 +434,7 @@ function stringOptions(value) {
634
434
  var REASONING_VARIANTS, DEFAULT_TIMEOUT_SECONDS, LANDING_WINDOW_SECONDS, DEFAULT_MAX_CONCURRENT, ANSI_PATTERN, AFORGE_DEFAULT_MODEL, Semaphore, aforgeSemaphore, AforgeProvider;
635
435
  var init_aforge = __esm({
636
436
  "src/harness/providers/aforge.ts"() {
437
+ init_base();
637
438
  init_types();
638
439
  init_cli();
639
440
  init_modelVariant();
@@ -685,9 +486,7 @@ var init_aforge = __esm({
685
486
  return aforgeSemaphore.use(() => this.executeImpl(prompt, options));
686
487
  }
687
488
  async executeImpl(prompt, options) {
688
- const projectDir = typeof options.projectDir === "string" ? options.projectDir : typeof options.project_dir === "string" ? options.project_dir : void 0;
689
- const cwd = typeof options.cwd === "string" ? options.cwd : void 0;
690
- const root = projectDir ?? cwd ?? ".";
489
+ const root = resolveRoot(options) ?? ".";
691
490
  const outerTimeout = timeoutSeconds();
692
491
  const command = (process.env.AGENTFIELD_AFORGE_COMMAND ?? "exec").trim().toLowerCase();
693
492
  if (command !== "do" && command !== "exec") {
@@ -815,7 +614,7 @@ var claude_exports = {};
815
614
  __export(claude_exports, {
816
615
  ClaudeCodeProvider: () => ClaudeCodeProvider
817
616
  });
818
- function isRecord4(value) {
617
+ function isRecord2(value) {
819
618
  return typeof value === "object" && value !== null;
820
619
  }
821
620
  function getString(record, key) {
@@ -829,6 +628,7 @@ function getNumber(record, key) {
829
628
  var ClaudeCodeProvider;
830
629
  var init_claude = __esm({
831
630
  "src/harness/providers/claude.ts"() {
631
+ init_base();
832
632
  init_types();
833
633
  init_modelVariant();
834
634
  ClaudeCodeProvider = class {
@@ -845,7 +645,8 @@ var init_claude = __esm({
845
645
  const agentOptions = {};
846
646
  const { model: modelValue } = resolveModelAndVariant(options);
847
647
  if (modelValue !== void 0) agentOptions.model = modelValue;
848
- if (options.cwd !== void 0) agentOptions.cwd = options.cwd;
648
+ const root = resolveRoot(options);
649
+ if (root !== void 0) agentOptions.cwd = root;
849
650
  if (options.maxTurns !== void 0) agentOptions.maxTurns = options.maxTurns;
850
651
  if (options.tools !== void 0) agentOptions.allowedTools = options.tools;
851
652
  if (options.systemPrompt !== void 0) agentOptions.systemPrompt = options.systemPrompt;
@@ -870,7 +671,7 @@ var init_claude = __esm({
870
671
  const startApi = Date.now();
871
672
  try {
872
673
  for await (const msg of sdk.query({ prompt, options: agentOptions })) {
873
- const msgObj = isRecord4(msg) ? msg : { raw: String(msg) };
674
+ const msgObj = isRecord2(msg) ? msg : { raw: String(msg) };
874
675
  messages.push(msgObj);
875
676
  const msgType = getString(msgObj, "type") ?? "";
876
677
  if (msgType === "result") {
@@ -889,7 +690,7 @@ var init_claude = __esm({
889
690
  }
890
691
  const turns = getNumber(msgObj, "num_turns");
891
692
  numTurns = turns === void 0 ? messages.length : Math.trunc(turns);
892
- if (isRecord4(msgObj.usage)) {
693
+ if (isRecord2(msgObj.usage)) {
893
694
  usageObj = msgObj.usage;
894
695
  inputTokens = getNumber(usageObj, "input_tokens");
895
696
  outputTokens = getNumber(usageObj, "output_tokens");
@@ -898,19 +699,19 @@ var init_claude = __esm({
898
699
  }
899
700
  modelName = getString(msgObj, "model") ?? modelName;
900
701
  } else if (msgType === "assistant") {
901
- if (modelName === void 0 && isRecord4(msgObj.message)) {
702
+ if (modelName === void 0 && isRecord2(msgObj.message)) {
902
703
  modelName = getString(msgObj.message, "model");
903
704
  }
904
705
  if (resultText !== void 0) continue;
905
706
  let content = msgObj.content;
906
- if (content === void 0 && isRecord4(msgObj.message)) {
707
+ if (content === void 0 && isRecord2(msgObj.message)) {
907
708
  content = msgObj.message.content;
908
709
  }
909
710
  if (typeof content === "string") {
910
711
  resultText = content;
911
712
  } else if (Array.isArray(content)) {
912
713
  for (const block of content) {
913
- if (isRecord4(block) && block.type === "text" && typeof block.text === "string") {
714
+ if (isRecord2(block) && block.type === "text" && typeof block.text === "string") {
914
715
  resultText = block.text;
915
716
  }
916
717
  }
@@ -956,6 +757,7 @@ __export(codex_exports, {
956
757
  var CodexProvider;
957
758
  var init_codex = __esm({
958
759
  "src/harness/providers/codex.ts"() {
760
+ init_base();
959
761
  init_types();
960
762
  init_cli();
961
763
  init_modelVariant();
@@ -966,8 +768,9 @@ var init_codex = __esm({
966
768
  }
967
769
  async execute(prompt, options) {
968
770
  const cmd = [this.bin, "exec", "--json"];
969
- if (options.cwd) {
970
- cmd.push("-C", String(options.cwd));
771
+ const root = resolveRoot(options);
772
+ if (root) {
773
+ cmd.push("-C", root);
971
774
  }
972
775
  if (options.permissionMode === "auto") {
973
776
  cmd.push("--full-auto");
@@ -984,7 +787,7 @@ var init_codex = __esm({
984
787
  try {
985
788
  const { stdout, stderr, exitCode } = await runCli(cmd, {
986
789
  env: options.env,
987
- cwd: options.cwd
790
+ cwd: root
988
791
  });
989
792
  const events = parseJsonl(stdout);
990
793
  const resultText = extractFinalText(events);
@@ -1037,6 +840,7 @@ __export(gemini_exports, {
1037
840
  var GeminiProvider;
1038
841
  var init_gemini = __esm({
1039
842
  "src/harness/providers/gemini.ts"() {
843
+ init_base();
1040
844
  init_types();
1041
845
  init_cli();
1042
846
  init_modelVariant();
@@ -1061,7 +865,7 @@ var init_gemini = __esm({
1061
865
  try {
1062
866
  const { stdout, stderr, exitCode } = await runCli(cmd, {
1063
867
  env: options.env,
1064
- cwd: options.cwd
868
+ cwd: resolveRoot(options)
1065
869
  });
1066
870
  const resultText = stdout.trim() || void 0;
1067
871
  const isError = exitCode !== 0 && !resultText;
@@ -1113,6 +917,7 @@ function extractOpenCodeError(stderr) {
1113
917
  var ANSI_PATTERN2, STDERR_ERROR_PATTERNS, OpenCodeProvider;
1114
918
  var init_opencode = __esm({
1115
919
  "src/harness/providers/opencode.ts"() {
920
+ init_base();
1116
921
  init_types();
1117
922
  init_cli();
1118
923
  init_modelVariant();
@@ -1132,10 +937,9 @@ var init_opencode = __esm({
1132
937
  }
1133
938
  async execute(prompt, options) {
1134
939
  const cmd = [this.bin, "run"];
1135
- if (options.cwd && typeof options.cwd === "string") {
1136
- cmd.push("--dir", options.cwd);
1137
- } else if (options.project_dir && typeof options.project_dir === "string") {
1138
- cmd.push("--dir", options.project_dir);
940
+ const root = resolveRoot(options);
941
+ if (root) {
942
+ cmd.push("--dir", root);
1139
943
  }
1140
944
  const env = { ...options.env };
1141
945
  const { model: modelValue, variant: variantValue } = resolveModelAndVariant(options);
@@ -1221,6 +1025,229 @@ ${prompt}`;
1221
1025
  }
1222
1026
  });
1223
1027
 
1028
+ // src/harness/providers/pi.ts
1029
+ var pi_exports = {};
1030
+ __export(pi_exports, {
1031
+ OMPProvider: () => OMPProvider,
1032
+ PiProvider: () => PiProvider
1033
+ });
1034
+ function normalizeTools(tools, flavor) {
1035
+ const normalized = [];
1036
+ for (const tool2 of tools) {
1037
+ let name = String(tool2).trim().toLowerCase();
1038
+ if (!name) {
1039
+ continue;
1040
+ }
1041
+ if (name === "glob") {
1042
+ name = flavor === "omp" ? "glob" : "find";
1043
+ }
1044
+ if (!normalized.includes(name)) {
1045
+ normalized.push(name);
1046
+ }
1047
+ }
1048
+ return normalized;
1049
+ }
1050
+ function numberValue(value) {
1051
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
1052
+ }
1053
+ function textContent(message) {
1054
+ if (typeof message.content === "string") {
1055
+ return message.content || void 0;
1056
+ }
1057
+ if (!Array.isArray(message.content)) {
1058
+ return void 0;
1059
+ }
1060
+ const text2 = message.content.filter((part) => typeof part === "object" && part !== null).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
1061
+ return text2 || void 0;
1062
+ }
1063
+ function parsePiEvents(events, configuredModel) {
1064
+ let result;
1065
+ let sessionId = "";
1066
+ let numTurns = 0;
1067
+ let inputTokens = 0;
1068
+ let outputTokens = 0;
1069
+ let cacheReadTokens = 0;
1070
+ let cacheCreationTokens = 0;
1071
+ let totalCostUsd;
1072
+ let reportedModel;
1073
+ let providerError;
1074
+ for (const event of events) {
1075
+ if (event.type === "session" && typeof event.id === "string") {
1076
+ sessionId = event.id;
1077
+ }
1078
+ if (event.type === "turn_end") {
1079
+ numTurns += 1;
1080
+ }
1081
+ if (event.type !== "message_end" || typeof event.message !== "object" || event.message === null) {
1082
+ continue;
1083
+ }
1084
+ const message = event.message;
1085
+ if (message.role !== "assistant") {
1086
+ continue;
1087
+ }
1088
+ result = textContent(message) ?? result;
1089
+ if (typeof message.model === "string") {
1090
+ reportedModel = message.model;
1091
+ }
1092
+ if (typeof message.usage === "object" && message.usage !== null) {
1093
+ const usage = message.usage;
1094
+ inputTokens += numberValue(usage.input);
1095
+ outputTokens += numberValue(usage.output);
1096
+ cacheReadTokens += numberValue(usage.cacheRead);
1097
+ cacheCreationTokens += numberValue(usage.cacheWrite);
1098
+ if (typeof usage.cost === "object" && usage.cost !== null) {
1099
+ const cost = usage.cost.total;
1100
+ if (typeof cost === "number" && Number.isFinite(cost)) {
1101
+ totalCostUsd = (totalCostUsd ?? 0) + cost;
1102
+ }
1103
+ }
1104
+ }
1105
+ if (message.stopReason === "error" || message.stopReason === "aborted") {
1106
+ providerError = String(
1107
+ message.errorMessage ?? message.error ?? `Pi stopped with reason ${String(message.stopReason)}.`
1108
+ );
1109
+ } else {
1110
+ providerError = void 0;
1111
+ }
1112
+ }
1113
+ if (numTurns === 0 && result) {
1114
+ numTurns = 1;
1115
+ }
1116
+ return {
1117
+ result,
1118
+ providerError,
1119
+ metrics: createMetrics({
1120
+ numTurns,
1121
+ totalCostUsd,
1122
+ sessionId,
1123
+ inputTokens,
1124
+ outputTokens,
1125
+ cacheReadTokens,
1126
+ cacheCreationTokens,
1127
+ totalTokens: inputTokens + outputTokens,
1128
+ model: configuredModel ?? reportedModel
1129
+ })
1130
+ };
1131
+ }
1132
+ var READ_ONLY_TOOLS, ANSI_PATTERN3, PiFamilyProvider, PiProvider, OMPProvider;
1133
+ var init_pi = __esm({
1134
+ "src/harness/providers/pi.ts"() {
1135
+ init_base();
1136
+ init_types();
1137
+ init_cli();
1138
+ init_modelVariant();
1139
+ READ_ONLY_TOOLS = /* @__PURE__ */ new Set(["read", "grep", "find", "glob", "ls", "lsp"]);
1140
+ ANSI_PATTERN3 = /\x1B\[[0-?]*[ -/]*[@-~]/g;
1141
+ PiFamilyProvider = class {
1142
+ constructor(flavor, bin) {
1143
+ this.flavor = flavor;
1144
+ this.bin = bin;
1145
+ }
1146
+ flavor;
1147
+ bin;
1148
+ async execute(prompt, options) {
1149
+ const cmd = [this.bin, "--print", "--mode", "json"];
1150
+ const root = resolveRoot(options);
1151
+ if (this.flavor === "omp" && root) {
1152
+ cmd.push("--cwd", root);
1153
+ }
1154
+ const { model, variant } = resolveModelAndVariant(options);
1155
+ if (model) {
1156
+ cmd.push("--model", model);
1157
+ }
1158
+ if (variant) {
1159
+ cmd.push("--thinking", variant);
1160
+ }
1161
+ if (typeof options.systemPrompt === "string" && options.systemPrompt.trim()) {
1162
+ cmd.push("--system-prompt", options.systemPrompt.trim());
1163
+ }
1164
+ if (typeof options.resumeSessionId === "string" && options.resumeSessionId) {
1165
+ cmd.push(this.flavor === "omp" ? "--resume" : "--session", options.resumeSessionId);
1166
+ }
1167
+ if (options.permissionMode === "auto") {
1168
+ if (this.flavor === "omp") {
1169
+ cmd.push("--auto-approve");
1170
+ }
1171
+ }
1172
+ const explicitTools = Array.isArray(options.tools);
1173
+ let tools = explicitTools ? normalizeTools(options.tools, this.flavor) : [];
1174
+ if (options.permissionMode === "plan") {
1175
+ tools = tools.filter((tool2) => READ_ONLY_TOOLS.has(tool2));
1176
+ if (tools.length === 0) {
1177
+ tools = ["read", "grep", this.flavor === "omp" ? "glob" : "find"];
1178
+ }
1179
+ }
1180
+ if (explicitTools || options.permissionMode === "plan") {
1181
+ if (tools.length > 0) {
1182
+ cmd.push("--tools", tools.join(","));
1183
+ } else {
1184
+ cmd.push("--no-tools");
1185
+ }
1186
+ }
1187
+ const env = { ...options.env };
1188
+ const startApi = Date.now();
1189
+ try {
1190
+ const { stdout, stderr, exitCode } = await runCli(cmd, {
1191
+ env,
1192
+ cwd: root,
1193
+ inputText: prompt,
1194
+ timeout: typeof options.timeout === "number" ? options.timeout * 1e3 : void 0
1195
+ });
1196
+ const events = parseJsonl(stdout);
1197
+ const parsed = parsePiEvents(events, model);
1198
+ parsed.metrics.durationApiMs = Date.now() - startApi;
1199
+ const cleanStderr = stderr.trim().replace(ANSI_PATTERN3, "").slice(0, 1e3);
1200
+ let errorMessage;
1201
+ let failureType;
1202
+ if (exitCode < 0) {
1203
+ errorMessage = `Process killed by signal ${-exitCode}.`;
1204
+ failureType = "crash";
1205
+ } else if (exitCode !== 0) {
1206
+ errorMessage = cleanStderr || parsed.providerError || `Process exited with code ${exitCode}.`;
1207
+ failureType = "crash";
1208
+ } else if (parsed.providerError) {
1209
+ errorMessage = parsed.providerError;
1210
+ failureType = "api_error";
1211
+ } else if (!parsed.result) {
1212
+ errorMessage = cleanStderr || `${this.flavor} exited successfully without an assistant response.`;
1213
+ failureType = "no_output";
1214
+ } else {
1215
+ failureType = "none";
1216
+ }
1217
+ return createRawResult({
1218
+ result: parsed.result,
1219
+ messages: events,
1220
+ metrics: parsed.metrics,
1221
+ isError: failureType !== "none",
1222
+ errorMessage,
1223
+ failureType,
1224
+ returnCode: exitCode
1225
+ });
1226
+ } catch (error) {
1227
+ const message = error instanceof Error ? error.message : String(error);
1228
+ const binaryMissing = message.includes("ENOENT");
1229
+ return createRawResult({
1230
+ isError: true,
1231
+ errorMessage: binaryMissing ? `${this.flavor === "omp" ? "OMP" : "Pi"} binary not found at '${this.bin}'. ${this.flavor === "omp" ? "Install: curl -fsSL https://omp.sh/install | sh" : "Install: npm install -g --ignore-scripts @earendil-works/pi-coding-agent"}` : message,
1232
+ failureType: /timed out|deadline exceeded|no progress/i.test(message) ? "timeout" : "crash",
1233
+ metrics: createMetrics({ durationApiMs: Date.now() - startApi })
1234
+ });
1235
+ }
1236
+ }
1237
+ };
1238
+ PiProvider = class extends PiFamilyProvider {
1239
+ constructor(binPath = "pi") {
1240
+ super("pi", binPath);
1241
+ }
1242
+ };
1243
+ OMPProvider = class extends PiFamilyProvider {
1244
+ constructor(binPath = "omp") {
1245
+ super("omp", binPath);
1246
+ }
1247
+ };
1248
+ }
1249
+ });
1250
+
1224
1251
  // src/harness/providers/factory.ts
1225
1252
  function resolveProviderName(explicit) {
1226
1253
  const explicitName = explicit?.trim();
@@ -1257,125 +1284,362 @@ async function buildProvider(config) {
1257
1284
  const { OpenCodeProvider: OpenCodeProvider2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
1258
1285
  return new OpenCodeProvider2(config.opencodeBin ?? "opencode");
1259
1286
  }
1287
+ if (provider === "pi") {
1288
+ const { PiProvider: PiProvider2 } = await Promise.resolve().then(() => (init_pi(), pi_exports));
1289
+ return new PiProvider2(config.piBin ?? "pi");
1290
+ }
1291
+ if (provider === "omp") {
1292
+ const { OMPProvider: OMPProvider2 } = await Promise.resolve().then(() => (init_pi(), pi_exports));
1293
+ return new OMPProvider2(config.ompBin ?? "omp");
1294
+ }
1260
1295
  throw new Error(`Provider "${provider}" is not yet implemented.`);
1261
1296
  }
1262
1297
  var SUPPORTED_PROVIDERS, DEFAULT_HARNESS_PROVIDER, HARNESS_PROVIDER_ENV_VAR;
1263
1298
  var init_factory = __esm({
1264
1299
  "src/harness/providers/factory.ts"() {
1265
- SUPPORTED_PROVIDERS = /* @__PURE__ */ new Set(["aforge", "claude-code", "codex", "gemini", "opencode"]);
1300
+ SUPPORTED_PROVIDERS = /* @__PURE__ */ new Set([
1301
+ "aforge",
1302
+ "claude-code",
1303
+ "codex",
1304
+ "gemini",
1305
+ "omp",
1306
+ "opencode",
1307
+ "pi"
1308
+ ]);
1266
1309
  DEFAULT_HARNESS_PROVIDER = "aforge";
1267
1310
  HARNESS_PROVIDER_ENV_VAR = "AGENTFIELD_HARNESS_PROVIDER";
1268
1311
  }
1269
1312
  });
1270
-
1271
- // src/harness/runner.ts
1272
- var runner_exports = {};
1273
- __export(runner_exports, {
1274
- HarnessRunner: () => HarnessRunner
1275
- });
1276
- function tokenMetrics(raw) {
1277
- const { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, model } = raw.metrics;
1278
- return { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, model };
1313
+ function isRecord3(value) {
1314
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1279
1315
  }
1280
- var TRANSIENT_PATTERNS, HarnessRunner;
1281
- var init_runner = __esm({
1282
- "src/harness/runner.ts"() {
1283
- init_schema();
1284
- init_factory();
1285
- init_types();
1286
- TRANSIENT_PATTERNS = [
1287
- "rate limit",
1288
- "rate_limit",
1289
- "overloaded",
1290
- "timeout",
1291
- "timed out",
1292
- "connection reset",
1293
- "connection refused",
1294
- "temporarily unavailable",
1295
- "service unavailable",
1296
- "503",
1297
- "502",
1298
- "504",
1299
- "internal server error",
1300
- "500"
1301
- ];
1302
- HarnessRunner = class {
1303
- constructor(config) {
1304
- this.config = config;
1305
- }
1306
- config;
1307
- async run(prompt, options = {}) {
1308
- const { schema, ...rest } = options;
1309
- const resolved = this.resolveOptions(this.config, rest);
1310
- resolved.provider = resolveProviderName(resolved.provider);
1311
- const provider = await this.buildProvider(resolved.provider, resolved);
1312
- const cwd = resolved.cwd ?? ".";
1313
- const outputRoot = resolved.projectDir ?? cwd;
1314
- let outputDir;
1315
- if (schema !== void 0) {
1316
- fs.mkdirSync(outputRoot, { recursive: true });
1317
- outputDir = fs.mkdtempSync(path4__default.join(outputRoot, ".agentfield-out-"));
1318
- }
1319
- const effectivePrompt = schema === void 0 ? prompt : `${prompt}${buildPromptSuffix(schema, outputDir)}`;
1320
- const startTime = Date.now();
1321
- try {
1322
- const raw = await this.executeWithRetry(provider, effectivePrompt, resolved);
1323
- if (schema !== void 0) {
1324
- return this.handleSchemaOutput(raw, schema, outputDir, startTime);
1325
- }
1326
- return createHarnessResult({
1327
- result: raw.result,
1328
- isError: raw.isError,
1329
- errorMessage: raw.errorMessage,
1330
- failureType: raw.failureType,
1331
- returnCode: raw.returnCode,
1332
- costUsd: raw.metrics.totalCostUsd,
1333
- numTurns: raw.metrics.numTurns,
1334
- durationMs: Date.now() - startTime,
1335
- sessionId: raw.metrics.sessionId,
1336
- messages: raw.messages,
1337
- ...tokenMetrics(raw)
1338
- });
1339
- } finally {
1340
- if (schema !== void 0) {
1341
- cleanupTempFiles(outputDir);
1342
- fs.rmSync(outputDir, { recursive: true, force: true });
1343
- }
1316
+ function isZod4Schema(value) {
1317
+ if (!isRecord3(value) || !("_zod" in value) || !isRecord3(value._zod)) {
1318
+ return false;
1319
+ }
1320
+ return isRecord3(value._zod.def);
1321
+ }
1322
+ function getZod4Converter() {
1323
+ if (zod4Converter !== void 0) {
1324
+ return zod4Converter;
1325
+ }
1326
+ const requires = [];
1327
+ try {
1328
+ requires.push(createRequire(path4__default.join(process.cwd(), "package.json")));
1329
+ } catch {
1330
+ }
1331
+ requires.push(createRequire(import.meta.url));
1332
+ for (const req of requires) {
1333
+ for (const moduleName of ["zod", "zod/v4"]) {
1334
+ try {
1335
+ const mod = req(moduleName);
1336
+ if (typeof mod.toJSONSchema === "function") {
1337
+ zod4Converter = mod.toJSONSchema;
1338
+ return zod4Converter;
1344
1339
  }
1340
+ } catch {
1345
1341
  }
1346
- resolveOptions(config, overrides) {
1347
- const out = {};
1348
- if (config) {
1349
- for (const key of [
1350
- "provider",
1351
- "model",
1352
- "variant",
1353
- "maxTurns",
1354
- "maxBudgetUsd",
1355
- "maxRetries",
1356
- "initialDelay",
1357
- "maxDelay",
1358
- "backoffFactor",
1359
- "tools",
1360
- "permissionMode",
1361
- "systemPrompt",
1362
- "env",
1363
- "cwd",
1364
- "projectDir",
1365
- "aforgeBin",
1366
- "codexBin",
1367
- "geminiBin",
1368
- "opencodeBin"
1369
- ]) {
1370
- const value = config[key];
1371
- if (value !== void 0 && value !== null) {
1372
- out[key] = value;
1373
- }
1374
- }
1375
- }
1376
- for (const [key, value] of Object.entries(overrides)) {
1377
- if (value !== void 0 && value !== null) {
1378
- out[key] = value;
1342
+ }
1343
+ }
1344
+ zod4Converter = null;
1345
+ return zod4Converter;
1346
+ }
1347
+ function zod4ToJsonSchema(schema) {
1348
+ const converter = getZod4Converter();
1349
+ if (converter === null) {
1350
+ throw new TypeError(
1351
+ 'Cannot convert a Zod 4 schema: install the "zod" package with its "zod/v4" entry point available.'
1352
+ );
1353
+ }
1354
+ return converter(schema);
1355
+ }
1356
+ var zod4Converter;
1357
+ var init_zod_schema = __esm({
1358
+ "src/utils/zod-schema.ts"() {
1359
+ }
1360
+ });
1361
+ function getZodConverter() {
1362
+ if (zodConverter !== void 0) {
1363
+ return zodConverter;
1364
+ }
1365
+ try {
1366
+ const require2 = createRequire(import.meta.url);
1367
+ const mod = require2("zod-to-json-schema");
1368
+ zodConverter = mod.zodToJsonSchema ?? mod.default ?? null;
1369
+ } catch {
1370
+ zodConverter = null;
1371
+ }
1372
+ return zodConverter;
1373
+ }
1374
+ function isRecord4(value) {
1375
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1376
+ }
1377
+ function hasJsonSchema(value) {
1378
+ return isRecord4(value) && typeof value.jsonSchema === "function";
1379
+ }
1380
+ function hasParse(value) {
1381
+ return isRecord4(value) && typeof value.parse === "function";
1382
+ }
1383
+ function estimateTokens(text2) {
1384
+ return Math.floor(text2.length / 4);
1385
+ }
1386
+ function writeSchemaFile(schemaJson, cwd) {
1387
+ const filePath = getSchemaPath(cwd);
1388
+ fs.mkdirSync(path4__default.dirname(filePath), { recursive: true });
1389
+ const fd = fs.openSync(filePath, "w", 384);
1390
+ try {
1391
+ fs.writeFileSync(fd, schemaJson, "utf8");
1392
+ } finally {
1393
+ fs.closeSync(fd);
1394
+ }
1395
+ return filePath;
1396
+ }
1397
+ function validateAgainstSchema(data, schema) {
1398
+ if (hasParse(schema)) {
1399
+ return schema.parse(data);
1400
+ }
1401
+ return data;
1402
+ }
1403
+ function getOutputPath(cwd) {
1404
+ return path4__default.join(cwd, OUTPUT_FILENAME);
1405
+ }
1406
+ function getSchemaPath(cwd) {
1407
+ return path4__default.join(cwd, SCHEMA_FILENAME);
1408
+ }
1409
+ function schemaToJsonSchema(schema) {
1410
+ if (isZod4Schema(schema)) {
1411
+ return zod4ToJsonSchema(schema);
1412
+ }
1413
+ if (isRecord4(schema)) {
1414
+ if ("type" in schema || "properties" in schema || "$schema" in schema) {
1415
+ return schema;
1416
+ }
1417
+ if (hasJsonSchema(schema)) {
1418
+ return schema.jsonSchema();
1419
+ }
1420
+ }
1421
+ const converter = getZodConverter();
1422
+ if (converter !== null) {
1423
+ return converter(schema);
1424
+ }
1425
+ throw new TypeError(
1426
+ 'Unsupported schema type. Expected a Zod schema (requires "zod-to-json-schema" for Zod 3 or "zod" for Zod 4), JSON schema object, or jsonSchema() provider.'
1427
+ );
1428
+ }
1429
+ function isLargeSchema(schemaJson) {
1430
+ return estimateTokens(schemaJson) > LARGE_SCHEMA_TOKEN_THRESHOLD;
1431
+ }
1432
+ function buildPromptSuffix(schema, cwd) {
1433
+ const jsonSchema2 = schemaToJsonSchema(schema);
1434
+ const schemaJson = JSON.stringify(jsonSchema2, null, 2);
1435
+ const outputPath = getOutputPath(cwd);
1436
+ if (isLargeSchema(schemaJson)) {
1437
+ const schemaPath = writeSchemaFile(schemaJson, cwd);
1438
+ return `
1439
+
1440
+ ---
1441
+ OUTPUT REQUIREMENTS:
1442
+ Read the JSON Schema at: ${schemaPath}
1443
+ Write your final answer as valid JSON conforming to that schema to: ${outputPath}
1444
+ Do not include any text outside the JSON in that file. Do not wrap in markdown fences.`;
1445
+ }
1446
+ return `
1447
+
1448
+ ---
1449
+ OUTPUT REQUIREMENTS:
1450
+ Write your final answer as valid JSON to the file: ${outputPath}
1451
+ The JSON must conform to this schema:
1452
+ ${schemaJson}
1453
+ Do not include any text outside the JSON in that file. Do not wrap in markdown fences.`;
1454
+ }
1455
+ function cosmeticRepair(raw) {
1456
+ let text2 = raw.trim();
1457
+ const fenceMatch = text2.match(/^```(?:json)?\s*\n([\s\S]*?)```\s*$/);
1458
+ if (fenceMatch) {
1459
+ text2 = fenceMatch[1].trim();
1460
+ }
1461
+ if (text2.length > 0 && text2[0] !== "{" && text2[0] !== "[") {
1462
+ const firstJsonCharIndex = [...text2].findIndex((char) => char === "{" || char === "[");
1463
+ if (firstJsonCharIndex >= 0) {
1464
+ text2 = text2.slice(firstJsonCharIndex);
1465
+ }
1466
+ }
1467
+ text2 = text2.replace(/,\s*([}\]])/g, "$1");
1468
+ const openBraces = (text2.match(/{/g)?.length ?? 0) - (text2.match(/}/g)?.length ?? 0);
1469
+ const openBrackets = (text2.match(/\[/g)?.length ?? 0) - (text2.match(/\]/g)?.length ?? 0);
1470
+ if (openBraces > 0 || openBrackets > 0) {
1471
+ text2 += "]".repeat(openBrackets) + "}".repeat(openBraces);
1472
+ }
1473
+ return text2;
1474
+ }
1475
+ function readAndParse(filePath) {
1476
+ try {
1477
+ const content = fs.readFileSync(filePath, "utf8");
1478
+ if (content.trim().length === 0) {
1479
+ return null;
1480
+ }
1481
+ return JSON.parse(content);
1482
+ } catch {
1483
+ return null;
1484
+ }
1485
+ }
1486
+ function readRepairAndParse(filePath) {
1487
+ try {
1488
+ const content = fs.readFileSync(filePath, "utf8");
1489
+ if (content.trim().length === 0) {
1490
+ return null;
1491
+ }
1492
+ return JSON.parse(cosmeticRepair(content));
1493
+ } catch {
1494
+ return null;
1495
+ }
1496
+ }
1497
+ function parseAndValidate(filePath, schema) {
1498
+ const parsed = readAndParse(filePath);
1499
+ if (parsed !== null) {
1500
+ try {
1501
+ return validateAgainstSchema(parsed, schema);
1502
+ } catch {
1503
+ }
1504
+ }
1505
+ const repaired = readRepairAndParse(filePath);
1506
+ if (repaired !== null) {
1507
+ try {
1508
+ return validateAgainstSchema(repaired, schema);
1509
+ } catch {
1510
+ return null;
1511
+ }
1512
+ }
1513
+ return null;
1514
+ }
1515
+ function cleanupTempFiles(cwd) {
1516
+ for (const filename of [OUTPUT_FILENAME, SCHEMA_FILENAME]) {
1517
+ try {
1518
+ fs.unlinkSync(path4__default.join(cwd, filename));
1519
+ } catch {
1520
+ }
1521
+ }
1522
+ }
1523
+ var OUTPUT_FILENAME, SCHEMA_FILENAME, LARGE_SCHEMA_TOKEN_THRESHOLD, zodConverter;
1524
+ var init_schema = __esm({
1525
+ "src/harness/schema.ts"() {
1526
+ init_zod_schema();
1527
+ OUTPUT_FILENAME = ".agentfield_output.json";
1528
+ SCHEMA_FILENAME = ".agentfield_schema.json";
1529
+ LARGE_SCHEMA_TOKEN_THRESHOLD = 4e3;
1530
+ }
1531
+ });
1532
+
1533
+ // src/harness/runner.ts
1534
+ var runner_exports = {};
1535
+ __export(runner_exports, {
1536
+ HarnessRunner: () => HarnessRunner
1537
+ });
1538
+ function tokenMetrics(raw) {
1539
+ const { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, model } = raw.metrics;
1540
+ return { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, model };
1541
+ }
1542
+ var TRANSIENT_PATTERNS, HarnessRunner;
1543
+ var init_runner = __esm({
1544
+ "src/harness/runner.ts"() {
1545
+ init_schema();
1546
+ init_factory();
1547
+ init_base();
1548
+ init_types();
1549
+ TRANSIENT_PATTERNS = [
1550
+ "rate limit",
1551
+ "rate_limit",
1552
+ "overloaded",
1553
+ "timeout",
1554
+ "timed out",
1555
+ "connection reset",
1556
+ "connection refused",
1557
+ "temporarily unavailable",
1558
+ "service unavailable",
1559
+ "503",
1560
+ "502",
1561
+ "504",
1562
+ "internal server error",
1563
+ "500"
1564
+ ];
1565
+ HarnessRunner = class {
1566
+ constructor(config) {
1567
+ this.config = config;
1568
+ }
1569
+ config;
1570
+ async run(prompt, options = {}) {
1571
+ const { schema, ...rest } = options;
1572
+ const resolved = this.resolveOptions(this.config, rest);
1573
+ resolved.provider = resolveProviderName(resolved.provider);
1574
+ const provider = await this.buildProvider(resolved.provider, resolved);
1575
+ const outputRoot = resolveRoot(resolved) ?? ".";
1576
+ let outputDir;
1577
+ if (schema !== void 0) {
1578
+ fs.mkdirSync(outputRoot, { recursive: true });
1579
+ outputDir = fs.mkdtempSync(path4__default.join(outputRoot, ".agentfield-out-"));
1580
+ }
1581
+ const effectivePrompt = schema === void 0 ? prompt : `${prompt}${buildPromptSuffix(schema, outputDir)}`;
1582
+ const startTime = Date.now();
1583
+ try {
1584
+ const raw = await this.executeWithRetry(provider, effectivePrompt, resolved);
1585
+ if (schema !== void 0) {
1586
+ return this.handleSchemaOutput(raw, schema, outputDir, startTime);
1587
+ }
1588
+ return createHarnessResult({
1589
+ result: raw.result,
1590
+ isError: raw.isError,
1591
+ errorMessage: raw.errorMessage,
1592
+ failureType: raw.failureType,
1593
+ returnCode: raw.returnCode,
1594
+ costUsd: raw.metrics.totalCostUsd,
1595
+ numTurns: raw.metrics.numTurns,
1596
+ durationMs: Date.now() - startTime,
1597
+ sessionId: raw.metrics.sessionId,
1598
+ messages: raw.messages,
1599
+ ...tokenMetrics(raw)
1600
+ });
1601
+ } finally {
1602
+ if (schema !== void 0) {
1603
+ cleanupTempFiles(outputDir);
1604
+ fs.rmSync(outputDir, { recursive: true, force: true });
1605
+ }
1606
+ }
1607
+ }
1608
+ resolveOptions(config, overrides) {
1609
+ const out = {};
1610
+ if (config) {
1611
+ for (const key of [
1612
+ "provider",
1613
+ "model",
1614
+ "variant",
1615
+ "maxTurns",
1616
+ "maxBudgetUsd",
1617
+ "maxRetries",
1618
+ "initialDelay",
1619
+ "maxDelay",
1620
+ "backoffFactor",
1621
+ "tools",
1622
+ "permissionMode",
1623
+ "systemPrompt",
1624
+ "env",
1625
+ "cwd",
1626
+ "projectDir",
1627
+ "aforgeBin",
1628
+ "codexBin",
1629
+ "geminiBin",
1630
+ "opencodeBin",
1631
+ "piBin",
1632
+ "ompBin"
1633
+ ]) {
1634
+ const value = config[key];
1635
+ if (value !== void 0 && value !== null) {
1636
+ out[key] = value;
1637
+ }
1638
+ }
1639
+ }
1640
+ for (const [key, value] of Object.entries(overrides)) {
1641
+ if (value !== void 0 && value !== null) {
1642
+ out[key] = value;
1379
1643
  }
1380
1644
  }
1381
1645
  return out;
@@ -2882,110 +3146,398 @@ var StatelessRateLimiter = class {
2882
3146
  }
2883
3147
  return void 0;
2884
3148
  }
2885
- _createJitterRng(seed) {
2886
- let x = seed >>> 0;
2887
- return () => {
2888
- x = (1664525 * x + 1013904223) % 4294967296;
2889
- return x / 4294967296;
2890
- };
3149
+ _createJitterRng(seed) {
3150
+ let x = seed >>> 0;
3151
+ return () => {
3152
+ x = (1664525 * x + 1013904223) % 4294967296;
3153
+ return x / 4294967296;
3154
+ };
3155
+ }
3156
+ _calculateBackoffDelay(attempt, retryAfter) {
3157
+ let baseDelay;
3158
+ if (retryAfter && retryAfter <= this.maxDelay) {
3159
+ baseDelay = retryAfter;
3160
+ } else {
3161
+ baseDelay = Math.min(this.baseDelay * 2 ** attempt, this.maxDelay);
3162
+ }
3163
+ const jitterRange = baseDelay * this.jitterFactor;
3164
+ const rng = this._createJitterRng(this._containerSeed + attempt);
3165
+ const jitter = (rng() * 2 - 1) * jitterRange;
3166
+ const delay = Math.max(0.1, baseDelay + jitter);
3167
+ return delay;
3168
+ }
3169
+ _checkCircuitBreaker() {
3170
+ if (this._circuitOpenTime === void 0) {
3171
+ return false;
3172
+ }
3173
+ if (this._now() - this._circuitOpenTime > this.circuitBreakerTimeout) {
3174
+ this._circuitOpenTime = void 0;
3175
+ this._consecutiveFailures = 0;
3176
+ return false;
3177
+ }
3178
+ return true;
3179
+ }
3180
+ _updateCircuitBreaker(success) {
3181
+ if (success) {
3182
+ this._consecutiveFailures = 0;
3183
+ this._circuitOpenTime = void 0;
3184
+ return;
3185
+ }
3186
+ this._consecutiveFailures += 1;
3187
+ if (this._consecutiveFailures >= this.circuitBreakerThreshold && this._circuitOpenTime === void 0) {
3188
+ this._circuitOpenTime = this._now();
3189
+ }
3190
+ }
3191
+ async _sleep(delaySeconds) {
3192
+ await new Promise((resolve3) => setTimeout(resolve3, delaySeconds * 1e3));
3193
+ }
3194
+ _now() {
3195
+ return Date.now() / 1e3;
3196
+ }
3197
+ async executeWithRetry(fn) {
3198
+ if (this._checkCircuitBreaker()) {
3199
+ throw new RateLimitError(
3200
+ `Circuit breaker is open. Too many consecutive rate limit failures. Will retry after ${this.circuitBreakerTimeout} seconds.`
3201
+ );
3202
+ }
3203
+ let lastError;
3204
+ for (let attempt = 0; attempt <= this.maxRetries; attempt += 1) {
3205
+ try {
3206
+ const result = await fn();
3207
+ this._updateCircuitBreaker(true);
3208
+ return result;
3209
+ } catch (error) {
3210
+ lastError = error;
3211
+ if (!this._isRateLimitError(error)) {
3212
+ throw error;
3213
+ }
3214
+ this._updateCircuitBreaker(false);
3215
+ if (attempt >= this.maxRetries) {
3216
+ break;
3217
+ }
3218
+ const retryAfter = this._extractRetryAfter(error);
3219
+ const delay = this._calculateBackoffDelay(attempt, retryAfter);
3220
+ await this._sleep(delay);
3221
+ }
3222
+ }
3223
+ throw new RateLimitError(
3224
+ `Rate limit retries exhausted after ${this.maxRetries} attempts. Last error: ${String(lastError)}`,
3225
+ this._extractRetryAfter(lastError)
3226
+ );
3227
+ }
3228
+ };
3229
+ function toError(error) {
3230
+ if (error instanceof Error) return error;
3231
+ return new Error(String(error));
3232
+ }
3233
+
3234
+ // src/ai/AIClient.ts
3235
+ init_openrouterAttribution();
3236
+
3237
+ // src/ai/openrouterUsage.ts
3238
+ function withOpenRouterUsageInclude(baseFetch) {
3239
+ return (input, init) => {
3240
+ const impl = ((...args) => globalThis.fetch(...args));
3241
+ try {
3242
+ if (init && typeof init.body === "string") {
3243
+ const parsed = JSON.parse(init.body);
3244
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && parsed.usage === void 0) {
3245
+ parsed.usage = { include: true };
3246
+ return impl(input, { ...init, body: JSON.stringify(parsed) });
3247
+ }
3248
+ }
3249
+ } catch {
3250
+ }
3251
+ return impl(input, init);
3252
+ };
3253
+ }
3254
+ var IMAGE_MIME_TYPES = {
3255
+ ".jpg": "image/jpeg",
3256
+ ".jpeg": "image/jpeg",
3257
+ ".png": "image/png",
3258
+ ".gif": "image/gif",
3259
+ ".webp": "image/webp",
3260
+ ".bmp": "image/bmp"
3261
+ };
3262
+ var AUDIO_MIME_TYPES = {
3263
+ ".wav": "audio/wav",
3264
+ ".mp3": "audio/mpeg",
3265
+ ".flac": "audio/flac",
3266
+ ".ogg": "audio/ogg"
3267
+ };
3268
+ var VIDEO_MIME_TYPES = {
3269
+ ".mp4": "video/mp4",
3270
+ ".mpeg": "video/mpeg",
3271
+ ".mpg": "video/mpeg",
3272
+ ".mov": "video/quicktime",
3273
+ ".webm": "video/webm"
3274
+ };
3275
+ var Text = class {
3276
+ type = "text";
3277
+ text;
3278
+ constructor(text2) {
3279
+ this.text = text2;
3280
+ }
3281
+ };
3282
+ var Image = class _Image {
3283
+ type = "image_url";
3284
+ imageUrl;
3285
+ constructor(imageUrl) {
3286
+ this.imageUrl = imageUrl;
3287
+ }
3288
+ /**
3289
+ * Create Image from a local file by converting to base64 data URL.
3290
+ */
3291
+ static async fromFile(filePath, detail = "high") {
3292
+ const absolutePath = resolve(filePath);
3293
+ const buffer = await readFile(absolutePath);
3294
+ const base64Data = buffer.toString("base64");
3295
+ const ext = getExtension(absolutePath).toLowerCase();
3296
+ const mimeType = IMAGE_MIME_TYPES[ext] || "image/jpeg";
3297
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3298
+ return new _Image({ url: dataUrl, detail });
3299
+ }
3300
+ /**
3301
+ * Create Image from a URL.
3302
+ */
3303
+ static fromUrl(url, detail = "high") {
3304
+ return new _Image({ url, detail });
3305
+ }
3306
+ /**
3307
+ * Create Image from a buffer.
3308
+ */
3309
+ static async fromBuffer(buffer, mimeType = "image/jpeg", detail = "high") {
3310
+ const base64Data = Buffer.from(buffer).toString("base64");
3311
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3312
+ return new _Image({ url: dataUrl, detail });
3313
+ }
3314
+ /**
3315
+ * Create Image from a base64 string.
3316
+ */
3317
+ static async fromBase64(base64Data, mimeType = "image/jpeg", detail = "high") {
3318
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3319
+ return new _Image({ url: dataUrl, detail });
3320
+ }
3321
+ };
3322
+ var Audio = class _Audio {
3323
+ type = "input_audio";
3324
+ audio;
3325
+ constructor(audio) {
3326
+ this.audio = audio;
3327
+ }
3328
+ /**
3329
+ * Create Audio from a local file by converting to base64.
3330
+ */
3331
+ static async fromFile(filePath, format) {
3332
+ const absolutePath = resolve(filePath);
3333
+ const ext = getExtension(absolutePath).toLowerCase().replace(".", "");
3334
+ const audioFormat = format || (["wav", "mp3", "flac", "ogg"].includes(ext) ? ext : "wav");
3335
+ const buffer = await readFile(absolutePath);
3336
+ const base64Data = buffer.toString("base64");
3337
+ return new _Audio({ data: base64Data, format: audioFormat });
3338
+ }
3339
+ /**
3340
+ * Create Audio from a URL (downloads and converts to base64).
3341
+ */
3342
+ static async fromUrl(url, format = "wav") {
3343
+ try {
3344
+ const response = await fetch(url);
3345
+ if (!response.ok) {
3346
+ throw new Error(`Failed to fetch audio from URL: ${response.status} ${response.statusText}`);
3347
+ }
3348
+ const arrayBuffer = await response.arrayBuffer();
3349
+ const base64Data = Buffer.from(arrayBuffer).toString("base64");
3350
+ return new _Audio({ data: base64Data, format });
3351
+ } catch (error) {
3352
+ if (error instanceof TypeError && error.message.includes("fetch")) {
3353
+ throw new Error("URL download requires a fetch-compatible environment");
3354
+ }
3355
+ throw error;
3356
+ }
3357
+ }
3358
+ /**
3359
+ * Create Audio from a buffer.
3360
+ */
3361
+ static async fromBuffer(buffer, format = "wav") {
3362
+ const base64Data = Buffer.from(buffer).toString("base64");
3363
+ return new _Audio({ data: base64Data, format });
3364
+ }
3365
+ /**
3366
+ * Create Audio from a base64 string.
3367
+ */
3368
+ static async fromBase64(base64Data, format = "wav") {
3369
+ return new _Audio({ data: base64Data, format });
3370
+ }
3371
+ };
3372
+ var Video = class _Video {
3373
+ type = "video_url";
3374
+ videoUrl;
3375
+ constructor(videoUrl) {
3376
+ this.videoUrl = videoUrl;
2891
3377
  }
2892
- _calculateBackoffDelay(attempt, retryAfter) {
2893
- let baseDelay;
2894
- if (retryAfter && retryAfter <= this.maxDelay) {
2895
- baseDelay = retryAfter;
2896
- } else {
2897
- baseDelay = Math.min(this.baseDelay * 2 ** attempt, this.maxDelay);
2898
- }
2899
- const jitterRange = baseDelay * this.jitterFactor;
2900
- const rng = this._createJitterRng(this._containerSeed + attempt);
2901
- const jitter = (rng() * 2 - 1) * jitterRange;
2902
- const delay = Math.max(0.1, baseDelay + jitter);
2903
- return delay;
3378
+ /**
3379
+ * Create Video from a local file by converting to a base64 data URL.
3380
+ */
3381
+ static async fromFile(filePath) {
3382
+ const absolutePath = resolve(filePath);
3383
+ const buffer = await readFile(absolutePath);
3384
+ const base64Data = buffer.toString("base64");
3385
+ const ext = getExtension(absolutePath).toLowerCase();
3386
+ const mimeType = VIDEO_MIME_TYPES[ext] || "video/mp4";
3387
+ return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
2904
3388
  }
2905
- _checkCircuitBreaker() {
2906
- if (this._circuitOpenTime === void 0) {
2907
- return false;
2908
- }
2909
- if (this._now() - this._circuitOpenTime > this.circuitBreakerTimeout) {
2910
- this._circuitOpenTime = void 0;
2911
- this._consecutiveFailures = 0;
2912
- return false;
2913
- }
2914
- return true;
3389
+ /**
3390
+ * Create Video from a URL.
3391
+ */
3392
+ static fromUrl(url) {
3393
+ return new _Video({ url });
2915
3394
  }
2916
- _updateCircuitBreaker(success) {
2917
- if (success) {
2918
- this._consecutiveFailures = 0;
2919
- this._circuitOpenTime = void 0;
2920
- return;
2921
- }
2922
- this._consecutiveFailures += 1;
2923
- if (this._consecutiveFailures >= this.circuitBreakerThreshold && this._circuitOpenTime === void 0) {
2924
- this._circuitOpenTime = this._now();
2925
- }
3395
+ /**
3396
+ * Create Video from a buffer.
3397
+ */
3398
+ static async fromBuffer(buffer, mimeType = "video/mp4") {
3399
+ const base64Data = Buffer.from(buffer).toString("base64");
3400
+ return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
2926
3401
  }
2927
- async _sleep(delaySeconds) {
2928
- await new Promise((resolve3) => setTimeout(resolve3, delaySeconds * 1e3));
3402
+ /**
3403
+ * Create Video from a base64 string.
3404
+ */
3405
+ static async fromBase64(base64Data, mimeType = "video/mp4") {
3406
+ return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
2929
3407
  }
2930
- _now() {
2931
- return Date.now() / 1e3;
3408
+ };
3409
+ var File = class _File {
3410
+ type = "file";
3411
+ file;
3412
+ constructor(file) {
3413
+ this.file = file;
2932
3414
  }
2933
- async executeWithRetry(fn) {
2934
- if (this._checkCircuitBreaker()) {
2935
- throw new RateLimitError(
2936
- `Circuit breaker is open. Too many consecutive rate limit failures. Will retry after ${this.circuitBreakerTimeout} seconds.`
2937
- );
2938
- }
2939
- let lastError;
2940
- for (let attempt = 0; attempt <= this.maxRetries; attempt += 1) {
2941
- try {
2942
- const result = await fn();
2943
- this._updateCircuitBreaker(true);
2944
- return result;
2945
- } catch (error) {
2946
- lastError = error;
2947
- if (!this._isRateLimitError(error)) {
2948
- throw error;
2949
- }
2950
- this._updateCircuitBreaker(false);
2951
- if (attempt >= this.maxRetries) {
2952
- break;
2953
- }
2954
- const retryAfter = this._extractRetryAfter(error);
2955
- const delay = this._calculateBackoffDelay(attempt, retryAfter);
2956
- await this._sleep(delay);
2957
- }
2958
- }
2959
- throw new RateLimitError(
2960
- `Rate limit retries exhausted after ${this.maxRetries} attempts. Last error: ${String(lastError)}`,
2961
- this._extractRetryAfter(lastError)
2962
- );
3415
+ /**
3416
+ * Create File from a local file path.
3417
+ */
3418
+ static async fromFile(filePath, mimeType) {
3419
+ const absolutePath = resolve(filePath);
3420
+ const detectedMimeType = mimeType || guessMimeType(absolutePath) || "application/octet-stream";
3421
+ const buffer = await readFile(absolutePath);
3422
+ const base64Data = buffer.toString("base64");
3423
+ const dataUrl = `data:${detectedMimeType};base64,${base64Data}`;
3424
+ return new _File({ url: dataUrl, mimeType: detectedMimeType });
3425
+ }
3426
+ /**
3427
+ * Create File from a URL.
3428
+ */
3429
+ static fromUrl(url, mimeType) {
3430
+ return new _File({ url, mimeType });
3431
+ }
3432
+ /**
3433
+ * Create File from a buffer.
3434
+ */
3435
+ static async fromBuffer(buffer, mimeType) {
3436
+ const base64Data = Buffer.from(buffer).toString("base64");
3437
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3438
+ return new _File({ url: dataUrl, mimeType });
3439
+ }
3440
+ /**
3441
+ * Create File from a base64 string.
3442
+ */
3443
+ static async fromBase64(base64Data, mimeType) {
3444
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3445
+ return new _File({ url: dataUrl, mimeType });
2963
3446
  }
2964
3447
  };
2965
- function toError(error) {
2966
- if (error instanceof Error) return error;
2967
- return new Error(String(error));
3448
+ function getExtension(filePath) {
3449
+ const lastDot = filePath.lastIndexOf(".");
3450
+ if (lastDot === -1) {
3451
+ return "";
3452
+ }
3453
+ return filePath.slice(lastDot);
2968
3454
  }
2969
-
2970
- // src/ai/AIClient.ts
2971
- init_openrouterAttribution();
2972
-
2973
- // src/ai/openrouterUsage.ts
2974
- function withOpenRouterUsageInclude(baseFetch) {
2975
- return (input, init) => {
2976
- const impl = ((...args) => globalThis.fetch(...args));
2977
- try {
2978
- if (init && typeof init.body === "string") {
2979
- const parsed = JSON.parse(init.body);
2980
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && parsed.usage === void 0) {
2981
- parsed.usage = { include: true };
2982
- return impl(input, { ...init, body: JSON.stringify(parsed) });
2983
- }
2984
- }
2985
- } catch {
2986
- }
2987
- return impl(input, init);
3455
+ function guessMimeType(filePath) {
3456
+ const ext = getExtension(filePath).toLowerCase();
3457
+ if (ext in IMAGE_MIME_TYPES) {
3458
+ return IMAGE_MIME_TYPES[ext];
3459
+ }
3460
+ if (ext in AUDIO_MIME_TYPES) {
3461
+ return AUDIO_MIME_TYPES[ext];
3462
+ }
3463
+ if (ext in VIDEO_MIME_TYPES) {
3464
+ return VIDEO_MIME_TYPES[ext];
3465
+ }
3466
+ const documentMimeTypes = {
3467
+ ".pdf": "application/pdf",
3468
+ ".doc": "application/msword",
3469
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
3470
+ ".xls": "application/vnd.ms-excel",
3471
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
3472
+ ".txt": "text/plain",
3473
+ ".csv": "text/csv",
3474
+ ".html": "text/html",
3475
+ ".json": "application/json",
3476
+ ".xml": "application/xml",
3477
+ ".zip": "application/zip"
2988
3478
  };
3479
+ return documentMimeTypes[ext] || null;
3480
+ }
3481
+ function getDataUrlMimeType(url) {
3482
+ const match = /^data:([^;,]+)(?:;[^,]*)?,/i.exec(url);
3483
+ return match?.[1] || null;
3484
+ }
3485
+ function guessUrlMimeType(url) {
3486
+ return getDataUrlMimeType(url) ?? guessMimeType(url.split(/[?#]/, 1)[0]);
3487
+ }
3488
+ function audioMediaType(format) {
3489
+ return AUDIO_MIME_TYPES[`.${format.toLowerCase()}`] ?? `audio/${format}`;
3490
+ }
3491
+ function text(content) {
3492
+ return new Text(content);
3493
+ }
3494
+ async function imageFromFile(filePath, detail = "high") {
3495
+ return Image.fromFile(filePath, detail);
3496
+ }
3497
+ function imageFromUrl(url, detail = "high") {
3498
+ return Image.fromUrl(url, detail);
3499
+ }
3500
+ async function imageFromBuffer(buffer, mimeType = "image/jpeg", detail = "high") {
3501
+ return Image.fromBuffer(buffer, mimeType, detail);
3502
+ }
3503
+ async function imageFromBase64(base64Data, mimeType, detail = "high") {
3504
+ return Image.fromBase64(base64Data, mimeType, detail);
3505
+ }
3506
+ async function audioFromFile(filePath, format) {
3507
+ return Audio.fromFile(filePath, format);
3508
+ }
3509
+ async function audioFromUrl(url, format = "wav") {
3510
+ return Audio.fromUrl(url, format);
3511
+ }
3512
+ async function audioFromBuffer(buffer, format = "wav") {
3513
+ return Audio.fromBuffer(buffer, format);
3514
+ }
3515
+ async function audioFromBase64(base64Data, format = "wav") {
3516
+ return Audio.fromBase64(base64Data, format);
3517
+ }
3518
+ async function videoFromFile(filePath) {
3519
+ return Video.fromFile(filePath);
3520
+ }
3521
+ function videoFromUrl(url) {
3522
+ return Video.fromUrl(url);
3523
+ }
3524
+ async function videoFromBuffer(buffer, mimeType = "video/mp4") {
3525
+ return Video.fromBuffer(buffer, mimeType);
3526
+ }
3527
+ async function videoFromBase64(base64Data, mimeType = "video/mp4") {
3528
+ return Video.fromBase64(base64Data, mimeType);
3529
+ }
3530
+ async function fileFromPath(filePath, mimeType) {
3531
+ return File.fromFile(filePath, mimeType);
3532
+ }
3533
+ function fileFromUrl(url, mimeType) {
3534
+ return File.fromUrl(url, mimeType);
3535
+ }
3536
+ async function fileFromBuffer(buffer, mimeType) {
3537
+ return File.fromBuffer(buffer, mimeType);
3538
+ }
3539
+ async function fileFromBase64(base64Data, mimeType) {
3540
+ return File.fromBase64(base64Data, mimeType);
2989
3541
  }
2990
3542
 
2991
3543
  // src/ai/AIClient.ts
@@ -3025,11 +3577,12 @@ var AIClient = class {
3025
3577
  async generate(prompt, options = {}) {
3026
3578
  const { provider, modelName } = this.resolveModelChoice(options);
3027
3579
  const model = this.buildModel(options);
3580
+ const requestPrompt = this.buildPrompt(prompt, options.content);
3028
3581
  if (options.schema) {
3029
3582
  const schema = options.schema;
3030
3583
  const call2 = async () => generateObject({
3031
3584
  model,
3032
- prompt,
3585
+ prompt: requestPrompt,
3033
3586
  output: "object",
3034
3587
  system: options.system,
3035
3588
  temperature: options.temperature ?? this.config.temperature,
@@ -3043,7 +3596,7 @@ var AIClient = class {
3043
3596
  }
3044
3597
  const call = async () => generateText({
3045
3598
  model,
3046
- prompt,
3599
+ prompt: requestPrompt,
3047
3600
  system: options.system,
3048
3601
  temperature: options.temperature ?? this.config.temperature,
3049
3602
  maxOutputTokens: options.maxTokens ?? this.config.maxTokens
@@ -3060,7 +3613,7 @@ var AIClient = class {
3060
3613
  const model = this.buildModel(options);
3061
3614
  const streamResult = streamText({
3062
3615
  model,
3063
- prompt,
3616
+ prompt: this.buildPrompt(prompt, options.content),
3064
3617
  system: options.system,
3065
3618
  temperature: options.temperature ?? this.config.temperature,
3066
3619
  maxOutputTokens: options.maxTokens ?? this.config.maxTokens
@@ -3186,6 +3739,40 @@ var AIClient = class {
3186
3739
  }
3187
3740
  }
3188
3741
  }
3742
+ buildPrompt(prompt, content) {
3743
+ if (!content?.length) return prompt;
3744
+ const messageContent = [
3745
+ { type: "text", text: prompt },
3746
+ ...content.map((part) => {
3747
+ if (part.type === "text") return { type: "text", text: part.text };
3748
+ if (part.type === "image_url") return { type: "image", image: part.imageUrl.url };
3749
+ if (part.type === "video_url") {
3750
+ return {
3751
+ type: "file",
3752
+ data: part.videoUrl.url,
3753
+ mediaType: guessUrlMimeType(part.videoUrl.url) ?? "video/mp4"
3754
+ };
3755
+ }
3756
+ if (part.type === "input_audio") {
3757
+ return {
3758
+ type: "file",
3759
+ data: part.audio.data,
3760
+ mediaType: audioMediaType(part.audio.format)
3761
+ };
3762
+ }
3763
+ return {
3764
+ type: "file",
3765
+ data: part.file.url,
3766
+ mediaType: part.file.mimeType ?? guessUrlMimeType(part.file.url) ?? "application/octet-stream"
3767
+ };
3768
+ })
3769
+ ];
3770
+ const messages = [{
3771
+ role: "user",
3772
+ content: messageContent
3773
+ }];
3774
+ return messages;
3775
+ }
3189
3776
  buildEmbeddingModel(options) {
3190
3777
  const provider = options.provider ?? this.config.provider ?? "openai";
3191
3778
  const modelName = options.model ?? this.config.embeddingModel ?? "text-embedding-3-small";
@@ -4114,6 +4701,7 @@ function wrapResult(result) {
4114
4701
  }
4115
4702
 
4116
4703
  // src/agent/Agent.ts
4704
+ init_factory();
4117
4705
  init_modelVariant();
4118
4706
  var MemoryClientBase = class {
4119
4707
  http;
@@ -5701,7 +6289,7 @@ var Agent = class {
5701
6289
  if (!inputTokens && !outputTokens && !cacheRead && !cacheCreation && !reportedTotal && cost === null) {
5702
6290
  return;
5703
6291
  }
5704
- const providerName = options?.provider ?? this.config.harnessConfig?.provider;
6292
+ const providerName = resolveProviderName(options?.provider ?? this.config.harnessConfig?.provider);
5705
6293
  const harnessName = providerName ? String(providerName).replace(/-/g, "_") : null;
5706
6294
  const rawModelName = String(
5707
6295
  result.model ?? options?.model ?? this.config.harnessConfig?.model ?? providerName ?? "harness"
@@ -7141,416 +7729,138 @@ var Agent = class {
7141
7729
  }
7142
7730
  });
7143
7731
  }
7144
- parseTarget(target) {
7145
- if (!target.includes(".")) {
7146
- return { name: target };
7147
- }
7148
- const [agentId, remainder] = target.split(".", 2);
7149
- const name = remainder.replace(":", "/");
7150
- return { agentId, name };
7151
- }
7152
- };
7153
-
7154
- // src/router/AgentRouter.ts
7155
- var AgentRouter = class {
7156
- prefix;
7157
- tags;
7158
- reasoners = [];
7159
- skills = [];
7160
- constructor(options = {}) {
7161
- this.prefix = options.prefix;
7162
- this.tags = options.tags;
7163
- }
7164
- reasoner(name, handler, options) {
7165
- const fullName = this.prefix ? `${sanitize(this.prefix)}_${name}` : name;
7166
- this.reasoners.push({ name: fullName, handler, options });
7167
- return this;
7168
- }
7169
- skill(name, handler, options) {
7170
- const fullName = this.prefix ? `${sanitize(this.prefix)}_${name}` : name;
7171
- this.skills.push({ name: fullName, handler, options });
7172
- return this;
7173
- }
7174
- };
7175
- function sanitize(value) {
7176
- return value.replace(/[^0-9a-zA-Z]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
7177
- }
7178
- var JWE_ALG = "ECDH-ES";
7179
- var JWE_ENC = "A256GCM";
7180
- var KEY_AGREEMENT_TYPE = "X25519KeyAgreementKey2020";
7181
- var PayloadEncryptionError = class extends Error {
7182
- constructor(message) {
7183
- super(message);
7184
- this.name = "PayloadEncryptionError";
7185
- }
7186
- };
7187
- var encoder = new TextEncoder();
7188
- function payloadToBytes(payload) {
7189
- if (payload instanceof Uint8Array) return payload;
7190
- if (typeof payload === "string") return encoder.encode(payload);
7191
- return encoder.encode(JSON.stringify(payload));
7192
- }
7193
- async function generateX25519KeyPair() {
7194
- const { privateKey, publicKey } = await generateKeyPair("ECDH-ES", {
7195
- crv: "X25519",
7196
- extractable: true
7197
- });
7198
- const privateJwk = await exportJWK(privateKey);
7199
- const publicJwk = await exportJWK(publicKey);
7200
- return { privateJwk, publicJwk };
7201
- }
7202
- function extractKeyAgreementJwk(didDocument) {
7203
- if (typeof didDocument !== "object" || didDocument === null) {
7204
- throw new PayloadEncryptionError("DID document must be an object");
7205
- }
7206
- const doc = didDocument["did_document"] ?? didDocument;
7207
- const flat = doc["key_agreement"];
7208
- if (flat && typeof flat === "object" && flat.crv === "X25519") {
7209
- return flat;
7210
- }
7211
- const keyAgreement = doc["keyAgreement"];
7212
- if (!keyAgreement || Array.isArray(keyAgreement) && keyAgreement.length === 0) {
7213
- throw new PayloadEncryptionError(
7214
- "DID document has no keyAgreement key; the agent has not published an X25519 encryption key"
7215
- );
7216
- }
7217
- const verificationMethods = /* @__PURE__ */ new Map();
7218
- for (const vm2 of doc["verificationMethod"] ?? []) {
7219
- if (vm2 && typeof vm2 === "object" && typeof vm2["id"] === "string") {
7220
- verificationMethods.set(vm2["id"], vm2);
7221
- }
7222
- }
7223
- const entry = Array.isArray(keyAgreement) ? keyAgreement[0] : keyAgreement;
7224
- let vm;
7225
- if (typeof entry === "string") {
7226
- vm = verificationMethods.get(entry);
7227
- if (!vm) {
7228
- throw new PayloadEncryptionError(
7229
- `keyAgreement references unknown verification method ${entry}`
7230
- );
7231
- }
7232
- } else if (entry && typeof entry === "object") {
7233
- vm = entry;
7234
- } else {
7235
- throw new PayloadEncryptionError("unsupported keyAgreement entry shape");
7236
- }
7237
- const jwk = vm["publicKeyJwk"];
7238
- if (!jwk || jwk.crv !== "X25519") {
7239
- throw new PayloadEncryptionError(
7240
- "keyAgreement verification method does not carry an X25519 publicKeyJwk"
7241
- );
7242
- }
7243
- return jwk;
7244
- }
7245
- async function encryptToJwk(publicJwk, payload) {
7246
- if (!publicJwk || publicJwk.crv !== "X25519") {
7247
- throw new PayloadEncryptionError("publicJwk must be an X25519 OKP JWK");
7248
- }
7249
- try {
7250
- const key = await importJWK(publicJwk, JWE_ALG);
7251
- return await new CompactEncrypt(payloadToBytes(payload)).setProtectedHeader({ alg: JWE_ALG, enc: JWE_ENC }).encrypt(key);
7252
- } catch (err) {
7253
- if (err instanceof PayloadEncryptionError) throw err;
7254
- throw new PayloadEncryptionError(`encryption failed: ${err.message}`);
7255
- }
7256
- }
7257
- async function encryptForDid(did, payload, resolver) {
7258
- const document = await resolver(did);
7259
- if (!document) {
7260
- throw new PayloadEncryptionError(`could not resolve DID ${did}`);
7261
- }
7262
- const publicJwk = extractKeyAgreementJwk(document);
7263
- return encryptToJwk(publicJwk, payload);
7264
- }
7265
- async function decrypt(token, privateJwk) {
7266
- try {
7267
- const key = await importJWK(privateJwk, JWE_ALG);
7268
- const { plaintext } = await compactDecrypt(token, key);
7269
- return Uint8Array.from(plaintext);
7270
- } catch (err) {
7271
- throw new PayloadEncryptionError(`decryption failed: ${err.message}`);
7272
- }
7273
- }
7274
- async function decryptToString(token, privateJwk) {
7275
- return new TextDecoder().decode(await decrypt(token, privateJwk));
7276
- }
7277
- var IMAGE_MIME_TYPES = {
7278
- ".jpg": "image/jpeg",
7279
- ".jpeg": "image/jpeg",
7280
- ".png": "image/png",
7281
- ".gif": "image/gif",
7282
- ".webp": "image/webp",
7283
- ".bmp": "image/bmp"
7284
- };
7285
- var AUDIO_MIME_TYPES = {
7286
- ".wav": "audio/wav",
7287
- ".mp3": "audio/mpeg",
7288
- ".flac": "audio/flac",
7289
- ".ogg": "audio/ogg"
7290
- };
7291
- var VIDEO_MIME_TYPES = {
7292
- ".mp4": "video/mp4",
7293
- ".mpeg": "video/mpeg",
7294
- ".mpg": "video/mpeg",
7295
- ".mov": "video/quicktime",
7296
- ".webm": "video/webm"
7297
- };
7298
- var Text = class {
7299
- type = "text";
7300
- text;
7301
- constructor(text2) {
7302
- this.text = text2;
7303
- }
7304
- };
7305
- var Image = class _Image {
7306
- type = "image_url";
7307
- imageUrl;
7308
- constructor(imageUrl) {
7309
- this.imageUrl = imageUrl;
7310
- }
7311
- /**
7312
- * Create Image from a local file by converting to base64 data URL.
7313
- */
7314
- static async fromFile(filePath, detail = "high") {
7315
- const absolutePath = resolve(filePath);
7316
- const buffer = await readFile(absolutePath);
7317
- const base64Data = buffer.toString("base64");
7318
- const ext = getExtension(absolutePath).toLowerCase();
7319
- const mimeType = IMAGE_MIME_TYPES[ext] || "image/jpeg";
7320
- const dataUrl = `data:${mimeType};base64,${base64Data}`;
7321
- return new _Image({ url: dataUrl, detail });
7322
- }
7323
- /**
7324
- * Create Image from a URL.
7325
- */
7326
- static fromUrl(url, detail = "high") {
7327
- return new _Image({ url, detail });
7328
- }
7329
- /**
7330
- * Create Image from a buffer.
7331
- */
7332
- static async fromBuffer(buffer, mimeType = "image/jpeg", detail = "high") {
7333
- const base64Data = Buffer.from(buffer).toString("base64");
7334
- const dataUrl = `data:${mimeType};base64,${base64Data}`;
7335
- return new _Image({ url: dataUrl, detail });
7336
- }
7337
- /**
7338
- * Create Image from a base64 string.
7339
- */
7340
- static async fromBase64(base64Data, mimeType = "image/jpeg", detail = "high") {
7341
- const dataUrl = `data:${mimeType};base64,${base64Data}`;
7342
- return new _Image({ url: dataUrl, detail });
7343
- }
7344
- };
7345
- var Audio = class _Audio {
7346
- type = "input_audio";
7347
- audio;
7348
- constructor(audio) {
7349
- this.audio = audio;
7350
- }
7351
- /**
7352
- * Create Audio from a local file by converting to base64.
7353
- */
7354
- static async fromFile(filePath, format) {
7355
- const absolutePath = resolve(filePath);
7356
- const ext = getExtension(absolutePath).toLowerCase().replace(".", "");
7357
- const audioFormat = format || (["wav", "mp3", "flac", "ogg"].includes(ext) ? ext : "wav");
7358
- const buffer = await readFile(absolutePath);
7359
- const base64Data = buffer.toString("base64");
7360
- return new _Audio({ data: base64Data, format: audioFormat });
7361
- }
7362
- /**
7363
- * Create Audio from a URL (downloads and converts to base64).
7364
- */
7365
- static async fromUrl(url, format = "wav") {
7366
- try {
7367
- const response = await fetch(url);
7368
- if (!response.ok) {
7369
- throw new Error(`Failed to fetch audio from URL: ${response.status} ${response.statusText}`);
7370
- }
7371
- const arrayBuffer = await response.arrayBuffer();
7372
- const base64Data = Buffer.from(arrayBuffer).toString("base64");
7373
- return new _Audio({ data: base64Data, format });
7374
- } catch (error) {
7375
- if (error instanceof TypeError && error.message.includes("fetch")) {
7376
- throw new Error("URL download requires a fetch-compatible environment");
7377
- }
7378
- throw error;
7379
- }
7380
- }
7381
- /**
7382
- * Create Audio from a buffer.
7383
- */
7384
- static async fromBuffer(buffer, format = "wav") {
7385
- const base64Data = Buffer.from(buffer).toString("base64");
7386
- return new _Audio({ data: base64Data, format });
7387
- }
7388
- /**
7389
- * Create Audio from a base64 string.
7390
- */
7391
- static async fromBase64(base64Data, format = "wav") {
7392
- return new _Audio({ data: base64Data, format });
7393
- }
7394
- };
7395
- var Video = class _Video {
7396
- type = "video_url";
7397
- videoUrl;
7398
- constructor(videoUrl) {
7399
- this.videoUrl = videoUrl;
7732
+ parseTarget(target) {
7733
+ if (!target.includes(".")) {
7734
+ return { name: target };
7735
+ }
7736
+ const [agentId, remainder] = target.split(".", 2);
7737
+ const name = remainder.replace(":", "/");
7738
+ return { agentId, name };
7400
7739
  }
7401
- /**
7402
- * Create Video from a local file by converting to a base64 data URL.
7403
- */
7404
- static async fromFile(filePath) {
7405
- const absolutePath = resolve(filePath);
7406
- const buffer = await readFile(absolutePath);
7407
- const base64Data = buffer.toString("base64");
7408
- const ext = getExtension(absolutePath).toLowerCase();
7409
- const mimeType = VIDEO_MIME_TYPES[ext] || "video/mp4";
7410
- return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
7740
+ };
7741
+
7742
+ // src/router/AgentRouter.ts
7743
+ var AgentRouter = class {
7744
+ prefix;
7745
+ tags;
7746
+ reasoners = [];
7747
+ skills = [];
7748
+ constructor(options = {}) {
7749
+ this.prefix = options.prefix;
7750
+ this.tags = options.tags;
7411
7751
  }
7412
- /**
7413
- * Create Video from a URL.
7414
- */
7415
- static fromUrl(url) {
7416
- return new _Video({ url });
7752
+ reasoner(name, handler, options) {
7753
+ const fullName = this.prefix ? `${sanitize(this.prefix)}_${name}` : name;
7754
+ this.reasoners.push({ name: fullName, handler, options });
7755
+ return this;
7417
7756
  }
7418
- /**
7419
- * Create Video from a buffer.
7420
- */
7421
- static async fromBuffer(buffer, mimeType = "video/mp4") {
7422
- const base64Data = Buffer.from(buffer).toString("base64");
7423
- return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
7757
+ skill(name, handler, options) {
7758
+ const fullName = this.prefix ? `${sanitize(this.prefix)}_${name}` : name;
7759
+ this.skills.push({ name: fullName, handler, options });
7760
+ return this;
7424
7761
  }
7425
- /**
7426
- * Create Video from a base64 string.
7427
- */
7428
- static async fromBase64(base64Data, mimeType = "video/mp4") {
7429
- return new _Video({ url: `data:${mimeType};base64,${base64Data}` });
7762
+ };
7763
+ function sanitize(value) {
7764
+ return value.replace(/[^0-9a-zA-Z]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
7765
+ }
7766
+ var JWE_ALG = "ECDH-ES";
7767
+ var JWE_ENC = "A256GCM";
7768
+ var KEY_AGREEMENT_TYPE = "X25519KeyAgreementKey2020";
7769
+ var PayloadEncryptionError = class extends Error {
7770
+ constructor(message) {
7771
+ super(message);
7772
+ this.name = "PayloadEncryptionError";
7430
7773
  }
7431
7774
  };
7432
- var File = class _File {
7433
- type = "file";
7434
- file;
7435
- constructor(file) {
7436
- this.file = file;
7775
+ var encoder = new TextEncoder();
7776
+ function payloadToBytes(payload) {
7777
+ if (payload instanceof Uint8Array) return payload;
7778
+ if (typeof payload === "string") return encoder.encode(payload);
7779
+ return encoder.encode(JSON.stringify(payload));
7780
+ }
7781
+ async function generateX25519KeyPair() {
7782
+ const { privateKey, publicKey } = await generateKeyPair("ECDH-ES", {
7783
+ crv: "X25519",
7784
+ extractable: true
7785
+ });
7786
+ const privateJwk = await exportJWK(privateKey);
7787
+ const publicJwk = await exportJWK(publicKey);
7788
+ return { privateJwk, publicJwk };
7789
+ }
7790
+ function extractKeyAgreementJwk(didDocument) {
7791
+ if (typeof didDocument !== "object" || didDocument === null) {
7792
+ throw new PayloadEncryptionError("DID document must be an object");
7437
7793
  }
7438
- /**
7439
- * Create File from a local file path.
7440
- */
7441
- static async fromFile(filePath, mimeType) {
7442
- const absolutePath = resolve(filePath);
7443
- const detectedMimeType = mimeType || guessMimeType(absolutePath) || "application/octet-stream";
7444
- const buffer = await readFile(absolutePath);
7445
- const base64Data = buffer.toString("base64");
7446
- const dataUrl = `data:${detectedMimeType};base64,${base64Data}`;
7447
- return new _File({ url: dataUrl, mimeType: detectedMimeType });
7794
+ const doc = didDocument["did_document"] ?? didDocument;
7795
+ const flat = doc["key_agreement"];
7796
+ if (flat && typeof flat === "object" && flat.crv === "X25519") {
7797
+ return flat;
7448
7798
  }
7449
- /**
7450
- * Create File from a URL.
7451
- */
7452
- static fromUrl(url, mimeType) {
7453
- return new _File({ url, mimeType });
7799
+ const keyAgreement = doc["keyAgreement"];
7800
+ if (!keyAgreement || Array.isArray(keyAgreement) && keyAgreement.length === 0) {
7801
+ throw new PayloadEncryptionError(
7802
+ "DID document has no keyAgreement key; the agent has not published an X25519 encryption key"
7803
+ );
7454
7804
  }
7455
- /**
7456
- * Create File from a buffer.
7457
- */
7458
- static async fromBuffer(buffer, mimeType) {
7459
- const base64Data = Buffer.from(buffer).toString("base64");
7460
- const dataUrl = `data:${mimeType};base64,${base64Data}`;
7461
- return new _File({ url: dataUrl, mimeType });
7805
+ const verificationMethods = /* @__PURE__ */ new Map();
7806
+ for (const vm2 of doc["verificationMethod"] ?? []) {
7807
+ if (vm2 && typeof vm2 === "object" && typeof vm2["id"] === "string") {
7808
+ verificationMethods.set(vm2["id"], vm2);
7809
+ }
7462
7810
  }
7463
- /**
7464
- * Create File from a base64 string.
7465
- */
7466
- static async fromBase64(base64Data, mimeType) {
7467
- const dataUrl = `data:${mimeType};base64,${base64Data}`;
7468
- return new _File({ url: dataUrl, mimeType });
7811
+ const entry = Array.isArray(keyAgreement) ? keyAgreement[0] : keyAgreement;
7812
+ let vm;
7813
+ if (typeof entry === "string") {
7814
+ vm = verificationMethods.get(entry);
7815
+ if (!vm) {
7816
+ throw new PayloadEncryptionError(
7817
+ `keyAgreement references unknown verification method ${entry}`
7818
+ );
7819
+ }
7820
+ } else if (entry && typeof entry === "object") {
7821
+ vm = entry;
7822
+ } else {
7823
+ throw new PayloadEncryptionError("unsupported keyAgreement entry shape");
7469
7824
  }
7470
- };
7471
- function getExtension(filePath) {
7472
- const lastDot = filePath.lastIndexOf(".");
7473
- if (lastDot === -1) {
7474
- return "";
7825
+ const jwk = vm["publicKeyJwk"];
7826
+ if (!jwk || jwk.crv !== "X25519") {
7827
+ throw new PayloadEncryptionError(
7828
+ "keyAgreement verification method does not carry an X25519 publicKeyJwk"
7829
+ );
7475
7830
  }
7476
- return filePath.slice(lastDot);
7831
+ return jwk;
7477
7832
  }
7478
- function guessMimeType(filePath) {
7479
- const ext = getExtension(filePath).toLowerCase();
7480
- if (ext in IMAGE_MIME_TYPES) {
7481
- return IMAGE_MIME_TYPES[ext];
7482
- }
7483
- if (ext in AUDIO_MIME_TYPES) {
7484
- return AUDIO_MIME_TYPES[ext];
7833
+ async function encryptToJwk(publicJwk, payload) {
7834
+ if (!publicJwk || publicJwk.crv !== "X25519") {
7835
+ throw new PayloadEncryptionError("publicJwk must be an X25519 OKP JWK");
7485
7836
  }
7486
- if (ext in VIDEO_MIME_TYPES) {
7487
- return VIDEO_MIME_TYPES[ext];
7837
+ try {
7838
+ const key = await importJWK(publicJwk, JWE_ALG);
7839
+ return await new CompactEncrypt(payloadToBytes(payload)).setProtectedHeader({ alg: JWE_ALG, enc: JWE_ENC }).encrypt(key);
7840
+ } catch (err) {
7841
+ if (err instanceof PayloadEncryptionError) throw err;
7842
+ throw new PayloadEncryptionError(`encryption failed: ${err.message}`);
7488
7843
  }
7489
- const documentMimeTypes = {
7490
- ".pdf": "application/pdf",
7491
- ".doc": "application/msword",
7492
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
7493
- ".xls": "application/vnd.ms-excel",
7494
- ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
7495
- ".txt": "text/plain",
7496
- ".csv": "text/csv",
7497
- ".html": "text/html",
7498
- ".json": "application/json",
7499
- ".xml": "application/xml",
7500
- ".zip": "application/zip"
7501
- };
7502
- return documentMimeTypes[ext] || null;
7503
- }
7504
- function text(content) {
7505
- return new Text(content);
7506
- }
7507
- async function imageFromFile(filePath, detail = "high") {
7508
- return Image.fromFile(filePath, detail);
7509
- }
7510
- function imageFromUrl(url, detail = "high") {
7511
- return Image.fromUrl(url, detail);
7512
- }
7513
- async function imageFromBuffer(buffer, mimeType = "image/jpeg", detail = "high") {
7514
- return Image.fromBuffer(buffer, mimeType, detail);
7515
- }
7516
- async function imageFromBase64(base64Data, mimeType, detail = "high") {
7517
- return Image.fromBase64(base64Data, mimeType, detail);
7518
- }
7519
- async function audioFromFile(filePath, format) {
7520
- return Audio.fromFile(filePath, format);
7521
- }
7522
- async function audioFromUrl(url, format = "wav") {
7523
- return Audio.fromUrl(url, format);
7524
- }
7525
- async function audioFromBuffer(buffer, format = "wav") {
7526
- return Audio.fromBuffer(buffer, format);
7527
- }
7528
- async function audioFromBase64(base64Data, format = "wav") {
7529
- return Audio.fromBase64(base64Data, format);
7530
- }
7531
- async function videoFromFile(filePath) {
7532
- return Video.fromFile(filePath);
7533
- }
7534
- function videoFromUrl(url) {
7535
- return Video.fromUrl(url);
7536
7844
  }
7537
- async function videoFromBuffer(buffer, mimeType = "video/mp4") {
7538
- return Video.fromBuffer(buffer, mimeType);
7539
- }
7540
- async function videoFromBase64(base64Data, mimeType = "video/mp4") {
7541
- return Video.fromBase64(base64Data, mimeType);
7542
- }
7543
- async function fileFromPath(filePath, mimeType) {
7544
- return File.fromFile(filePath, mimeType);
7545
- }
7546
- function fileFromUrl(url, mimeType) {
7547
- return File.fromUrl(url, mimeType);
7845
+ async function encryptForDid(did, payload, resolver) {
7846
+ const document = await resolver(did);
7847
+ if (!document) {
7848
+ throw new PayloadEncryptionError(`could not resolve DID ${did}`);
7849
+ }
7850
+ const publicJwk = extractKeyAgreementJwk(document);
7851
+ return encryptToJwk(publicJwk, payload);
7548
7852
  }
7549
- async function fileFromBuffer(buffer, mimeType) {
7550
- return File.fromBuffer(buffer, mimeType);
7853
+ async function decrypt(token, privateJwk) {
7854
+ try {
7855
+ const key = await importJWK(privateJwk, JWE_ALG);
7856
+ const { plaintext } = await compactDecrypt(token, key);
7857
+ return Uint8Array.from(plaintext);
7858
+ } catch (err) {
7859
+ throw new PayloadEncryptionError(`decryption failed: ${err.message}`);
7860
+ }
7551
7861
  }
7552
- async function fileFromBase64(base64Data, mimeType) {
7553
- return File.fromBase64(base64Data, mimeType);
7862
+ async function decryptToString(token, privateJwk) {
7863
+ return new TextDecoder().decode(await decrypt(token, privateJwk));
7554
7864
  }
7555
7865
  var MultimodalResponse = class {
7556
7866
  _text;
@@ -8367,7 +8677,7 @@ var OpenRouterMediaProvider = class {
8367
8677
  );
8368
8678
  }
8369
8679
  const audioChunks = [];
8370
- let textContent = "";
8680
+ let textContent2 = "";
8371
8681
  const reader = res.body?.getReader();
8372
8682
  if (!reader) {
8373
8683
  throw new MediaProviderError("No response body stream available", {
@@ -8399,7 +8709,7 @@ var OpenRouterMediaProvider = class {
8399
8709
  const delta = choice.delta;
8400
8710
  if (!delta) continue;
8401
8711
  if (typeof delta.content === "string") {
8402
- textContent += delta.content;
8712
+ textContent2 += delta.content;
8403
8713
  }
8404
8714
  const audioDelta = delta.audio;
8405
8715
  if (audioDelta?.data) {
@@ -8430,7 +8740,7 @@ var OpenRouterMediaProvider = class {
8430
8740
  const delta = choice.delta;
8431
8741
  if (!delta) continue;
8432
8742
  if (typeof delta.content === "string") {
8433
- textContent += delta.content;
8743
+ textContent2 += delta.content;
8434
8744
  }
8435
8745
  const audioDelta = delta.audio;
8436
8746
  if (audioDelta?.data) {
@@ -8444,7 +8754,7 @@ var OpenRouterMediaProvider = class {
8444
8754
  }
8445
8755
  }
8446
8756
  const resp = emptyMediaResponse(null);
8447
- resp.text = textContent;
8757
+ resp.text = textContent2;
8448
8758
  if (audioChunks.length > 0) {
8449
8759
  let b64 = audioChunks.join("");
8450
8760
  try {
@@ -8589,6 +8899,6 @@ function loadFixture(source) {
8589
8899
  );
8590
8900
  }
8591
8901
 
8592
- export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, ApprovalResult, Audio, CANONICAL_STATUSES, CostTracker, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, JWE_ALG, JWE_ENC, KEY_AGREEMENT_TYPE, MODEL_VARIANT_SEP, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, PauseClock, PauseManager, PayloadEncryptionError, RateLimitError, RealtimeSession, ReasonerContext, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, SessionTransportError, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, USAGE_ENVELOPE_KEY, Video, WorkflowReporter, applyTriggerTransform, attachUsageToSyncResult, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, decrypt, decryptToString, deriveProvider, encryptForDid, encryptToJwk, eventTrigger, executeToolCallLoop, extractKeyAgreementJwk, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, generateX25519KeyPair, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, installApprovalWebhookRoute, isActive, isExecutionLogBatchPayload, isTerminal, isTriggerEnvelope, loadFixture, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, resolveModelAndVariant, scheduleTrigger, serializeExecutionLogEntry, simulateSchedule, simulateTrigger, splitModelVariant, text, triggerToPayload, unwrapEnvelope, usageSummaryOrNull, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
8902
+ export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, ApprovalResult, Audio, CANONICAL_STATUSES, CostTracker, DEFAULT_HARNESS_PROVIDER, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HARNESS_PROVIDER_ENV_VAR, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, JWE_ALG, JWE_ENC, KEY_AGREEMENT_TYPE, MODEL_VARIANT_SEP, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, PauseClock, PauseManager, PayloadEncryptionError, RateLimitError, RealtimeSession, ReasonerContext, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, SessionTransportError, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, USAGE_ENVELOPE_KEY, Video, WorkflowReporter, applyTriggerTransform, attachUsageToSyncResult, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, audioMediaType, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, decrypt, decryptToString, deriveProvider, encryptForDid, encryptToJwk, eventTrigger, executeToolCallLoop, extractKeyAgreementJwk, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, generateX25519KeyPair, getCurrentContext, getCurrentSkillContext, guessUrlMimeType, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, installApprovalWebhookRoute, isActive, isExecutionLogBatchPayload, isTerminal, isTriggerEnvelope, loadFixture, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, resolveModelAndVariant, resolveProviderName, scheduleTrigger, serializeExecutionLogEntry, simulateSchedule, simulateTrigger, splitModelVariant, text, triggerToPayload, unwrapEnvelope, usageSummaryOrNull, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
8593
8903
  //# sourceMappingURL=index.js.map
8594
8904
  //# sourceMappingURL=index.js.map