@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.d.ts +215 -192
- package/dist/index.js +1189 -879
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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/
|
|
154
|
-
function
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
391
|
-
|
|
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
|
-
|
|
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/
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const
|
|
568
|
-
return
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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 &&
|
|
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 &&
|
|
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 (
|
|
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
|
-
|
|
970
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
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([
|
|
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
|
-
|
|
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
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
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
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
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
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
const
|
|
2900
|
-
const
|
|
2901
|
-
|
|
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
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
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
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
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
|
-
|
|
2928
|
-
|
|
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
|
-
|
|
2931
|
-
|
|
3408
|
+
};
|
|
3409
|
+
var File = class _File {
|
|
3410
|
+
type = "file";
|
|
3411
|
+
file;
|
|
3412
|
+
constructor(file) {
|
|
3413
|
+
this.file = file;
|
|
2932
3414
|
}
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
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
|
|
2966
|
-
|
|
2967
|
-
|
|
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
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
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
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
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
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
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
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
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
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
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
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
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
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
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
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
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
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
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
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
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
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
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
|
|
7831
|
+
return jwk;
|
|
7477
7832
|
}
|
|
7478
|
-
function
|
|
7479
|
-
|
|
7480
|
-
|
|
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
|
-
|
|
7487
|
-
|
|
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
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
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
|
|
7550
|
-
|
|
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
|
|
7553
|
-
return
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|