agentv 3.11.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -12
- package/dist/{chunk-ETMDLQ72.js → chunk-2ELQ6F3C.js} +916 -523
- package/dist/chunk-2ELQ6F3C.js.map +1 -0
- package/dist/{chunk-JK6V4KVD.js → chunk-NR7QVL75.js} +32 -24
- package/dist/chunk-NR7QVL75.js.map +1 -0
- package/dist/{chunk-EZGWZVVK.js → chunk-UYBLUYHN.js} +927 -615
- package/dist/chunk-UYBLUYHN.js.map +1 -0
- package/dist/{chunk-JEW3FEO7.js → chunk-VLOFRXH4.js} +469 -198
- package/dist/chunk-VLOFRXH4.js.map +1 -0
- package/dist/cli.js +4 -4
- package/dist/{dist-QERRYDSC.js → dist-L6R5HJ72.js} +3 -3
- package/dist/index.js +4 -4
- package/dist/{interactive-AD4PRYDN.js → interactive-5X62YEEX.js} +4 -4
- package/dist/{simple-trace-file-exporter-S76DMABU-5FCJESD2.js → simple-trace-file-exporter-CRIO5HDZ-QYYT2QQT.js} +2 -2
- package/dist/templates/.agentv/.env.example +23 -0
- package/dist/templates/.agentv/config.yaml +13 -4
- package/dist/templates/.agentv/targets.yaml +16 -0
- package/package.json +9 -3
- package/dist/chunk-ETMDLQ72.js.map +0 -1
- package/dist/chunk-EZGWZVVK.js.map +0 -1
- package/dist/chunk-JEW3FEO7.js.map +0 -1
- package/dist/chunk-JK6V4KVD.js.map +0 -1
- /package/dist/{dist-QERRYDSC.js.map → dist-L6R5HJ72.js.map} +0 -0
- /package/dist/{interactive-AD4PRYDN.js.map → interactive-5X62YEEX.js.map} +0 -0
- /package/dist/{simple-trace-file-exporter-S76DMABU-5FCJESD2.js.map → simple-trace-file-exporter-CRIO5HDZ-QYYT2QQT.js.map} +0 -0
|
@@ -301,7 +301,7 @@ var require_dist = __commonJS({
|
|
|
301
301
|
}
|
|
302
302
|
});
|
|
303
303
|
|
|
304
|
-
// ../../packages/core/dist/chunk-
|
|
304
|
+
// ../../packages/core/dist/chunk-4XWPXNQM.js
|
|
305
305
|
import { constants } from "node:fs";
|
|
306
306
|
import { access, readFile } from "node:fs/promises";
|
|
307
307
|
import path from "node:path";
|
|
@@ -419,7 +419,7 @@ __export(external_exports2, {
|
|
|
419
419
|
void: () => voidType
|
|
420
420
|
});
|
|
421
421
|
|
|
422
|
-
// ../../packages/core/dist/chunk-
|
|
422
|
+
// ../../packages/core/dist/chunk-4XWPXNQM.js
|
|
423
423
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
424
424
|
import path3 from "node:path";
|
|
425
425
|
import fg from "fast-glob";
|
|
@@ -938,14 +938,14 @@ function resolveTargetDefinition(definition, env = process.env, evalFilePath) {
|
|
|
938
938
|
providerBatching,
|
|
939
939
|
config: resolvePiCodingAgentConfig(parsed, env, evalFilePath)
|
|
940
940
|
};
|
|
941
|
-
case "pi-
|
|
941
|
+
case "pi-cli":
|
|
942
942
|
return {
|
|
943
|
-
kind: "pi-
|
|
943
|
+
kind: "pi-cli",
|
|
944
944
|
name: parsed.name,
|
|
945
945
|
graderTarget: parsed.grader_target ?? parsed.judge_target,
|
|
946
946
|
workers: parsed.workers,
|
|
947
947
|
providerBatching,
|
|
948
|
-
config:
|
|
948
|
+
config: resolvePiCliConfig(parsed, env, evalFilePath)
|
|
949
949
|
};
|
|
950
950
|
case "claude":
|
|
951
951
|
case "claude-code":
|
|
@@ -1362,23 +1362,17 @@ function normalizeCopilotLogFormat(value) {
|
|
|
1362
1362
|
throw new Error("copilot log format must be 'summary' or 'json'");
|
|
1363
1363
|
}
|
|
1364
1364
|
function resolvePiCodingAgentConfig(target, env, evalFilePath) {
|
|
1365
|
-
const executableSource = target.executable ?? target.command ?? target.binary;
|
|
1366
1365
|
const subproviderSource = target.subprovider;
|
|
1367
1366
|
const modelSource = target.model ?? target.pi_model ?? target.piModel;
|
|
1368
1367
|
const apiKeySource = target.api_key ?? target.apiKey;
|
|
1369
1368
|
const toolsSource = target.tools ?? target.pi_tools ?? target.piTools;
|
|
1370
1369
|
const thinkingSource = target.thinking ?? target.pi_thinking ?? target.piThinking;
|
|
1371
|
-
const argsSource = target.args ?? target.arguments;
|
|
1372
1370
|
const cwdSource = target.cwd;
|
|
1373
1371
|
const workspaceTemplateSource = target.workspace_template ?? target.workspaceTemplate;
|
|
1374
1372
|
const timeoutSource = target.timeout_seconds ?? target.timeoutSeconds;
|
|
1375
1373
|
const logDirSource = target.log_dir ?? target.logDir ?? target.log_directory ?? target.logDirectory;
|
|
1376
1374
|
const logFormatSource = target.log_format ?? target.logFormat;
|
|
1377
1375
|
const systemPromptSource = target.system_prompt ?? target.systemPrompt;
|
|
1378
|
-
const executable = resolveOptionalString(executableSource, env, `${target.name} pi executable`, {
|
|
1379
|
-
allowLiteral: true,
|
|
1380
|
-
optionalEnv: true
|
|
1381
|
-
}) ?? "pi";
|
|
1382
1376
|
const subprovider = resolveOptionalString(
|
|
1383
1377
|
subproviderSource,
|
|
1384
1378
|
env,
|
|
@@ -1404,7 +1398,6 @@ function resolvePiCodingAgentConfig(target, env, evalFilePath) {
|
|
|
1404
1398
|
allowLiteral: true,
|
|
1405
1399
|
optionalEnv: true
|
|
1406
1400
|
});
|
|
1407
|
-
const args = resolveOptionalStringArray(argsSource, env, `${target.name} pi args`);
|
|
1408
1401
|
const cwd = resolveOptionalString(cwdSource, env, `${target.name} pi cwd`, {
|
|
1409
1402
|
allowLiteral: true,
|
|
1410
1403
|
optionalEnv: true
|
|
@@ -1434,13 +1427,11 @@ function resolvePiCodingAgentConfig(target, env, evalFilePath) {
|
|
|
1434
1427
|
const logFormat = logFormatSource === "json" || logFormatSource === "summary" ? logFormatSource : void 0;
|
|
1435
1428
|
const systemPrompt = typeof systemPromptSource === "string" && systemPromptSource.trim().length > 0 ? systemPromptSource.trim() : void 0;
|
|
1436
1429
|
return {
|
|
1437
|
-
executable,
|
|
1438
1430
|
subprovider,
|
|
1439
1431
|
model,
|
|
1440
1432
|
apiKey,
|
|
1441
1433
|
tools,
|
|
1442
1434
|
thinking,
|
|
1443
|
-
args,
|
|
1444
1435
|
cwd,
|
|
1445
1436
|
workspaceTemplate,
|
|
1446
1437
|
timeoutMs,
|
|
@@ -1449,36 +1440,83 @@ function resolvePiCodingAgentConfig(target, env, evalFilePath) {
|
|
|
1449
1440
|
systemPrompt
|
|
1450
1441
|
};
|
|
1451
1442
|
}
|
|
1452
|
-
function
|
|
1443
|
+
function resolvePiCliConfig(target, env, evalFilePath) {
|
|
1444
|
+
const executableSource = target.executable ?? target.command ?? target.binary;
|
|
1453
1445
|
const subproviderSource = target.subprovider;
|
|
1454
1446
|
const modelSource = target.model ?? target.pi_model ?? target.piModel;
|
|
1455
1447
|
const apiKeySource = target.api_key ?? target.apiKey;
|
|
1448
|
+
const toolsSource = target.tools ?? target.pi_tools ?? target.piTools;
|
|
1449
|
+
const thinkingSource = target.thinking ?? target.pi_thinking ?? target.piThinking;
|
|
1450
|
+
const cwdSource = target.cwd;
|
|
1451
|
+
const workspaceTemplateSource = target.workspace_template ?? target.workspaceTemplate;
|
|
1456
1452
|
const timeoutSource = target.timeout_seconds ?? target.timeoutSeconds;
|
|
1453
|
+
const logDirSource = target.log_dir ?? target.logDir ?? target.log_directory ?? target.logDirectory;
|
|
1454
|
+
const logFormatSource = target.log_format ?? target.logFormat;
|
|
1457
1455
|
const systemPromptSource = target.system_prompt ?? target.systemPrompt;
|
|
1456
|
+
const executable = resolveOptionalString(executableSource, env, `${target.name} pi-cli executable`, {
|
|
1457
|
+
allowLiteral: true,
|
|
1458
|
+
optionalEnv: true
|
|
1459
|
+
}) ?? "pi";
|
|
1458
1460
|
const subprovider = resolveOptionalString(
|
|
1459
1461
|
subproviderSource,
|
|
1460
1462
|
env,
|
|
1461
|
-
`${target.name} pi-
|
|
1462
|
-
{
|
|
1463
|
-
allowLiteral: true,
|
|
1464
|
-
optionalEnv: true
|
|
1465
|
-
}
|
|
1463
|
+
`${target.name} pi-cli subprovider`,
|
|
1464
|
+
{ allowLiteral: true, optionalEnv: true }
|
|
1466
1465
|
);
|
|
1467
|
-
const model = resolveOptionalString(modelSource, env, `${target.name} pi-
|
|
1466
|
+
const model = resolveOptionalString(modelSource, env, `${target.name} pi-cli model`, {
|
|
1468
1467
|
allowLiteral: true,
|
|
1469
1468
|
optionalEnv: true
|
|
1470
1469
|
});
|
|
1471
|
-
const apiKey = resolveOptionalString(apiKeySource, env, `${target.name} pi-
|
|
1470
|
+
const apiKey = resolveOptionalString(apiKeySource, env, `${target.name} pi-cli api key`, {
|
|
1472
1471
|
allowLiteral: false,
|
|
1473
1472
|
optionalEnv: true
|
|
1474
1473
|
});
|
|
1475
|
-
const
|
|
1474
|
+
const tools = resolveOptionalString(toolsSource, env, `${target.name} pi-cli tools`, {
|
|
1475
|
+
allowLiteral: true,
|
|
1476
|
+
optionalEnv: true
|
|
1477
|
+
});
|
|
1478
|
+
const thinking = resolveOptionalString(thinkingSource, env, `${target.name} pi-cli thinking`, {
|
|
1479
|
+
allowLiteral: true,
|
|
1480
|
+
optionalEnv: true
|
|
1481
|
+
});
|
|
1482
|
+
const rawArgs = target.args ?? target.arguments;
|
|
1483
|
+
const args = resolveOptionalStringArray(rawArgs, env, `${target.name} pi-cli args`);
|
|
1484
|
+
const cwd = resolveOptionalString(cwdSource, env, `${target.name} pi-cli cwd`, {
|
|
1485
|
+
allowLiteral: true,
|
|
1486
|
+
optionalEnv: true
|
|
1487
|
+
});
|
|
1488
|
+
let workspaceTemplate = resolveOptionalString(
|
|
1489
|
+
workspaceTemplateSource,
|
|
1490
|
+
env,
|
|
1491
|
+
`${target.name} pi-cli workspace template`,
|
|
1492
|
+
{ allowLiteral: true, optionalEnv: true }
|
|
1493
|
+
);
|
|
1494
|
+
if (workspaceTemplate && evalFilePath && !path2.isAbsolute(workspaceTemplate)) {
|
|
1495
|
+
workspaceTemplate = path2.resolve(path2.dirname(path2.resolve(evalFilePath)), workspaceTemplate);
|
|
1496
|
+
}
|
|
1497
|
+
if (cwd && workspaceTemplate) {
|
|
1498
|
+
throw new Error(`${target.name}: 'cwd' and 'workspace_template' are mutually exclusive.`);
|
|
1499
|
+
}
|
|
1500
|
+
const timeoutMs = resolveTimeoutMs(timeoutSource, `${target.name} pi-cli timeout`);
|
|
1501
|
+
const logDir = resolveOptionalString(logDirSource, env, `${target.name} pi-cli log directory`, {
|
|
1502
|
+
allowLiteral: true,
|
|
1503
|
+
optionalEnv: true
|
|
1504
|
+
});
|
|
1505
|
+
const logFormat = logFormatSource === "json" || logFormatSource === "summary" ? logFormatSource : void 0;
|
|
1476
1506
|
const systemPrompt = typeof systemPromptSource === "string" && systemPromptSource.trim().length > 0 ? systemPromptSource.trim() : void 0;
|
|
1477
1507
|
return {
|
|
1508
|
+
executable,
|
|
1478
1509
|
subprovider,
|
|
1479
1510
|
model,
|
|
1480
1511
|
apiKey,
|
|
1512
|
+
tools,
|
|
1513
|
+
thinking,
|
|
1514
|
+
args,
|
|
1515
|
+
cwd,
|
|
1516
|
+
workspaceTemplate,
|
|
1481
1517
|
timeoutMs,
|
|
1518
|
+
logDir,
|
|
1519
|
+
logFormat,
|
|
1482
1520
|
systemPrompt
|
|
1483
1521
|
};
|
|
1484
1522
|
}
|
|
@@ -1608,8 +1646,8 @@ function resolveCliConfig(target, env, evalFilePath) {
|
|
|
1608
1646
|
const parseResult = CliTargetInputSchema.safeParse(target, { errorMap: cliErrorMap });
|
|
1609
1647
|
if (!parseResult.success) {
|
|
1610
1648
|
const firstError = parseResult.error.errors[0];
|
|
1611
|
-
const
|
|
1612
|
-
const prefix =
|
|
1649
|
+
const path45 = firstError?.path.join(".") || "";
|
|
1650
|
+
const prefix = path45 ? `${target.name} ${path45}: ` : `${target.name}: `;
|
|
1613
1651
|
throw new Error(`${prefix}${firstError?.message}`);
|
|
1614
1652
|
}
|
|
1615
1653
|
const normalized = normalizeCliTargetInput(parseResult.data, env, evalFilePath);
|
|
@@ -1949,7 +1987,7 @@ var AGENT_PROVIDER_KINDS = [
|
|
|
1949
1987
|
"copilot-sdk",
|
|
1950
1988
|
"copilot-cli",
|
|
1951
1989
|
"pi-coding-agent",
|
|
1952
|
-
"pi-
|
|
1990
|
+
"pi-cli",
|
|
1953
1991
|
"claude",
|
|
1954
1992
|
"claude-cli",
|
|
1955
1993
|
"claude-sdk",
|
|
@@ -1966,7 +2004,7 @@ var KNOWN_PROVIDERS = [
|
|
|
1966
2004
|
"copilot-sdk",
|
|
1967
2005
|
"copilot-cli",
|
|
1968
2006
|
"pi-coding-agent",
|
|
1969
|
-
"pi-
|
|
2007
|
+
"pi-cli",
|
|
1970
2008
|
"claude",
|
|
1971
2009
|
"claude-cli",
|
|
1972
2010
|
"claude-sdk",
|
|
@@ -6651,7 +6689,7 @@ function createOpenRouter(options = {}) {
|
|
|
6651
6689
|
);
|
|
6652
6690
|
const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
|
|
6653
6691
|
provider: "openrouter.chat",
|
|
6654
|
-
url: ({ path:
|
|
6692
|
+
url: ({ path: path45 }) => `${baseURL}${path45}`,
|
|
6655
6693
|
headers: getHeaders,
|
|
6656
6694
|
compatibility,
|
|
6657
6695
|
fetch: options.fetch,
|
|
@@ -6659,7 +6697,7 @@ function createOpenRouter(options = {}) {
|
|
|
6659
6697
|
});
|
|
6660
6698
|
const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
|
|
6661
6699
|
provider: "openrouter.completion",
|
|
6662
|
-
url: ({ path:
|
|
6700
|
+
url: ({ path: path45 }) => `${baseURL}${path45}`,
|
|
6663
6701
|
headers: getHeaders,
|
|
6664
6702
|
compatibility,
|
|
6665
6703
|
fetch: options.fetch,
|
|
@@ -6667,14 +6705,14 @@ function createOpenRouter(options = {}) {
|
|
|
6667
6705
|
});
|
|
6668
6706
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
|
|
6669
6707
|
provider: "openrouter.embedding",
|
|
6670
|
-
url: ({ path:
|
|
6708
|
+
url: ({ path: path45 }) => `${baseURL}${path45}`,
|
|
6671
6709
|
headers: getHeaders,
|
|
6672
6710
|
fetch: options.fetch,
|
|
6673
6711
|
extraBody: options.extraBody
|
|
6674
6712
|
});
|
|
6675
6713
|
const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
|
|
6676
6714
|
provider: "openrouter.image",
|
|
6677
|
-
url: ({ path:
|
|
6715
|
+
url: ({ path: path45 }) => `${baseURL}${path45}`,
|
|
6678
6716
|
headers: getHeaders,
|
|
6679
6717
|
fetch: options.fetch,
|
|
6680
6718
|
extraBody: options.extraBody
|
|
@@ -14183,37 +14221,43 @@ import { createWriteStream as createWriteStream5 } from "node:fs";
|
|
|
14183
14221
|
import { mkdir as mkdir6, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
14184
14222
|
import { tmpdir } from "node:os";
|
|
14185
14223
|
import path17 from "node:path";
|
|
14224
|
+
import { execSync } from "node:child_process";
|
|
14225
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
14226
|
+
import { createWriteStream as createWriteStream6 } from "node:fs";
|
|
14227
|
+
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
14228
|
+
import path18 from "node:path";
|
|
14229
|
+
import { createInterface } from "node:readline";
|
|
14186
14230
|
import { exec as exec2 } from "node:child_process";
|
|
14187
14231
|
import { constants as constants3, access as access3, stat as stat4 } from "node:fs/promises";
|
|
14188
|
-
import
|
|
14232
|
+
import path30 from "node:path";
|
|
14189
14233
|
import { promisify as promisify3 } from "node:util";
|
|
14190
14234
|
import { stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
|
|
14191
|
-
import
|
|
14235
|
+
import path28 from "node:path";
|
|
14192
14236
|
import { constants as constants22 } from "node:fs";
|
|
14193
|
-
import { access as access22, mkdir as
|
|
14194
|
-
import path18 from "node:path";
|
|
14237
|
+
import { access as access22, mkdir as mkdir8, readdir, rm as rm2, stat } from "node:fs/promises";
|
|
14195
14238
|
import path19 from "node:path";
|
|
14196
14239
|
import path20 from "node:path";
|
|
14197
|
-
import { readFile as readFile7 } from "node:fs/promises";
|
|
14198
14240
|
import path21 from "node:path";
|
|
14241
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
14242
|
+
import path222 from "node:path";
|
|
14199
14243
|
import { exec, spawn as spawn4 } from "node:child_process";
|
|
14200
|
-
import { mkdir as
|
|
14201
|
-
import
|
|
14244
|
+
import { mkdir as mkdir9, writeFile as writeFile2 } from "node:fs/promises";
|
|
14245
|
+
import path25 from "node:path";
|
|
14202
14246
|
import { promisify as promisify2 } from "node:util";
|
|
14203
|
-
import
|
|
14247
|
+
import path24 from "node:path";
|
|
14204
14248
|
import os2 from "node:os";
|
|
14205
|
-
import
|
|
14206
|
-
import { copyFile, mkdir as
|
|
14249
|
+
import path23 from "node:path";
|
|
14250
|
+
import { copyFile, mkdir as mkdir10, readFile as readFile8, readdir as readdir2, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
|
|
14251
|
+
import path27 from "node:path";
|
|
14207
14252
|
import path26 from "node:path";
|
|
14208
|
-
import path25 from "node:path";
|
|
14209
14253
|
import JSON5 from "json5";
|
|
14210
14254
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
14211
|
-
import
|
|
14255
|
+
import path29 from "node:path";
|
|
14212
14256
|
import { constants as constants4 } from "node:fs";
|
|
14213
14257
|
import { access as access4, readFile as readFile9 } from "node:fs/promises";
|
|
14214
|
-
import path30 from "node:path";
|
|
14215
|
-
import { parse as parse4 } from "yaml";
|
|
14216
14258
|
import path31 from "node:path";
|
|
14259
|
+
import { parse as parse4 } from "yaml";
|
|
14260
|
+
import path322 from "node:path";
|
|
14217
14261
|
import fg2 from "fast-glob";
|
|
14218
14262
|
import { mkdtemp as mkdtemp2, rm as rm3, writeFile as writeFile6 } from "node:fs/promises";
|
|
14219
14263
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
@@ -14221,38 +14265,38 @@ import { dirname, join } from "node:path";
|
|
|
14221
14265
|
import { randomBytes } from "node:crypto";
|
|
14222
14266
|
import { createServer } from "node:http";
|
|
14223
14267
|
import fs2 from "node:fs/promises";
|
|
14224
|
-
import path322 from "node:path";
|
|
14225
|
-
import { createHash as createHash2, randomUUID as randomUUID8 } from "node:crypto";
|
|
14226
|
-
import { copyFile as copyFile2, mkdir as mkdir13, readdir as readdir6, stat as stat7 } from "node:fs/promises";
|
|
14227
|
-
import path41 from "node:path";
|
|
14228
|
-
import micromatch3 from "micromatch";
|
|
14229
14268
|
import path33 from "node:path";
|
|
14269
|
+
import { createHash as createHash2, randomUUID as randomUUID9 } from "node:crypto";
|
|
14270
|
+
import { copyFile as copyFile2, mkdir as mkdir14, readdir as readdir6, stat as stat7 } from "node:fs/promises";
|
|
14271
|
+
import path422 from "node:path";
|
|
14272
|
+
import micromatch3 from "micromatch";
|
|
14230
14273
|
import path34 from "node:path";
|
|
14231
|
-
import fg22 from "fast-glob";
|
|
14232
14274
|
import path35 from "node:path";
|
|
14275
|
+
import fg22 from "fast-glob";
|
|
14276
|
+
import path36 from "node:path";
|
|
14233
14277
|
import fg3 from "fast-glob";
|
|
14234
14278
|
import { exec as execCallback } from "node:child_process";
|
|
14235
14279
|
import { readdirSync as readdirSync2, statSync } from "node:fs";
|
|
14236
|
-
import path36 from "node:path";
|
|
14237
|
-
import { promisify as promisify4 } from "node:util";
|
|
14238
|
-
import { cp, mkdir as mkdir11, readdir as readdir3, rm as rm4, stat as stat5 } from "node:fs/promises";
|
|
14239
14280
|
import path37 from "node:path";
|
|
14281
|
+
import { promisify as promisify4 } from "node:util";
|
|
14282
|
+
import { cp, mkdir as mkdir12, readdir as readdir3, rm as rm4, stat as stat5 } from "node:fs/promises";
|
|
14283
|
+
import path38 from "node:path";
|
|
14240
14284
|
import { execFile } from "node:child_process";
|
|
14241
14285
|
import { createHash } from "node:crypto";
|
|
14242
14286
|
import { existsSync as existsSync2 } from "node:fs";
|
|
14243
|
-
import { cp as cp2, mkdir as
|
|
14244
|
-
import
|
|
14287
|
+
import { cp as cp2, mkdir as mkdir13, readFile as readFile10, readdir as readdir4, rm as rm5, unlink, writeFile as writeFile7 } from "node:fs/promises";
|
|
14288
|
+
import path39 from "node:path";
|
|
14245
14289
|
import { promisify as promisify5 } from "node:util";
|
|
14246
14290
|
import { execFile as execFile2 } from "node:child_process";
|
|
14247
14291
|
import { existsSync as existsSync3 } from "node:fs";
|
|
14248
|
-
import
|
|
14292
|
+
import path40 from "node:path";
|
|
14249
14293
|
import { promisify as promisify6 } from "node:util";
|
|
14250
14294
|
import { readdir as readdir5, stat as stat6 } from "node:fs/promises";
|
|
14251
|
-
import
|
|
14295
|
+
import path41 from "node:path";
|
|
14252
14296
|
import { existsSync as existsSync4 } from "node:fs";
|
|
14253
|
-
import path422 from "node:path";
|
|
14254
|
-
import { mkdir as mkdir14, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
|
|
14255
14297
|
import path43 from "node:path";
|
|
14298
|
+
import { mkdir as mkdir15, readFile as readFile11, writeFile as writeFile8 } from "node:fs/promises";
|
|
14299
|
+
import path44 from "node:path";
|
|
14256
14300
|
function computeTraceSummary(messages) {
|
|
14257
14301
|
const toolCallCounts = {};
|
|
14258
14302
|
const toolDurations = {};
|
|
@@ -20871,260 +20915,6 @@ var MockProvider = class {
|
|
|
20871
20915
|
return this.delayMs;
|
|
20872
20916
|
}
|
|
20873
20917
|
};
|
|
20874
|
-
function extractPiTextContent(content) {
|
|
20875
|
-
if (typeof content === "string") {
|
|
20876
|
-
return content;
|
|
20877
|
-
}
|
|
20878
|
-
if (!Array.isArray(content)) {
|
|
20879
|
-
return void 0;
|
|
20880
|
-
}
|
|
20881
|
-
const textParts = [];
|
|
20882
|
-
for (const part of content) {
|
|
20883
|
-
if (!part || typeof part !== "object") {
|
|
20884
|
-
continue;
|
|
20885
|
-
}
|
|
20886
|
-
const p = part;
|
|
20887
|
-
if (p.type === "text" && typeof p.text === "string") {
|
|
20888
|
-
textParts.push(p.text);
|
|
20889
|
-
}
|
|
20890
|
-
}
|
|
20891
|
-
return textParts.length > 0 ? textParts.join("\n") : void 0;
|
|
20892
|
-
}
|
|
20893
|
-
function toFiniteNumber(value) {
|
|
20894
|
-
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
20895
|
-
return void 0;
|
|
20896
|
-
}
|
|
20897
|
-
var piAgentModule = null;
|
|
20898
|
-
var piAiModule = null;
|
|
20899
|
-
async function loadPiModules() {
|
|
20900
|
-
if (!piAgentModule || !piAiModule) {
|
|
20901
|
-
try {
|
|
20902
|
-
[piAgentModule, piAiModule] = await Promise.all([
|
|
20903
|
-
import("@mariozechner/pi-agent-core"),
|
|
20904
|
-
import("@mariozechner/pi-ai")
|
|
20905
|
-
]);
|
|
20906
|
-
} catch (error) {
|
|
20907
|
-
throw new Error(
|
|
20908
|
-
`Failed to load pi-agent-sdk dependencies. Please install them:
|
|
20909
|
-
npm install @mariozechner/pi-agent-core @mariozechner/pi-ai
|
|
20910
|
-
|
|
20911
|
-
Original error: ${error instanceof Error ? error.message : String(error)}`
|
|
20912
|
-
);
|
|
20913
|
-
}
|
|
20914
|
-
}
|
|
20915
|
-
return {
|
|
20916
|
-
Agent: piAgentModule.Agent,
|
|
20917
|
-
getModel: piAiModule.getModel,
|
|
20918
|
-
getEnvApiKey: piAiModule.getEnvApiKey
|
|
20919
|
-
};
|
|
20920
|
-
}
|
|
20921
|
-
var PiAgentSdkProvider = class {
|
|
20922
|
-
id;
|
|
20923
|
-
kind = "pi-agent-sdk";
|
|
20924
|
-
targetName;
|
|
20925
|
-
supportsBatch = false;
|
|
20926
|
-
config;
|
|
20927
|
-
constructor(targetName, config) {
|
|
20928
|
-
this.id = `pi-agent-sdk:${targetName}`;
|
|
20929
|
-
this.targetName = targetName;
|
|
20930
|
-
this.config = config;
|
|
20931
|
-
}
|
|
20932
|
-
async invoke(request) {
|
|
20933
|
-
if (request.signal?.aborted) {
|
|
20934
|
-
throw new Error("Pi agent SDK request was aborted before execution");
|
|
20935
|
-
}
|
|
20936
|
-
const { Agent, getModel, getEnvApiKey } = await loadPiModules();
|
|
20937
|
-
const startTimeIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
20938
|
-
const startMs = Date.now();
|
|
20939
|
-
const providerName = this.config.subprovider ?? "anthropic";
|
|
20940
|
-
const modelId = this.config.model ?? "claude-sonnet-4-20250514";
|
|
20941
|
-
const model = getModel(providerName, modelId);
|
|
20942
|
-
const systemPrompt = this.config.systemPrompt ?? "Answer directly and concisely.";
|
|
20943
|
-
const agent = new Agent({
|
|
20944
|
-
initialState: {
|
|
20945
|
-
systemPrompt,
|
|
20946
|
-
model,
|
|
20947
|
-
tools: [],
|
|
20948
|
-
// No tools for simple Q&A
|
|
20949
|
-
messages: []
|
|
20950
|
-
},
|
|
20951
|
-
getApiKey: async (provider) => {
|
|
20952
|
-
return this.config.apiKey ?? getEnvApiKey(provider) ?? void 0;
|
|
20953
|
-
}
|
|
20954
|
-
});
|
|
20955
|
-
let tokenUsage;
|
|
20956
|
-
let costUsd;
|
|
20957
|
-
const toolTrackers = /* @__PURE__ */ new Map();
|
|
20958
|
-
const completedToolResults = /* @__PURE__ */ new Map();
|
|
20959
|
-
const unsubscribe = agent.subscribe((event) => {
|
|
20960
|
-
switch (event.type) {
|
|
20961
|
-
case "message_end": {
|
|
20962
|
-
const msg = event.message;
|
|
20963
|
-
if (msg && typeof msg === "object" && "role" in msg && msg.role === "assistant" && "usage" in msg) {
|
|
20964
|
-
const usage = msg.usage;
|
|
20965
|
-
if (usage && typeof usage === "object") {
|
|
20966
|
-
const u = usage;
|
|
20967
|
-
const input = toFiniteNumber(u.input);
|
|
20968
|
-
const output = toFiniteNumber(u.output);
|
|
20969
|
-
const cached = toFiniteNumber(u.cacheRead);
|
|
20970
|
-
let callDelta;
|
|
20971
|
-
if (input !== void 0 || output !== void 0) {
|
|
20972
|
-
callDelta = {
|
|
20973
|
-
input: input ?? 0,
|
|
20974
|
-
output: output ?? 0,
|
|
20975
|
-
...cached !== void 0 ? { cached } : {}
|
|
20976
|
-
};
|
|
20977
|
-
tokenUsage = {
|
|
20978
|
-
input: (tokenUsage?.input ?? 0) + callDelta.input,
|
|
20979
|
-
output: (tokenUsage?.output ?? 0) + callDelta.output,
|
|
20980
|
-
...cached !== void 0 ? { cached: (tokenUsage?.cached ?? 0) + cached } : tokenUsage?.cached !== void 0 ? { cached: tokenUsage.cached } : {}
|
|
20981
|
-
};
|
|
20982
|
-
}
|
|
20983
|
-
const cost = u.cost;
|
|
20984
|
-
if (cost && typeof cost === "object") {
|
|
20985
|
-
const total = toFiniteNumber(cost.total);
|
|
20986
|
-
if (total !== void 0) {
|
|
20987
|
-
costUsd = (costUsd ?? 0) + total;
|
|
20988
|
-
}
|
|
20989
|
-
}
|
|
20990
|
-
request.streamCallbacks?.onLlmCallEnd?.(modelId, callDelta);
|
|
20991
|
-
}
|
|
20992
|
-
}
|
|
20993
|
-
break;
|
|
20994
|
-
}
|
|
20995
|
-
case "tool_execution_start": {
|
|
20996
|
-
toolTrackers.set(event.toolCallId, {
|
|
20997
|
-
toolCallId: event.toolCallId,
|
|
20998
|
-
toolName: event.toolName,
|
|
20999
|
-
args: event.args,
|
|
21000
|
-
startMs: Date.now(),
|
|
21001
|
-
startTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
21002
|
-
});
|
|
21003
|
-
request.streamCallbacks?.onToolCallStart?.(event.toolName, event.toolCallId);
|
|
21004
|
-
break;
|
|
21005
|
-
}
|
|
21006
|
-
case "tool_execution_end": {
|
|
21007
|
-
const tracker = toolTrackers.get(event.toolCallId);
|
|
21008
|
-
const durationMs = tracker ? Date.now() - tracker.startMs : 0;
|
|
21009
|
-
completedToolResults.set(event.toolCallId, {
|
|
21010
|
-
output: event.result,
|
|
21011
|
-
durationMs
|
|
21012
|
-
});
|
|
21013
|
-
request.streamCallbacks?.onToolCallEnd?.(
|
|
21014
|
-
event.toolName,
|
|
21015
|
-
tracker?.args,
|
|
21016
|
-
event.result,
|
|
21017
|
-
durationMs,
|
|
21018
|
-
event.toolCallId
|
|
21019
|
-
);
|
|
21020
|
-
toolTrackers.delete(event.toolCallId);
|
|
21021
|
-
break;
|
|
21022
|
-
}
|
|
21023
|
-
}
|
|
21024
|
-
});
|
|
21025
|
-
try {
|
|
21026
|
-
if (this.config.timeoutMs) {
|
|
21027
|
-
const timeoutMs = this.config.timeoutMs;
|
|
21028
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
21029
|
-
setTimeout(
|
|
21030
|
-
() => reject(new Error(`Pi agent SDK timed out after ${timeoutMs}ms`)),
|
|
21031
|
-
timeoutMs
|
|
21032
|
-
);
|
|
21033
|
-
});
|
|
21034
|
-
await Promise.race([agent.prompt(request.question), timeoutPromise]);
|
|
21035
|
-
} else {
|
|
21036
|
-
await agent.prompt(request.question);
|
|
21037
|
-
}
|
|
21038
|
-
await agent.waitForIdle();
|
|
21039
|
-
const agentMessages = agent.state.messages;
|
|
21040
|
-
const output = [];
|
|
21041
|
-
for (const msg of agentMessages) {
|
|
21042
|
-
output.push(convertAgentMessage(msg, toolTrackers, completedToolResults));
|
|
21043
|
-
}
|
|
21044
|
-
const endTimeIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
21045
|
-
const durationMs = Date.now() - startMs;
|
|
21046
|
-
return {
|
|
21047
|
-
raw: {
|
|
21048
|
-
messages: agentMessages,
|
|
21049
|
-
systemPrompt,
|
|
21050
|
-
model: this.config.model,
|
|
21051
|
-
subprovider: this.config.subprovider
|
|
21052
|
-
},
|
|
21053
|
-
output,
|
|
21054
|
-
tokenUsage,
|
|
21055
|
-
costUsd,
|
|
21056
|
-
durationMs,
|
|
21057
|
-
startTime: startTimeIso,
|
|
21058
|
-
endTime: endTimeIso
|
|
21059
|
-
};
|
|
21060
|
-
} finally {
|
|
21061
|
-
unsubscribe();
|
|
21062
|
-
}
|
|
21063
|
-
}
|
|
21064
|
-
};
|
|
21065
|
-
function convertAgentMessage(message, toolTrackers, completedToolResults) {
|
|
21066
|
-
if (!message || typeof message !== "object") {
|
|
21067
|
-
return { role: "unknown", content: String(message) };
|
|
21068
|
-
}
|
|
21069
|
-
const msg = message;
|
|
21070
|
-
const role = typeof msg.role === "string" ? msg.role : "unknown";
|
|
21071
|
-
const content = extractPiTextContent(msg.content);
|
|
21072
|
-
const toolCalls = extractToolCalls3(msg.content, toolTrackers, completedToolResults);
|
|
21073
|
-
const startTime = typeof msg.timestamp === "number" ? new Date(msg.timestamp).toISOString() : typeof msg.timestamp === "string" ? msg.timestamp : void 0;
|
|
21074
|
-
let msgTokenUsage;
|
|
21075
|
-
if (msg.usage && typeof msg.usage === "object") {
|
|
21076
|
-
const u = msg.usage;
|
|
21077
|
-
const input = toFiniteNumber(u.input);
|
|
21078
|
-
const output = toFiniteNumber(u.output);
|
|
21079
|
-
if (input !== void 0 || output !== void 0) {
|
|
21080
|
-
msgTokenUsage = {
|
|
21081
|
-
input: input ?? 0,
|
|
21082
|
-
output: output ?? 0,
|
|
21083
|
-
...toFiniteNumber(u.cacheRead) !== void 0 ? { cached: toFiniteNumber(u.cacheRead) } : {}
|
|
21084
|
-
};
|
|
21085
|
-
}
|
|
21086
|
-
}
|
|
21087
|
-
const metadata = {};
|
|
21088
|
-
if (msg.api) metadata.api = msg.api;
|
|
21089
|
-
if (msg.provider) metadata.provider = msg.provider;
|
|
21090
|
-
if (msg.model) metadata.model = msg.model;
|
|
21091
|
-
if (msg.stopReason) metadata.stopReason = msg.stopReason;
|
|
21092
|
-
return {
|
|
21093
|
-
role,
|
|
21094
|
-
content,
|
|
21095
|
-
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
21096
|
-
startTime,
|
|
21097
|
-
metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
|
|
21098
|
-
tokenUsage: msgTokenUsage
|
|
21099
|
-
};
|
|
21100
|
-
}
|
|
21101
|
-
function extractToolCalls3(content, toolTrackers, completedToolResults) {
|
|
21102
|
-
if (!Array.isArray(content)) {
|
|
21103
|
-
return [];
|
|
21104
|
-
}
|
|
21105
|
-
const toolCalls = [];
|
|
21106
|
-
for (const part of content) {
|
|
21107
|
-
if (!part || typeof part !== "object") {
|
|
21108
|
-
continue;
|
|
21109
|
-
}
|
|
21110
|
-
const p = part;
|
|
21111
|
-
if (p.type === "toolCall" && typeof p.name === "string") {
|
|
21112
|
-
const id = typeof p.id === "string" ? p.id : void 0;
|
|
21113
|
-
const tracker = id ? toolTrackers.get(id) : void 0;
|
|
21114
|
-
const completed = id ? completedToolResults.get(id) : void 0;
|
|
21115
|
-
toolCalls.push({
|
|
21116
|
-
tool: p.name,
|
|
21117
|
-
input: p.arguments,
|
|
21118
|
-
id,
|
|
21119
|
-
output: completed?.output,
|
|
21120
|
-
durationMs: completed?.durationMs,
|
|
21121
|
-
startTime: tracker?.startTime,
|
|
21122
|
-
endTime: tracker?.startTime && completed?.durationMs !== void 0 ? new Date(new Date(tracker.startTime).getTime() + completed.durationMs).toISOString() : void 0
|
|
21123
|
-
});
|
|
21124
|
-
}
|
|
21125
|
-
}
|
|
21126
|
-
return toolCalls;
|
|
21127
|
-
}
|
|
21128
20918
|
var GLOBAL_LOGS_KEY5 = Symbol.for("agentv.piLogs");
|
|
21129
20919
|
var GLOBAL_SUBSCRIBERS_KEY5 = Symbol.for("agentv.piLogSubscribers");
|
|
21130
20920
|
function getPiLogStore() {
|
|
@@ -21176,24 +20966,47 @@ function subscribeToPiLogEntries(listener) {
|
|
|
21176
20966
|
store.delete(listener);
|
|
21177
20967
|
};
|
|
21178
20968
|
}
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
20969
|
+
function extractPiTextContent(content) {
|
|
20970
|
+
if (typeof content === "string") {
|
|
20971
|
+
return content;
|
|
20972
|
+
}
|
|
20973
|
+
if (!Array.isArray(content)) {
|
|
20974
|
+
return void 0;
|
|
20975
|
+
}
|
|
20976
|
+
const textParts = [];
|
|
20977
|
+
for (const part of content) {
|
|
20978
|
+
if (!part || typeof part !== "object") {
|
|
20979
|
+
continue;
|
|
20980
|
+
}
|
|
20981
|
+
const p = part;
|
|
20982
|
+
if (p.type === "text" && typeof p.text === "string") {
|
|
20983
|
+
textParts.push(p.text);
|
|
20984
|
+
}
|
|
20985
|
+
}
|
|
20986
|
+
return textParts.length > 0 ? textParts.join("\n") : void 0;
|
|
20987
|
+
}
|
|
20988
|
+
function toFiniteNumber(value) {
|
|
20989
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
20990
|
+
return void 0;
|
|
20991
|
+
}
|
|
20992
|
+
var WORKSPACE_PREFIX = "agentv-pi-";
|
|
20993
|
+
var PROMPT_FILENAME = "prompt.md";
|
|
20994
|
+
var PiCliProvider = class {
|
|
21182
20995
|
id;
|
|
21183
|
-
kind = "pi-
|
|
20996
|
+
kind = "pi-cli";
|
|
21184
20997
|
targetName;
|
|
21185
20998
|
supportsBatch = false;
|
|
21186
20999
|
config;
|
|
21187
21000
|
runPi;
|
|
21188
21001
|
constructor(targetName, config, runner = defaultPiRunner) {
|
|
21189
|
-
this.id = `pi-
|
|
21002
|
+
this.id = `pi-cli:${targetName}`;
|
|
21190
21003
|
this.targetName = targetName;
|
|
21191
21004
|
this.config = config;
|
|
21192
21005
|
this.runPi = runner;
|
|
21193
21006
|
}
|
|
21194
21007
|
async invoke(request) {
|
|
21195
21008
|
if (request.signal?.aborted) {
|
|
21196
|
-
throw new Error("Pi
|
|
21009
|
+
throw new Error("Pi CLI request was aborted before execution");
|
|
21197
21010
|
}
|
|
21198
21011
|
const inputFiles = normalizeInputFiles(request.inputFiles);
|
|
21199
21012
|
const startTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -21203,17 +21016,17 @@ var PiCodingAgentProvider = class {
|
|
|
21203
21016
|
try {
|
|
21204
21017
|
const promptFile = path17.join(workspaceRoot, PROMPT_FILENAME);
|
|
21205
21018
|
await writeFile(promptFile, request.question, "utf8");
|
|
21206
|
-
const args = this.buildPiArgs(request.question, inputFiles
|
|
21019
|
+
const args = this.buildPiArgs(request.question, inputFiles);
|
|
21207
21020
|
const cwd = this.resolveCwd(workspaceRoot, request.cwd);
|
|
21208
21021
|
const result = await this.executePi(args, cwd, request.signal, logger);
|
|
21209
21022
|
if (result.timedOut) {
|
|
21210
21023
|
throw new Error(
|
|
21211
|
-
`Pi
|
|
21024
|
+
`Pi CLI timed out${formatTimeoutSuffix3(this.config.timeoutMs ?? void 0)}`
|
|
21212
21025
|
);
|
|
21213
21026
|
}
|
|
21214
21027
|
if (result.exitCode !== 0) {
|
|
21215
21028
|
const detail = pickDetail(result.stderr, result.stdout);
|
|
21216
|
-
const prefix = `Pi
|
|
21029
|
+
const prefix = `Pi CLI exited with code ${result.exitCode}`;
|
|
21217
21030
|
throw new Error(detail ? `${prefix}: ${detail}` : prefix);
|
|
21218
21031
|
}
|
|
21219
21032
|
const parsed = parsePiJsonl(result.stdout);
|
|
@@ -21270,7 +21083,7 @@ var PiCodingAgentProvider = class {
|
|
|
21270
21083
|
}
|
|
21271
21084
|
return path17.resolve(this.config.cwd);
|
|
21272
21085
|
}
|
|
21273
|
-
buildPiArgs(prompt, inputFiles
|
|
21086
|
+
buildPiArgs(prompt, inputFiles) {
|
|
21274
21087
|
const args = [];
|
|
21275
21088
|
if (this.config.subprovider) {
|
|
21276
21089
|
args.push("--provider", this.config.subprovider);
|
|
@@ -21322,7 +21135,7 @@ ${prompt}` : prompt;
|
|
|
21322
21135
|
const err = error;
|
|
21323
21136
|
if (err.code === "ENOENT") {
|
|
21324
21137
|
throw new Error(
|
|
21325
|
-
`Pi
|
|
21138
|
+
`Pi CLI executable '${this.config.executable}' was not found. Update the target executable or add it to PATH.`
|
|
21326
21139
|
);
|
|
21327
21140
|
}
|
|
21328
21141
|
throw error;
|
|
@@ -21332,26 +21145,18 @@ ${prompt}` : prompt;
|
|
|
21332
21145
|
const env = { ...process.env };
|
|
21333
21146
|
if (this.config.apiKey) {
|
|
21334
21147
|
const provider = this.config.subprovider?.toLowerCase() ?? "google";
|
|
21335
|
-
|
|
21336
|
-
|
|
21337
|
-
|
|
21338
|
-
|
|
21339
|
-
|
|
21340
|
-
|
|
21341
|
-
|
|
21342
|
-
|
|
21343
|
-
|
|
21344
|
-
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
env.GROQ_API_KEY = this.config.apiKey;
|
|
21348
|
-
break;
|
|
21349
|
-
case "xai":
|
|
21350
|
-
env.XAI_API_KEY = this.config.apiKey;
|
|
21351
|
-
break;
|
|
21352
|
-
case "openrouter":
|
|
21353
|
-
env.OPENROUTER_API_KEY = this.config.apiKey;
|
|
21354
|
-
break;
|
|
21148
|
+
const ENV_KEY_MAP = {
|
|
21149
|
+
google: "GEMINI_API_KEY",
|
|
21150
|
+
gemini: "GEMINI_API_KEY",
|
|
21151
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
21152
|
+
openai: "OPENAI_API_KEY",
|
|
21153
|
+
groq: "GROQ_API_KEY",
|
|
21154
|
+
xai: "XAI_API_KEY",
|
|
21155
|
+
openrouter: "OPENROUTER_API_KEY"
|
|
21156
|
+
};
|
|
21157
|
+
const envKey = ENV_KEY_MAP[provider];
|
|
21158
|
+
if (envKey) {
|
|
21159
|
+
env[envKey] = this.config.apiKey;
|
|
21355
21160
|
}
|
|
21356
21161
|
}
|
|
21357
21162
|
return env;
|
|
@@ -21369,7 +21174,7 @@ ${prompt}` : prompt;
|
|
|
21369
21174
|
if (this.config.logDir) {
|
|
21370
21175
|
return path17.resolve(this.config.logDir);
|
|
21371
21176
|
}
|
|
21372
|
-
return path17.join(process.cwd(), ".agentv", "logs", "pi-
|
|
21177
|
+
return path17.join(process.cwd(), ".agentv", "logs", "pi-cli");
|
|
21373
21178
|
}
|
|
21374
21179
|
async createStreamLogger(request) {
|
|
21375
21180
|
const logDir = this.resolveLogDirectory();
|
|
@@ -21421,7 +21226,7 @@ var PiStreamLogger = class _PiStreamLogger {
|
|
|
21421
21226
|
static async create(options) {
|
|
21422
21227
|
const logger = new _PiStreamLogger(options.filePath, options.format);
|
|
21423
21228
|
const header = [
|
|
21424
|
-
"# Pi
|
|
21229
|
+
"# Pi CLI stream log",
|
|
21425
21230
|
`# target: ${options.targetName}`,
|
|
21426
21231
|
options.evalCaseId ? `# eval: ${options.evalCaseId}` : void 0,
|
|
21427
21232
|
options.attempt !== void 0 ? `# attempt: ${options.attempt + 1}` : void 0,
|
|
@@ -21570,10 +21375,10 @@ function summarizePiEvent(event) {
|
|
|
21570
21375
|
return `${type}: ${role}`;
|
|
21571
21376
|
}
|
|
21572
21377
|
case "message_update": {
|
|
21573
|
-
const
|
|
21574
|
-
const eventType =
|
|
21378
|
+
const evt = record.assistantMessageEvent;
|
|
21379
|
+
const eventType = evt?.type;
|
|
21575
21380
|
if (eventType === "text_delta") {
|
|
21576
|
-
const delta =
|
|
21381
|
+
const delta = evt?.delta;
|
|
21577
21382
|
if (typeof delta === "string") {
|
|
21578
21383
|
const preview = delta.length > 50 ? `${delta.slice(0, 50)}...` : delta;
|
|
21579
21384
|
return `text_delta: ${preview}`;
|
|
@@ -21595,7 +21400,7 @@ function tryParseJsonValue(rawLine) {
|
|
|
21595
21400
|
function parsePiJsonl(output) {
|
|
21596
21401
|
const trimmed = output.trim();
|
|
21597
21402
|
if (trimmed.length === 0) {
|
|
21598
|
-
throw new Error("Pi
|
|
21403
|
+
throw new Error("Pi CLI produced no output");
|
|
21599
21404
|
}
|
|
21600
21405
|
const lines = trimmed.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
21601
21406
|
const parsed = [];
|
|
@@ -21606,38 +21411,27 @@ function parsePiJsonl(output) {
|
|
|
21606
21411
|
}
|
|
21607
21412
|
}
|
|
21608
21413
|
if (parsed.length === 0) {
|
|
21609
|
-
throw new Error("Pi
|
|
21414
|
+
throw new Error("Pi CLI produced no valid JSON output");
|
|
21610
21415
|
}
|
|
21611
21416
|
return parsed;
|
|
21612
21417
|
}
|
|
21613
21418
|
function extractMessages(events) {
|
|
21614
21419
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
21615
21420
|
const event = events[i];
|
|
21616
|
-
if (!event || typeof event !== "object")
|
|
21617
|
-
continue;
|
|
21618
|
-
}
|
|
21421
|
+
if (!event || typeof event !== "object") continue;
|
|
21619
21422
|
const record = event;
|
|
21620
|
-
if (record.type !== "agent_end")
|
|
21621
|
-
continue;
|
|
21622
|
-
}
|
|
21423
|
+
if (record.type !== "agent_end") continue;
|
|
21623
21424
|
const messages = record.messages;
|
|
21624
|
-
if (!Array.isArray(messages))
|
|
21625
|
-
continue;
|
|
21626
|
-
}
|
|
21425
|
+
if (!Array.isArray(messages)) continue;
|
|
21627
21426
|
return messages.map(convertPiMessage).filter((m) => m !== void 0);
|
|
21628
21427
|
}
|
|
21629
21428
|
const output = [];
|
|
21630
21429
|
for (const event of events) {
|
|
21631
|
-
if (!event || typeof event !== "object")
|
|
21632
|
-
continue;
|
|
21633
|
-
}
|
|
21430
|
+
if (!event || typeof event !== "object") continue;
|
|
21634
21431
|
const record = event;
|
|
21635
21432
|
if (record.type === "turn_end") {
|
|
21636
|
-
const
|
|
21637
|
-
|
|
21638
|
-
if (converted) {
|
|
21639
|
-
output.push(converted);
|
|
21640
|
-
}
|
|
21433
|
+
const converted = convertPiMessage(record.message);
|
|
21434
|
+
if (converted) output.push(converted);
|
|
21641
21435
|
}
|
|
21642
21436
|
}
|
|
21643
21437
|
return output;
|
|
@@ -21654,10 +21448,7 @@ function extractTokenUsage(events) {
|
|
|
21654
21448
|
const input = toFiniteNumber(u.input_tokens ?? u.inputTokens ?? u.input);
|
|
21655
21449
|
const output = toFiniteNumber(u.output_tokens ?? u.outputTokens ?? u.output);
|
|
21656
21450
|
if (input !== void 0 || output !== void 0) {
|
|
21657
|
-
const result = {
|
|
21658
|
-
input: input ?? 0,
|
|
21659
|
-
output: output ?? 0
|
|
21660
|
-
};
|
|
21451
|
+
const result = { input: input ?? 0, output: output ?? 0 };
|
|
21661
21452
|
const cached = toFiniteNumber(u.cache_read_input_tokens ?? u.cached ?? u.cachedTokens);
|
|
21662
21453
|
const reasoning = toFiniteNumber(u.reasoning_tokens ?? u.reasoningTokens ?? u.reasoning);
|
|
21663
21454
|
return {
|
|
@@ -21705,16 +21496,12 @@ function aggregateUsageFromMessages(messages) {
|
|
|
21705
21496
|
return result;
|
|
21706
21497
|
}
|
|
21707
21498
|
function convertPiMessage(message) {
|
|
21708
|
-
if (!message || typeof message !== "object")
|
|
21709
|
-
return void 0;
|
|
21710
|
-
}
|
|
21499
|
+
if (!message || typeof message !== "object") return void 0;
|
|
21711
21500
|
const msg = message;
|
|
21712
21501
|
const role = msg.role;
|
|
21713
|
-
if (typeof role !== "string")
|
|
21714
|
-
return void 0;
|
|
21715
|
-
}
|
|
21502
|
+
if (typeof role !== "string") return void 0;
|
|
21716
21503
|
const content = extractPiTextContent(msg.content);
|
|
21717
|
-
const toolCalls =
|
|
21504
|
+
const toolCalls = extractToolCalls3(msg.content);
|
|
21718
21505
|
const startTime = typeof msg.timestamp === "number" ? new Date(msg.timestamp).toISOString() : typeof msg.timestamp === "string" ? msg.timestamp : void 0;
|
|
21719
21506
|
const metadata = {};
|
|
21720
21507
|
if (msg.api) metadata.api = msg.api;
|
|
@@ -21730,15 +21517,11 @@ function convertPiMessage(message) {
|
|
|
21730
21517
|
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
21731
21518
|
};
|
|
21732
21519
|
}
|
|
21733
|
-
function
|
|
21734
|
-
if (!Array.isArray(content))
|
|
21735
|
-
return [];
|
|
21736
|
-
}
|
|
21520
|
+
function extractToolCalls3(content) {
|
|
21521
|
+
if (!Array.isArray(content)) return [];
|
|
21737
21522
|
const toolCalls = [];
|
|
21738
21523
|
for (const part of content) {
|
|
21739
|
-
if (!part || typeof part !== "object")
|
|
21740
|
-
continue;
|
|
21741
|
-
}
|
|
21524
|
+
if (!part || typeof part !== "object") continue;
|
|
21742
21525
|
const p = part;
|
|
21743
21526
|
if (p.type === "tool_use" && typeof p.name === "string") {
|
|
21744
21527
|
toolCalls.push({
|
|
@@ -21758,10 +21541,7 @@ function extractToolCalls4(content) {
|
|
|
21758
21541
|
const existing = toolCalls.find((tc) => tc.id === p.tool_use_id);
|
|
21759
21542
|
if (existing) {
|
|
21760
21543
|
const idx = toolCalls.indexOf(existing);
|
|
21761
|
-
toolCalls[idx] = {
|
|
21762
|
-
...existing,
|
|
21763
|
-
output: p.content
|
|
21764
|
-
};
|
|
21544
|
+
toolCalls[idx] = { ...existing, output: p.content };
|
|
21765
21545
|
}
|
|
21766
21546
|
}
|
|
21767
21547
|
}
|
|
@@ -21772,18 +21552,13 @@ function escapeAtSymbols(prompt) {
|
|
|
21772
21552
|
}
|
|
21773
21553
|
function pickDetail(stderr, stdout) {
|
|
21774
21554
|
const errorText = stderr.trim();
|
|
21775
|
-
if (errorText.length > 0)
|
|
21776
|
-
return errorText;
|
|
21777
|
-
}
|
|
21555
|
+
if (errorText.length > 0) return errorText;
|
|
21778
21556
|
const stdoutText = stdout.trim();
|
|
21779
21557
|
return stdoutText.length > 0 ? stdoutText : void 0;
|
|
21780
21558
|
}
|
|
21781
21559
|
function formatTimeoutSuffix3(timeoutMs) {
|
|
21782
|
-
if (!timeoutMs || timeoutMs <= 0)
|
|
21783
|
-
|
|
21784
|
-
}
|
|
21785
|
-
const seconds = Math.ceil(timeoutMs / 1e3);
|
|
21786
|
-
return ` after ${seconds}s`;
|
|
21560
|
+
if (!timeoutMs || timeoutMs <= 0) return "";
|
|
21561
|
+
return ` after ${Math.ceil(timeoutMs / 1e3)}s`;
|
|
21787
21562
|
}
|
|
21788
21563
|
async function defaultPiRunner(options) {
|
|
21789
21564
|
return await new Promise((resolve2, reject) => {
|
|
@@ -21830,12 +21605,8 @@ async function defaultPiRunner(options) {
|
|
|
21830
21605
|
});
|
|
21831
21606
|
child.stdin.end();
|
|
21832
21607
|
const cleanup = () => {
|
|
21833
|
-
if (timeoutHandle)
|
|
21834
|
-
|
|
21835
|
-
}
|
|
21836
|
-
if (options.signal) {
|
|
21837
|
-
options.signal.removeEventListener("abort", onAbort);
|
|
21838
|
-
}
|
|
21608
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
21609
|
+
if (options.signal) options.signal.removeEventListener("abort", onAbort);
|
|
21839
21610
|
};
|
|
21840
21611
|
child.on("error", (error) => {
|
|
21841
21612
|
cleanup();
|
|
@@ -21852,6 +21623,460 @@ async function defaultPiRunner(options) {
|
|
|
21852
21623
|
});
|
|
21853
21624
|
});
|
|
21854
21625
|
}
|
|
21626
|
+
var piCodingAgentModule = null;
|
|
21627
|
+
var piAiModule = null;
|
|
21628
|
+
async function promptInstall() {
|
|
21629
|
+
if (!process.stdout.isTTY) return false;
|
|
21630
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
21631
|
+
try {
|
|
21632
|
+
return await new Promise((resolve2) => {
|
|
21633
|
+
rl.question(
|
|
21634
|
+
"@mariozechner/pi-coding-agent is not installed. Install it now? (y/N) ",
|
|
21635
|
+
(answer) => resolve2(answer.trim().toLowerCase() === "y")
|
|
21636
|
+
);
|
|
21637
|
+
});
|
|
21638
|
+
} finally {
|
|
21639
|
+
rl.close();
|
|
21640
|
+
}
|
|
21641
|
+
}
|
|
21642
|
+
async function loadSdkModules() {
|
|
21643
|
+
if (!piCodingAgentModule || !piAiModule) {
|
|
21644
|
+
try {
|
|
21645
|
+
[piCodingAgentModule, piAiModule] = await Promise.all([
|
|
21646
|
+
import("@mariozechner/pi-coding-agent"),
|
|
21647
|
+
import("@mariozechner/pi-ai")
|
|
21648
|
+
]);
|
|
21649
|
+
} catch {
|
|
21650
|
+
if (await promptInstall()) {
|
|
21651
|
+
console.error("Installing @mariozechner/pi-coding-agent...");
|
|
21652
|
+
execSync("bun add @mariozechner/pi-coding-agent", { stdio: "inherit" });
|
|
21653
|
+
[piCodingAgentModule, piAiModule] = await Promise.all([
|
|
21654
|
+
import("@mariozechner/pi-coding-agent"),
|
|
21655
|
+
import("@mariozechner/pi-ai")
|
|
21656
|
+
]);
|
|
21657
|
+
} else {
|
|
21658
|
+
throw new Error(
|
|
21659
|
+
"pi-coding-agent SDK is not installed. Install it with:\n bun add @mariozechner/pi-coding-agent"
|
|
21660
|
+
);
|
|
21661
|
+
}
|
|
21662
|
+
}
|
|
21663
|
+
}
|
|
21664
|
+
const toolMap = {
|
|
21665
|
+
read: piCodingAgentModule.readTool,
|
|
21666
|
+
bash: piCodingAgentModule.bashTool,
|
|
21667
|
+
edit: piCodingAgentModule.editTool,
|
|
21668
|
+
write: piCodingAgentModule.writeTool,
|
|
21669
|
+
grep: piCodingAgentModule.grepTool,
|
|
21670
|
+
find: piCodingAgentModule.findTool,
|
|
21671
|
+
ls: piCodingAgentModule.lsTool
|
|
21672
|
+
};
|
|
21673
|
+
return {
|
|
21674
|
+
createAgentSession: piCodingAgentModule.createAgentSession,
|
|
21675
|
+
codingTools: piCodingAgentModule.codingTools,
|
|
21676
|
+
toolMap,
|
|
21677
|
+
SessionManager: piCodingAgentModule.SessionManager,
|
|
21678
|
+
getModel: piAiModule.getModel
|
|
21679
|
+
};
|
|
21680
|
+
}
|
|
21681
|
+
var PiCodingAgentProvider = class {
|
|
21682
|
+
id;
|
|
21683
|
+
kind = "pi-coding-agent";
|
|
21684
|
+
targetName;
|
|
21685
|
+
supportsBatch = false;
|
|
21686
|
+
config;
|
|
21687
|
+
constructor(targetName, config) {
|
|
21688
|
+
this.id = `pi-coding-agent:${targetName}`;
|
|
21689
|
+
this.targetName = targetName;
|
|
21690
|
+
this.config = config;
|
|
21691
|
+
}
|
|
21692
|
+
async invoke(request) {
|
|
21693
|
+
if (request.signal?.aborted) {
|
|
21694
|
+
throw new Error("Pi coding agent request was aborted before execution");
|
|
21695
|
+
}
|
|
21696
|
+
const inputFiles = normalizeInputFiles(request.inputFiles);
|
|
21697
|
+
const startTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
21698
|
+
const startMs = Date.now();
|
|
21699
|
+
const sdk = await loadSdkModules();
|
|
21700
|
+
const logger = await this.createStreamLogger(request).catch(() => void 0);
|
|
21701
|
+
try {
|
|
21702
|
+
const cwd = this.resolveCwd(request.cwd);
|
|
21703
|
+
const providerName = this.config.subprovider ?? "google";
|
|
21704
|
+
const modelId = this.config.model ?? "gemini-2.5-flash";
|
|
21705
|
+
this.setApiKeyEnv(providerName);
|
|
21706
|
+
const model = sdk.getModel(providerName, modelId);
|
|
21707
|
+
const tools = this.resolveTools(sdk);
|
|
21708
|
+
const { session } = await sdk.createAgentSession({
|
|
21709
|
+
cwd,
|
|
21710
|
+
model,
|
|
21711
|
+
tools,
|
|
21712
|
+
thinkingLevel: this.config.thinking,
|
|
21713
|
+
sessionManager: sdk.SessionManager.inMemory(cwd)
|
|
21714
|
+
});
|
|
21715
|
+
let tokenUsage;
|
|
21716
|
+
let costUsd;
|
|
21717
|
+
const toolTrackers = /* @__PURE__ */ new Map();
|
|
21718
|
+
const completedToolResults = /* @__PURE__ */ new Map();
|
|
21719
|
+
const unsubscribe = session.subscribe((event) => {
|
|
21720
|
+
logger?.handleEvent(event);
|
|
21721
|
+
switch (event.type) {
|
|
21722
|
+
case "message_end": {
|
|
21723
|
+
const msg = event.message;
|
|
21724
|
+
if (msg && typeof msg === "object" && "role" in msg && msg.role === "assistant" && "usage" in msg) {
|
|
21725
|
+
const usage = msg.usage;
|
|
21726
|
+
if (usage && typeof usage === "object") {
|
|
21727
|
+
const u = usage;
|
|
21728
|
+
const input = toFiniteNumber(u.input);
|
|
21729
|
+
const output = toFiniteNumber(u.output);
|
|
21730
|
+
const cached = toFiniteNumber(u.cacheRead);
|
|
21731
|
+
let callDelta;
|
|
21732
|
+
if (input !== void 0 || output !== void 0) {
|
|
21733
|
+
callDelta = {
|
|
21734
|
+
input: input ?? 0,
|
|
21735
|
+
output: output ?? 0,
|
|
21736
|
+
...cached !== void 0 ? { cached } : {}
|
|
21737
|
+
};
|
|
21738
|
+
tokenUsage = {
|
|
21739
|
+
input: (tokenUsage?.input ?? 0) + callDelta.input,
|
|
21740
|
+
output: (tokenUsage?.output ?? 0) + callDelta.output,
|
|
21741
|
+
...cached !== void 0 ? { cached: (tokenUsage?.cached ?? 0) + cached } : tokenUsage?.cached !== void 0 ? { cached: tokenUsage.cached } : {}
|
|
21742
|
+
};
|
|
21743
|
+
}
|
|
21744
|
+
const cost = u.cost;
|
|
21745
|
+
if (cost && typeof cost === "object") {
|
|
21746
|
+
const total = toFiniteNumber(cost.total);
|
|
21747
|
+
if (total !== void 0) {
|
|
21748
|
+
costUsd = (costUsd ?? 0) + total;
|
|
21749
|
+
}
|
|
21750
|
+
}
|
|
21751
|
+
request.streamCallbacks?.onLlmCallEnd?.(modelId, callDelta);
|
|
21752
|
+
}
|
|
21753
|
+
}
|
|
21754
|
+
break;
|
|
21755
|
+
}
|
|
21756
|
+
case "tool_execution_start": {
|
|
21757
|
+
toolTrackers.set(event.toolCallId, {
|
|
21758
|
+
toolCallId: event.toolCallId,
|
|
21759
|
+
toolName: event.toolName,
|
|
21760
|
+
args: event.args,
|
|
21761
|
+
startMs: Date.now(),
|
|
21762
|
+
startTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
21763
|
+
});
|
|
21764
|
+
request.streamCallbacks?.onToolCallStart?.(event.toolName, event.toolCallId);
|
|
21765
|
+
break;
|
|
21766
|
+
}
|
|
21767
|
+
case "tool_execution_end": {
|
|
21768
|
+
const tracker = toolTrackers.get(event.toolCallId);
|
|
21769
|
+
const durationMs = tracker ? Date.now() - tracker.startMs : 0;
|
|
21770
|
+
completedToolResults.set(event.toolCallId, {
|
|
21771
|
+
output: event.result,
|
|
21772
|
+
durationMs
|
|
21773
|
+
});
|
|
21774
|
+
request.streamCallbacks?.onToolCallEnd?.(
|
|
21775
|
+
event.toolName,
|
|
21776
|
+
tracker?.args,
|
|
21777
|
+
event.result,
|
|
21778
|
+
durationMs,
|
|
21779
|
+
event.toolCallId
|
|
21780
|
+
);
|
|
21781
|
+
toolTrackers.delete(event.toolCallId);
|
|
21782
|
+
break;
|
|
21783
|
+
}
|
|
21784
|
+
}
|
|
21785
|
+
});
|
|
21786
|
+
try {
|
|
21787
|
+
const systemPrompt = this.config.systemPrompt;
|
|
21788
|
+
let prompt = request.question;
|
|
21789
|
+
if (systemPrompt) {
|
|
21790
|
+
prompt = `${systemPrompt}
|
|
21791
|
+
|
|
21792
|
+
${prompt}`;
|
|
21793
|
+
}
|
|
21794
|
+
if (inputFiles && inputFiles.length > 0) {
|
|
21795
|
+
const fileList = inputFiles.map((f) => `@${f}`).join("\n");
|
|
21796
|
+
prompt = `${prompt}
|
|
21797
|
+
|
|
21798
|
+
Files:
|
|
21799
|
+
${fileList}`;
|
|
21800
|
+
}
|
|
21801
|
+
if (this.config.timeoutMs) {
|
|
21802
|
+
const timeoutMs = this.config.timeoutMs;
|
|
21803
|
+
let timeoutId;
|
|
21804
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
21805
|
+
timeoutId = setTimeout(
|
|
21806
|
+
() => reject(
|
|
21807
|
+
new Error(`Pi coding agent timed out after ${Math.ceil(timeoutMs / 1e3)}s`)
|
|
21808
|
+
),
|
|
21809
|
+
timeoutMs
|
|
21810
|
+
);
|
|
21811
|
+
});
|
|
21812
|
+
try {
|
|
21813
|
+
await Promise.race([session.prompt(prompt), timeoutPromise]);
|
|
21814
|
+
} finally {
|
|
21815
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
21816
|
+
}
|
|
21817
|
+
} else {
|
|
21818
|
+
await session.prompt(prompt);
|
|
21819
|
+
}
|
|
21820
|
+
const agentMessages = session.agent.state.messages;
|
|
21821
|
+
const output = [];
|
|
21822
|
+
for (const msg of agentMessages) {
|
|
21823
|
+
output.push(convertAgentMessage(msg, toolTrackers, completedToolResults));
|
|
21824
|
+
}
|
|
21825
|
+
const endTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
21826
|
+
const durationMs = Date.now() - startMs;
|
|
21827
|
+
return {
|
|
21828
|
+
raw: {
|
|
21829
|
+
messages: agentMessages,
|
|
21830
|
+
model: this.config.model,
|
|
21831
|
+
provider: this.config.subprovider
|
|
21832
|
+
},
|
|
21833
|
+
output,
|
|
21834
|
+
tokenUsage,
|
|
21835
|
+
costUsd,
|
|
21836
|
+
durationMs,
|
|
21837
|
+
startTime,
|
|
21838
|
+
endTime
|
|
21839
|
+
};
|
|
21840
|
+
} finally {
|
|
21841
|
+
unsubscribe();
|
|
21842
|
+
session.dispose();
|
|
21843
|
+
}
|
|
21844
|
+
} finally {
|
|
21845
|
+
await logger?.close();
|
|
21846
|
+
}
|
|
21847
|
+
}
|
|
21848
|
+
/** Maps config apiKey to the provider-specific env var the SDK reads. */
|
|
21849
|
+
setApiKeyEnv(providerName) {
|
|
21850
|
+
if (!this.config.apiKey) return;
|
|
21851
|
+
const ENV_KEY_MAP = {
|
|
21852
|
+
google: "GEMINI_API_KEY",
|
|
21853
|
+
gemini: "GEMINI_API_KEY",
|
|
21854
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
21855
|
+
openai: "OPENAI_API_KEY",
|
|
21856
|
+
groq: "GROQ_API_KEY",
|
|
21857
|
+
xai: "XAI_API_KEY",
|
|
21858
|
+
openrouter: "OPENROUTER_API_KEY"
|
|
21859
|
+
};
|
|
21860
|
+
const envKey = ENV_KEY_MAP[providerName.toLowerCase()];
|
|
21861
|
+
if (envKey) {
|
|
21862
|
+
process.env[envKey] = this.config.apiKey;
|
|
21863
|
+
}
|
|
21864
|
+
}
|
|
21865
|
+
resolveCwd(cwdOverride) {
|
|
21866
|
+
if (cwdOverride) {
|
|
21867
|
+
return path18.resolve(cwdOverride);
|
|
21868
|
+
}
|
|
21869
|
+
if (this.config.cwd) {
|
|
21870
|
+
return path18.resolve(this.config.cwd);
|
|
21871
|
+
}
|
|
21872
|
+
return process.cwd();
|
|
21873
|
+
}
|
|
21874
|
+
resolveTools(sdk) {
|
|
21875
|
+
if (!this.config.tools) {
|
|
21876
|
+
return sdk.codingTools;
|
|
21877
|
+
}
|
|
21878
|
+
const toolNames = this.config.tools.split(",").map((t) => t.trim().toLowerCase());
|
|
21879
|
+
const selected = [];
|
|
21880
|
+
for (const name21 of toolNames) {
|
|
21881
|
+
if (name21 in sdk.toolMap) {
|
|
21882
|
+
selected.push(sdk.toolMap[name21]);
|
|
21883
|
+
}
|
|
21884
|
+
}
|
|
21885
|
+
return selected.length > 0 ? selected : sdk.codingTools;
|
|
21886
|
+
}
|
|
21887
|
+
resolveLogDirectory() {
|
|
21888
|
+
if (this.config.logDir) {
|
|
21889
|
+
return path18.resolve(this.config.logDir);
|
|
21890
|
+
}
|
|
21891
|
+
return path18.join(process.cwd(), ".agentv", "logs", "pi-coding-agent");
|
|
21892
|
+
}
|
|
21893
|
+
async createStreamLogger(request) {
|
|
21894
|
+
const logDir = this.resolveLogDirectory();
|
|
21895
|
+
if (!logDir) {
|
|
21896
|
+
return void 0;
|
|
21897
|
+
}
|
|
21898
|
+
try {
|
|
21899
|
+
await mkdir7(logDir, { recursive: true });
|
|
21900
|
+
} catch (error) {
|
|
21901
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
21902
|
+
console.warn(`Skipping Pi stream logging (could not create ${logDir}): ${message}`);
|
|
21903
|
+
return void 0;
|
|
21904
|
+
}
|
|
21905
|
+
const filePath = path18.join(logDir, buildLogFilename6(request, this.targetName));
|
|
21906
|
+
try {
|
|
21907
|
+
const logger = await PiStreamLogger2.create({
|
|
21908
|
+
filePath,
|
|
21909
|
+
targetName: this.targetName,
|
|
21910
|
+
evalCaseId: request.evalCaseId,
|
|
21911
|
+
attempt: request.attempt,
|
|
21912
|
+
format: this.config.logFormat ?? "summary"
|
|
21913
|
+
});
|
|
21914
|
+
recordPiLogEntry({
|
|
21915
|
+
filePath,
|
|
21916
|
+
targetName: this.targetName,
|
|
21917
|
+
evalCaseId: request.evalCaseId,
|
|
21918
|
+
attempt: request.attempt
|
|
21919
|
+
});
|
|
21920
|
+
return logger;
|
|
21921
|
+
} catch (error) {
|
|
21922
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
21923
|
+
console.warn(`Skipping Pi stream logging for ${filePath}: ${message}`);
|
|
21924
|
+
return void 0;
|
|
21925
|
+
}
|
|
21926
|
+
}
|
|
21927
|
+
};
|
|
21928
|
+
var PiStreamLogger2 = class _PiStreamLogger2 {
|
|
21929
|
+
filePath;
|
|
21930
|
+
stream;
|
|
21931
|
+
startedAt = Date.now();
|
|
21932
|
+
format;
|
|
21933
|
+
constructor(filePath, format) {
|
|
21934
|
+
this.filePath = filePath;
|
|
21935
|
+
this.format = format;
|
|
21936
|
+
this.stream = createWriteStream6(filePath, { flags: "a" });
|
|
21937
|
+
}
|
|
21938
|
+
static async create(options) {
|
|
21939
|
+
const logger = new _PiStreamLogger2(options.filePath, options.format);
|
|
21940
|
+
const header = [
|
|
21941
|
+
"# Pi Coding Agent stream log",
|
|
21942
|
+
`# target: ${options.targetName}`,
|
|
21943
|
+
options.evalCaseId ? `# eval: ${options.evalCaseId}` : void 0,
|
|
21944
|
+
options.attempt !== void 0 ? `# attempt: ${options.attempt + 1}` : void 0,
|
|
21945
|
+
`# started: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
21946
|
+
""
|
|
21947
|
+
].filter((line) => Boolean(line));
|
|
21948
|
+
for (const line of header) {
|
|
21949
|
+
logger.stream.write(`${line}
|
|
21950
|
+
`);
|
|
21951
|
+
}
|
|
21952
|
+
return logger;
|
|
21953
|
+
}
|
|
21954
|
+
handleEvent(event) {
|
|
21955
|
+
if (!event || typeof event !== "object") return;
|
|
21956
|
+
const record = event;
|
|
21957
|
+
const type = typeof record.type === "string" ? record.type : void 0;
|
|
21958
|
+
if (!type) return;
|
|
21959
|
+
const message = this.format === "json" ? JSON.stringify(event, null, 2) : summarizeSdkEvent2(event);
|
|
21960
|
+
if (message) {
|
|
21961
|
+
this.stream.write(`[+${formatElapsed6(this.startedAt)}] ${message}
|
|
21962
|
+
`);
|
|
21963
|
+
}
|
|
21964
|
+
}
|
|
21965
|
+
async close() {
|
|
21966
|
+
await new Promise((resolve2, reject) => {
|
|
21967
|
+
this.stream.once("error", reject);
|
|
21968
|
+
this.stream.end(() => resolve2());
|
|
21969
|
+
});
|
|
21970
|
+
}
|
|
21971
|
+
};
|
|
21972
|
+
function summarizeSdkEvent2(event) {
|
|
21973
|
+
if (!event || typeof event !== "object") return void 0;
|
|
21974
|
+
const record = event;
|
|
21975
|
+
const type = typeof record.type === "string" ? record.type : void 0;
|
|
21976
|
+
if (!type) return void 0;
|
|
21977
|
+
switch (type) {
|
|
21978
|
+
case "agent_start":
|
|
21979
|
+
case "agent_end":
|
|
21980
|
+
case "turn_start":
|
|
21981
|
+
case "turn_end":
|
|
21982
|
+
return type;
|
|
21983
|
+
case "message_start":
|
|
21984
|
+
case "message_end": {
|
|
21985
|
+
const msg = record.message;
|
|
21986
|
+
return `${type}: ${msg?.role ?? "unknown"}`;
|
|
21987
|
+
}
|
|
21988
|
+
case "tool_execution_start":
|
|
21989
|
+
return `tool_start: ${record.toolName}`;
|
|
21990
|
+
case "tool_execution_end":
|
|
21991
|
+
return `tool_end: ${record.toolName}`;
|
|
21992
|
+
default:
|
|
21993
|
+
return type;
|
|
21994
|
+
}
|
|
21995
|
+
}
|
|
21996
|
+
function buildLogFilename6(request, targetName) {
|
|
21997
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
21998
|
+
const evalId = sanitizeForFilename6(request.evalCaseId ?? "pi");
|
|
21999
|
+
const attemptSuffix = request.attempt !== void 0 ? `_attempt-${request.attempt + 1}` : "";
|
|
22000
|
+
const target = sanitizeForFilename6(targetName);
|
|
22001
|
+
return `${timestamp}_${target}_${evalId}${attemptSuffix}_${randomUUID8().slice(0, 8)}.log`;
|
|
22002
|
+
}
|
|
22003
|
+
function sanitizeForFilename6(value) {
|
|
22004
|
+
const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
22005
|
+
return sanitized.length > 0 ? sanitized : "pi";
|
|
22006
|
+
}
|
|
22007
|
+
function formatElapsed6(startedAt) {
|
|
22008
|
+
const elapsedSeconds = Math.floor((Date.now() - startedAt) / 1e3);
|
|
22009
|
+
const hours = Math.floor(elapsedSeconds / 3600);
|
|
22010
|
+
const minutes = Math.floor(elapsedSeconds % 3600 / 60);
|
|
22011
|
+
const seconds = elapsedSeconds % 60;
|
|
22012
|
+
if (hours > 0) {
|
|
22013
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
22014
|
+
}
|
|
22015
|
+
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
22016
|
+
}
|
|
22017
|
+
function convertAgentMessage(message, toolTrackers, completedToolResults) {
|
|
22018
|
+
if (!message || typeof message !== "object") {
|
|
22019
|
+
return { role: "unknown", content: String(message) };
|
|
22020
|
+
}
|
|
22021
|
+
const msg = message;
|
|
22022
|
+
const role = typeof msg.role === "string" ? msg.role : "unknown";
|
|
22023
|
+
const content = extractPiTextContent(msg.content);
|
|
22024
|
+
const toolCalls = extractToolCalls4(msg.content, toolTrackers, completedToolResults);
|
|
22025
|
+
const startTimeVal = typeof msg.timestamp === "number" ? new Date(msg.timestamp).toISOString() : typeof msg.timestamp === "string" ? msg.timestamp : void 0;
|
|
22026
|
+
let msgTokenUsage;
|
|
22027
|
+
if (msg.usage && typeof msg.usage === "object") {
|
|
22028
|
+
const u = msg.usage;
|
|
22029
|
+
const input = toFiniteNumber(u.input);
|
|
22030
|
+
const output = toFiniteNumber(u.output);
|
|
22031
|
+
if (input !== void 0 || output !== void 0) {
|
|
22032
|
+
msgTokenUsage = {
|
|
22033
|
+
input: input ?? 0,
|
|
22034
|
+
output: output ?? 0,
|
|
22035
|
+
...toFiniteNumber(u.cacheRead) !== void 0 ? { cached: toFiniteNumber(u.cacheRead) } : {}
|
|
22036
|
+
};
|
|
22037
|
+
}
|
|
22038
|
+
}
|
|
22039
|
+
const metadata = {};
|
|
22040
|
+
if (msg.api) metadata.api = msg.api;
|
|
22041
|
+
if (msg.provider) metadata.provider = msg.provider;
|
|
22042
|
+
if (msg.model) metadata.model = msg.model;
|
|
22043
|
+
if (msg.stopReason) metadata.stopReason = msg.stopReason;
|
|
22044
|
+
return {
|
|
22045
|
+
role,
|
|
22046
|
+
content,
|
|
22047
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
22048
|
+
startTime: startTimeVal,
|
|
22049
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
|
|
22050
|
+
tokenUsage: msgTokenUsage
|
|
22051
|
+
};
|
|
22052
|
+
}
|
|
22053
|
+
function extractToolCalls4(content, toolTrackers, completedToolResults) {
|
|
22054
|
+
if (!Array.isArray(content)) {
|
|
22055
|
+
return [];
|
|
22056
|
+
}
|
|
22057
|
+
const toolCalls = [];
|
|
22058
|
+
for (const part of content) {
|
|
22059
|
+
if (!part || typeof part !== "object") {
|
|
22060
|
+
continue;
|
|
22061
|
+
}
|
|
22062
|
+
const p = part;
|
|
22063
|
+
if (p.type === "toolCall" && typeof p.name === "string") {
|
|
22064
|
+
const id = typeof p.id === "string" ? p.id : void 0;
|
|
22065
|
+
const tracker = id ? toolTrackers.get(id) : void 0;
|
|
22066
|
+
const completed = id ? completedToolResults.get(id) : void 0;
|
|
22067
|
+
toolCalls.push({
|
|
22068
|
+
tool: p.name,
|
|
22069
|
+
input: p.arguments,
|
|
22070
|
+
id,
|
|
22071
|
+
output: completed?.output,
|
|
22072
|
+
durationMs: completed?.durationMs,
|
|
22073
|
+
startTime: tracker?.startTime,
|
|
22074
|
+
endTime: tracker?.startTime && completed?.durationMs !== void 0 ? new Date(new Date(tracker.startTime).getTime() + completed.durationMs).toISOString() : void 0
|
|
22075
|
+
});
|
|
22076
|
+
}
|
|
22077
|
+
}
|
|
22078
|
+
return toolCalls;
|
|
22079
|
+
}
|
|
21855
22080
|
var ProviderRegistry = class {
|
|
21856
22081
|
factories = /* @__PURE__ */ new Map();
|
|
21857
22082
|
/** Register a factory function for a provider kind. */
|
|
@@ -21894,13 +22119,13 @@ async function pathExists(target) {
|
|
|
21894
22119
|
}
|
|
21895
22120
|
}
|
|
21896
22121
|
async function ensureDir(target) {
|
|
21897
|
-
await
|
|
22122
|
+
await mkdir8(target, { recursive: true });
|
|
21898
22123
|
}
|
|
21899
22124
|
async function readDirEntries(target) {
|
|
21900
22125
|
const entries = await readdir(target, { withFileTypes: true });
|
|
21901
22126
|
return entries.map((entry) => ({
|
|
21902
22127
|
name: entry.name,
|
|
21903
|
-
absolutePath:
|
|
22128
|
+
absolutePath: path19.join(target, entry.name),
|
|
21904
22129
|
isDirectory: entry.isDirectory()
|
|
21905
22130
|
}));
|
|
21906
22131
|
}
|
|
@@ -21914,7 +22139,7 @@ async function removeIfExists(target) {
|
|
|
21914
22139
|
}
|
|
21915
22140
|
}
|
|
21916
22141
|
function pathToFileUri2(filePath) {
|
|
21917
|
-
const absolutePath =
|
|
22142
|
+
const absolutePath = path20.isAbsolute(filePath) ? filePath : path20.resolve(filePath);
|
|
21918
22143
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
21919
22144
|
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
21920
22145
|
return `file:///${normalizedPath}`;
|
|
@@ -22006,8 +22231,8 @@ function createBatchRequestPrompt(userQuery, responseFileTmp, responseFileFinal,
|
|
|
22006
22231
|
});
|
|
22007
22232
|
}
|
|
22008
22233
|
function createBatchOrchestratorPrompt(requestFiles, responseFiles, templateContent) {
|
|
22009
|
-
const requestLines = requestFiles.map((file, index) => `${index + 1}. messages/${
|
|
22010
|
-
const responseList = responseFiles.map((file) => `"${
|
|
22234
|
+
const requestLines = requestFiles.map((file, index) => `${index + 1}. messages/${path21.basename(file)}`).join("\n");
|
|
22235
|
+
const responseList = responseFiles.map((file) => `"${path21.basename(file)}"`).join(", ");
|
|
22011
22236
|
return renderTemplate2(templateContent, {
|
|
22012
22237
|
requestFiles: requestLines,
|
|
22013
22238
|
responseList
|
|
@@ -22067,7 +22292,7 @@ async function waitForResponseOutput(responseFileFinal, pollInterval = 1e3, sile
|
|
|
22067
22292
|
}
|
|
22068
22293
|
async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, silent = false, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
22069
22294
|
if (!silent) {
|
|
22070
|
-
const fileList = responseFilesFinal.map((file) =>
|
|
22295
|
+
const fileList = responseFilesFinal.map((file) => path222.basename(file)).join(", ");
|
|
22071
22296
|
console.error(`waiting for ${responseFilesFinal.length} batch response(s): ${fileList}`);
|
|
22072
22297
|
}
|
|
22073
22298
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -22076,7 +22301,7 @@ async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, sil
|
|
|
22076
22301
|
while (pending.size > 0) {
|
|
22077
22302
|
if (Date.now() >= deadline) {
|
|
22078
22303
|
if (!silent) {
|
|
22079
|
-
const remaining = [...pending].map((f) =>
|
|
22304
|
+
const remaining = [...pending].map((f) => path222.basename(f)).join(", ");
|
|
22080
22305
|
console.error(
|
|
22081
22306
|
`error: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for batch responses. Still pending: ${remaining}`
|
|
22082
22307
|
);
|
|
@@ -22133,25 +22358,25 @@ function getAgentvHome() {
|
|
|
22133
22358
|
}
|
|
22134
22359
|
return envHome;
|
|
22135
22360
|
}
|
|
22136
|
-
return
|
|
22361
|
+
return path23.join(os2.homedir(), ".agentv");
|
|
22137
22362
|
}
|
|
22138
22363
|
function getWorkspacesRoot() {
|
|
22139
|
-
return
|
|
22364
|
+
return path23.join(getAgentvHome(), "workspaces");
|
|
22140
22365
|
}
|
|
22141
22366
|
function getSubagentsRoot() {
|
|
22142
|
-
return
|
|
22367
|
+
return path23.join(getAgentvHome(), "subagents");
|
|
22143
22368
|
}
|
|
22144
22369
|
function getTraceStateRoot() {
|
|
22145
|
-
return
|
|
22370
|
+
return path23.join(getAgentvHome(), "trace-state");
|
|
22146
22371
|
}
|
|
22147
22372
|
function getWorkspacePoolRoot() {
|
|
22148
|
-
return
|
|
22373
|
+
return path23.join(getAgentvHome(), "workspace-pool");
|
|
22149
22374
|
}
|
|
22150
22375
|
var DEFAULT_LOCK_NAME = "subagent.lock";
|
|
22151
22376
|
var DEFAULT_ALIVE_FILENAME = ".alive";
|
|
22152
22377
|
function getDefaultSubagentRoot(vscodeCmd = "code") {
|
|
22153
22378
|
const folder = vscodeCmd === "code-insiders" ? "vscode-insiders-agents" : "vscode-agents";
|
|
22154
|
-
return
|
|
22379
|
+
return path24.join(getSubagentsRoot(), folder);
|
|
22155
22380
|
}
|
|
22156
22381
|
var DEFAULT_SUBAGENT_ROOT = getDefaultSubagentRoot();
|
|
22157
22382
|
var execAsync2 = promisify2(exec);
|
|
@@ -22216,11 +22441,11 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
22216
22441
|
await raceSpawnError(child);
|
|
22217
22442
|
return true;
|
|
22218
22443
|
}
|
|
22219
|
-
const aliveFile =
|
|
22444
|
+
const aliveFile = path25.join(subagentDir, DEFAULT_ALIVE_FILENAME);
|
|
22220
22445
|
await removeIfExists(aliveFile);
|
|
22221
|
-
const githubAgentsDir =
|
|
22222
|
-
await
|
|
22223
|
-
const wakeupDst =
|
|
22446
|
+
const githubAgentsDir = path25.join(subagentDir, ".github", "agents");
|
|
22447
|
+
await mkdir9(githubAgentsDir, { recursive: true });
|
|
22448
|
+
const wakeupDst = path25.join(githubAgentsDir, "wakeup.md");
|
|
22224
22449
|
await writeFile2(wakeupDst, DEFAULT_WAKEUP_CONTENT, "utf8");
|
|
22225
22450
|
const workspaceChild = spawnVsCode(vscodeCmd, [workspacePath], {
|
|
22226
22451
|
label: "open-workspace"
|
|
@@ -22233,7 +22458,7 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
22233
22458
|
"chat",
|
|
22234
22459
|
"-m",
|
|
22235
22460
|
wakeupChatId,
|
|
22236
|
-
`create a file named .alive in the ${
|
|
22461
|
+
`create a file named .alive in the ${path25.basename(subagentDir)} folder`
|
|
22237
22462
|
];
|
|
22238
22463
|
const wakeupChild = spawnVsCode(vscodeCmd, chatArgs, { label: "send-wakeup-chat" });
|
|
22239
22464
|
await raceSpawnError(wakeupChild);
|
|
@@ -22248,10 +22473,10 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
22248
22473
|
return true;
|
|
22249
22474
|
}
|
|
22250
22475
|
async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, requestInstructions, timestamp, vscodeCmd) {
|
|
22251
|
-
const workspacePath =
|
|
22252
|
-
const messagesDir =
|
|
22253
|
-
await
|
|
22254
|
-
const reqFile =
|
|
22476
|
+
const workspacePath = path25.join(subagentDir, `${path25.basename(subagentDir)}.code-workspace`);
|
|
22477
|
+
const messagesDir = path25.join(subagentDir, "messages");
|
|
22478
|
+
await mkdir9(messagesDir, { recursive: true });
|
|
22479
|
+
const reqFile = path25.join(messagesDir, `${timestamp}_req.md`);
|
|
22255
22480
|
await writeFile2(reqFile, requestInstructions, { encoding: "utf8" });
|
|
22256
22481
|
const reqUri = pathToFileUri2(reqFile);
|
|
22257
22482
|
const chatArgs = ["-r", "chat", "-m", chatId];
|
|
@@ -22259,16 +22484,16 @@ async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, reques
|
|
|
22259
22484
|
chatArgs.push("-a", attachment);
|
|
22260
22485
|
}
|
|
22261
22486
|
chatArgs.push("-a", reqFile);
|
|
22262
|
-
chatArgs.push(`Follow instructions in [${
|
|
22487
|
+
chatArgs.push(`Follow instructions in [${path25.basename(reqFile)}](${reqUri})`);
|
|
22263
22488
|
const workspaceReady = await ensureWorkspaceFocused(
|
|
22264
22489
|
workspacePath,
|
|
22265
|
-
|
|
22490
|
+
path25.basename(subagentDir),
|
|
22266
22491
|
subagentDir,
|
|
22267
22492
|
vscodeCmd
|
|
22268
22493
|
);
|
|
22269
22494
|
if (!workspaceReady) {
|
|
22270
22495
|
throw new Error(
|
|
22271
|
-
`VS Code workspace '${
|
|
22496
|
+
`VS Code workspace '${path25.basename(subagentDir)}' failed to become ready within the timeout. Check that '${vscodeCmd}' can open workspaces.`
|
|
22272
22497
|
);
|
|
22273
22498
|
}
|
|
22274
22499
|
await sleep2(500);
|
|
@@ -22276,9 +22501,9 @@ async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, reques
|
|
|
22276
22501
|
await raceSpawnError(child);
|
|
22277
22502
|
}
|
|
22278
22503
|
async function launchVsCodeWithBatchChat(subagentDir, chatId, attachmentPaths, chatInstruction, vscodeCmd) {
|
|
22279
|
-
const workspacePath =
|
|
22280
|
-
const messagesDir =
|
|
22281
|
-
await
|
|
22504
|
+
const workspacePath = path25.join(subagentDir, `${path25.basename(subagentDir)}.code-workspace`);
|
|
22505
|
+
const messagesDir = path25.join(subagentDir, "messages");
|
|
22506
|
+
await mkdir9(messagesDir, { recursive: true });
|
|
22282
22507
|
const chatArgs = ["-r", "chat", "-m", chatId];
|
|
22283
22508
|
for (const attachment of attachmentPaths) {
|
|
22284
22509
|
chatArgs.push("-a", attachment);
|
|
@@ -22286,13 +22511,13 @@ async function launchVsCodeWithBatchChat(subagentDir, chatId, attachmentPaths, c
|
|
|
22286
22511
|
chatArgs.push(chatInstruction);
|
|
22287
22512
|
const workspaceReady = await ensureWorkspaceFocused(
|
|
22288
22513
|
workspacePath,
|
|
22289
|
-
|
|
22514
|
+
path25.basename(subagentDir),
|
|
22290
22515
|
subagentDir,
|
|
22291
22516
|
vscodeCmd
|
|
22292
22517
|
);
|
|
22293
22518
|
if (!workspaceReady) {
|
|
22294
22519
|
throw new Error(
|
|
22295
|
-
`VS Code workspace '${
|
|
22520
|
+
`VS Code workspace '${path25.basename(subagentDir)}' failed to become ready within the timeout. Check that '${vscodeCmd}' can open workspaces.`
|
|
22296
22521
|
);
|
|
22297
22522
|
}
|
|
22298
22523
|
await sleep2(500);
|
|
@@ -22314,10 +22539,10 @@ function transformWorkspacePaths(workspaceContent, templateDir) {
|
|
|
22314
22539
|
}
|
|
22315
22540
|
const transformedFolders = workspace.folders.map((folder) => {
|
|
22316
22541
|
const folderPath = folder.path;
|
|
22317
|
-
if (
|
|
22542
|
+
if (path26.isAbsolute(folderPath)) {
|
|
22318
22543
|
return folder;
|
|
22319
22544
|
}
|
|
22320
|
-
const absolutePath =
|
|
22545
|
+
const absolutePath = path26.resolve(templateDir, folderPath);
|
|
22321
22546
|
return {
|
|
22322
22547
|
...folder,
|
|
22323
22548
|
path: absolutePath
|
|
@@ -22339,19 +22564,19 @@ function transformWorkspacePaths(workspaceContent, templateDir) {
|
|
|
22339
22564
|
if (locationMap && typeof locationMap === "object") {
|
|
22340
22565
|
const transformedMap = {};
|
|
22341
22566
|
for (const [locationPath, value] of Object.entries(locationMap)) {
|
|
22342
|
-
const isAbsolute =
|
|
22567
|
+
const isAbsolute = path26.isAbsolute(locationPath);
|
|
22343
22568
|
if (isAbsolute) {
|
|
22344
22569
|
transformedMap[locationPath] = value;
|
|
22345
22570
|
} else {
|
|
22346
22571
|
const firstGlobIndex = locationPath.search(/[*]/);
|
|
22347
22572
|
if (firstGlobIndex === -1) {
|
|
22348
|
-
const resolvedPath =
|
|
22573
|
+
const resolvedPath = path26.resolve(templateDir, locationPath).replace(/\\/g, "/");
|
|
22349
22574
|
transformedMap[resolvedPath] = value;
|
|
22350
22575
|
} else {
|
|
22351
22576
|
const basePathEnd = locationPath.lastIndexOf("/", firstGlobIndex);
|
|
22352
22577
|
const basePath = basePathEnd !== -1 ? locationPath.substring(0, basePathEnd) : ".";
|
|
22353
22578
|
const patternPath = locationPath.substring(basePathEnd !== -1 ? basePathEnd : 0);
|
|
22354
|
-
const resolvedPath = (
|
|
22579
|
+
const resolvedPath = (path26.resolve(templateDir, basePath) + patternPath).replace(
|
|
22355
22580
|
/\\/g,
|
|
22356
22581
|
"/"
|
|
22357
22582
|
);
|
|
@@ -22390,7 +22615,7 @@ async function findUnlockedSubagent(subagentRoot) {
|
|
|
22390
22615
|
number: Number.parseInt(entry.name.split("-")[1] ?? "", 10)
|
|
22391
22616
|
})).filter((entry) => Number.isInteger(entry.number)).sort((a, b) => a.number - b.number);
|
|
22392
22617
|
for (const subagent of subagents) {
|
|
22393
|
-
const lockFile =
|
|
22618
|
+
const lockFile = path27.join(subagent.absolutePath, DEFAULT_LOCK_NAME);
|
|
22394
22619
|
if (!await pathExists(lockFile)) {
|
|
22395
22620
|
return subagent.absolutePath;
|
|
22396
22621
|
}
|
|
@@ -22400,7 +22625,7 @@ async function findUnlockedSubagent(subagentRoot) {
|
|
|
22400
22625
|
async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
22401
22626
|
let workspaceContent;
|
|
22402
22627
|
if (workspaceTemplate) {
|
|
22403
|
-
const workspaceSrc =
|
|
22628
|
+
const workspaceSrc = path27.resolve(workspaceTemplate);
|
|
22404
22629
|
if (!await pathExists(workspaceSrc)) {
|
|
22405
22630
|
throw new Error(`workspace template not found: ${workspaceSrc}`);
|
|
22406
22631
|
}
|
|
@@ -22413,13 +22638,13 @@ async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
|
22413
22638
|
} else {
|
|
22414
22639
|
workspaceContent = DEFAULT_WORKSPACE_TEMPLATE;
|
|
22415
22640
|
}
|
|
22416
|
-
const workspaceName = `${
|
|
22417
|
-
const workspaceDst =
|
|
22418
|
-
const templateDir = workspaceTemplate ?
|
|
22641
|
+
const workspaceName = `${path27.basename(subagentDir)}.code-workspace`;
|
|
22642
|
+
const workspaceDst = path27.join(subagentDir, workspaceName);
|
|
22643
|
+
const templateDir = workspaceTemplate ? path27.dirname(path27.resolve(workspaceTemplate)) : subagentDir;
|
|
22419
22644
|
const workspaceJson = JSON.stringify(workspaceContent, null, 2);
|
|
22420
22645
|
let transformedContent = transformWorkspacePaths(workspaceJson, templateDir);
|
|
22421
22646
|
if (cwd) {
|
|
22422
|
-
const absCwd =
|
|
22647
|
+
const absCwd = path27.resolve(cwd);
|
|
22423
22648
|
const parsed = JSON.parse(transformedContent);
|
|
22424
22649
|
const alreadyPresent = parsed.folders.some((f) => f.path === absCwd);
|
|
22425
22650
|
if (!alreadyPresent) {
|
|
@@ -22428,35 +22653,35 @@ async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
|
22428
22653
|
}
|
|
22429
22654
|
}
|
|
22430
22655
|
await writeFile3(workspaceDst, transformedContent, "utf8");
|
|
22431
|
-
const messagesDir =
|
|
22432
|
-
await
|
|
22656
|
+
const messagesDir = path27.join(subagentDir, "messages");
|
|
22657
|
+
await mkdir10(messagesDir, { recursive: true });
|
|
22433
22658
|
return { workspace: workspaceDst, messagesDir };
|
|
22434
22659
|
}
|
|
22435
22660
|
async function createSubagentLock(subagentDir) {
|
|
22436
|
-
const messagesDir =
|
|
22661
|
+
const messagesDir = path27.join(subagentDir, "messages");
|
|
22437
22662
|
if (await pathExists(messagesDir)) {
|
|
22438
22663
|
const files = await readdir2(messagesDir);
|
|
22439
22664
|
await Promise.all(
|
|
22440
22665
|
files.map(async (file) => {
|
|
22441
|
-
const target =
|
|
22666
|
+
const target = path27.join(messagesDir, file);
|
|
22442
22667
|
await removeIfExists(target);
|
|
22443
22668
|
})
|
|
22444
22669
|
);
|
|
22445
22670
|
}
|
|
22446
|
-
const githubAgentsDir =
|
|
22671
|
+
const githubAgentsDir = path27.join(subagentDir, ".github", "agents");
|
|
22447
22672
|
if (await pathExists(githubAgentsDir)) {
|
|
22448
22673
|
const agentFiles = await readdir2(githubAgentsDir);
|
|
22449
22674
|
const preservedFiles = /* @__PURE__ */ new Set(["wakeup.md", "subagent.md"]);
|
|
22450
22675
|
await Promise.all(
|
|
22451
|
-
agentFiles.filter((file) => file.endsWith(".md") && !preservedFiles.has(file)).map((file) => removeIfExists(
|
|
22676
|
+
agentFiles.filter((file) => file.endsWith(".md") && !preservedFiles.has(file)).map((file) => removeIfExists(path27.join(githubAgentsDir, file)))
|
|
22452
22677
|
);
|
|
22453
22678
|
}
|
|
22454
|
-
const lockFile =
|
|
22679
|
+
const lockFile = path27.join(subagentDir, DEFAULT_LOCK_NAME);
|
|
22455
22680
|
await writeFile3(lockFile, "", { encoding: "utf8" });
|
|
22456
22681
|
return lockFile;
|
|
22457
22682
|
}
|
|
22458
22683
|
async function removeSubagentLock(subagentDir) {
|
|
22459
|
-
const lockFile =
|
|
22684
|
+
const lockFile = path27.join(subagentDir, DEFAULT_LOCK_NAME);
|
|
22460
22685
|
await removeIfExists(lockFile);
|
|
22461
22686
|
}
|
|
22462
22687
|
async function prepareSubagentDirectory(subagentDir, promptFile, chatId, workspaceTemplate, dryRun, cwd) {
|
|
@@ -22476,9 +22701,9 @@ async function prepareSubagentDirectory(subagentDir, promptFile, chatId, workspa
|
|
|
22476
22701
|
return 1;
|
|
22477
22702
|
}
|
|
22478
22703
|
if (promptFile) {
|
|
22479
|
-
const githubAgentsDir =
|
|
22480
|
-
await
|
|
22481
|
-
const agentFile =
|
|
22704
|
+
const githubAgentsDir = path27.join(subagentDir, ".github", "agents");
|
|
22705
|
+
await mkdir10(githubAgentsDir, { recursive: true });
|
|
22706
|
+
const agentFile = path27.join(githubAgentsDir, `${chatId}.md`);
|
|
22482
22707
|
try {
|
|
22483
22708
|
await copyFile(promptFile, agentFile);
|
|
22484
22709
|
} catch (error) {
|
|
@@ -22495,7 +22720,7 @@ async function resolvePromptFile(promptFile) {
|
|
|
22495
22720
|
if (!promptFile) {
|
|
22496
22721
|
return void 0;
|
|
22497
22722
|
}
|
|
22498
|
-
const resolvedPrompt =
|
|
22723
|
+
const resolvedPrompt = path28.resolve(promptFile);
|
|
22499
22724
|
if (!await pathExists(resolvedPrompt)) {
|
|
22500
22725
|
throw new Error(`Prompt file not found: ${resolvedPrompt}`);
|
|
22501
22726
|
}
|
|
@@ -22511,7 +22736,7 @@ async function resolveAttachments(extraAttachments) {
|
|
|
22511
22736
|
}
|
|
22512
22737
|
const resolved = [];
|
|
22513
22738
|
for (const attachment of extraAttachments) {
|
|
22514
|
-
const resolvedPath =
|
|
22739
|
+
const resolvedPath = path28.resolve(attachment);
|
|
22515
22740
|
if (!await pathExists(resolvedPath)) {
|
|
22516
22741
|
throw new Error(`Attachment not found: ${resolvedPath}`);
|
|
22517
22742
|
}
|
|
@@ -22553,7 +22778,7 @@ async function dispatchAgentSession(options) {
|
|
|
22553
22778
|
error: "No unlocked subagents available. Provision additional subagents with: subagent code provision --subagents <desired_total>"
|
|
22554
22779
|
};
|
|
22555
22780
|
}
|
|
22556
|
-
const subagentName =
|
|
22781
|
+
const subagentName = path28.basename(subagentDir);
|
|
22557
22782
|
const chatId = Math.random().toString(16).slice(2, 10);
|
|
22558
22783
|
const preparationResult = await prepareSubagentDirectory(
|
|
22559
22784
|
subagentDir,
|
|
@@ -22581,9 +22806,9 @@ async function dispatchAgentSession(options) {
|
|
|
22581
22806
|
};
|
|
22582
22807
|
}
|
|
22583
22808
|
const timestamp = generateTimestamp();
|
|
22584
|
-
const messagesDir =
|
|
22585
|
-
const responseFileTmp =
|
|
22586
|
-
const responseFileFinal =
|
|
22809
|
+
const messagesDir = path28.join(subagentDir, "messages");
|
|
22810
|
+
const responseFileTmp = path28.join(messagesDir, `${timestamp}_res.tmp.md`);
|
|
22811
|
+
const responseFileFinal = path28.join(messagesDir, `${timestamp}_res.md`);
|
|
22587
22812
|
const requestInstructions = createRequestPrompt(
|
|
22588
22813
|
userQuery,
|
|
22589
22814
|
responseFileTmp,
|
|
@@ -22688,7 +22913,7 @@ async function dispatchBatchAgent(options) {
|
|
|
22688
22913
|
error: "No unlocked subagents available. Provision additional subagents with: subagent code provision --subagents <desired_total>"
|
|
22689
22914
|
};
|
|
22690
22915
|
}
|
|
22691
|
-
subagentName =
|
|
22916
|
+
subagentName = path28.basename(subagentDir);
|
|
22692
22917
|
const chatId = Math.random().toString(16).slice(2, 10);
|
|
22693
22918
|
const preparationResult = await prepareSubagentDirectory(
|
|
22694
22919
|
subagentDir,
|
|
@@ -22719,17 +22944,17 @@ async function dispatchBatchAgent(options) {
|
|
|
22719
22944
|
};
|
|
22720
22945
|
}
|
|
22721
22946
|
const timestamp = generateTimestamp();
|
|
22722
|
-
const messagesDir =
|
|
22947
|
+
const messagesDir = path28.join(subagentDir, "messages");
|
|
22723
22948
|
requestFiles = userQueries.map(
|
|
22724
|
-
(_, index) =>
|
|
22949
|
+
(_, index) => path28.join(messagesDir, `${timestamp}_${index}_req.md`)
|
|
22725
22950
|
);
|
|
22726
22951
|
const responseTmpFiles = userQueries.map(
|
|
22727
|
-
(_, index) =>
|
|
22952
|
+
(_, index) => path28.join(messagesDir, `${timestamp}_${index}_res.tmp.md`)
|
|
22728
22953
|
);
|
|
22729
22954
|
responseFilesFinal = userQueries.map(
|
|
22730
|
-
(_, index) =>
|
|
22955
|
+
(_, index) => path28.join(messagesDir, `${timestamp}_${index}_res.md`)
|
|
22731
22956
|
);
|
|
22732
|
-
const orchestratorFile =
|
|
22957
|
+
const orchestratorFile = path28.join(messagesDir, `${timestamp}_orchestrator.md`);
|
|
22733
22958
|
if (!dryRun) {
|
|
22734
22959
|
await Promise.all(
|
|
22735
22960
|
userQueries.map((query, index) => {
|
|
@@ -22842,7 +23067,7 @@ async function provisionSubagents(options) {
|
|
|
22842
23067
|
if (!Number.isInteger(subagents) || subagents < 1) {
|
|
22843
23068
|
throw new Error("subagents must be a positive integer");
|
|
22844
23069
|
}
|
|
22845
|
-
const targetPath =
|
|
23070
|
+
const targetPath = path29.resolve(targetRoot);
|
|
22846
23071
|
if (!dryRun) {
|
|
22847
23072
|
await ensureDir(targetPath);
|
|
22848
23073
|
}
|
|
@@ -22862,7 +23087,7 @@ async function provisionSubagents(options) {
|
|
|
22862
23087
|
continue;
|
|
22863
23088
|
}
|
|
22864
23089
|
highestNumber = Math.max(highestNumber, parsed);
|
|
22865
|
-
const lockFile =
|
|
23090
|
+
const lockFile = path29.join(entry.absolutePath, lockName);
|
|
22866
23091
|
const locked = await pathExists(lockFile);
|
|
22867
23092
|
if (locked) {
|
|
22868
23093
|
lockedSubagents.add(entry.absolutePath);
|
|
@@ -22879,10 +23104,10 @@ async function provisionSubagents(options) {
|
|
|
22879
23104
|
break;
|
|
22880
23105
|
}
|
|
22881
23106
|
const subagentDir = subagent.absolutePath;
|
|
22882
|
-
const githubAgentsDir =
|
|
22883
|
-
const lockFile =
|
|
22884
|
-
const workspaceDst =
|
|
22885
|
-
const wakeupDst =
|
|
23107
|
+
const githubAgentsDir = path29.join(subagentDir, ".github", "agents");
|
|
23108
|
+
const lockFile = path29.join(subagentDir, lockName);
|
|
23109
|
+
const workspaceDst = path29.join(subagentDir, `${path29.basename(subagentDir)}.code-workspace`);
|
|
23110
|
+
const wakeupDst = path29.join(githubAgentsDir, "wakeup.md");
|
|
22886
23111
|
const isLocked = await pathExists(lockFile);
|
|
22887
23112
|
if (isLocked && !force) {
|
|
22888
23113
|
continue;
|
|
@@ -22920,10 +23145,10 @@ async function provisionSubagents(options) {
|
|
|
22920
23145
|
let nextIndex = highestNumber;
|
|
22921
23146
|
while (subagentsProvisioned < subagents) {
|
|
22922
23147
|
nextIndex += 1;
|
|
22923
|
-
const subagentDir =
|
|
22924
|
-
const githubAgentsDir =
|
|
22925
|
-
const workspaceDst =
|
|
22926
|
-
const wakeupDst =
|
|
23148
|
+
const subagentDir = path29.join(targetPath, `subagent-${nextIndex}`);
|
|
23149
|
+
const githubAgentsDir = path29.join(subagentDir, ".github", "agents");
|
|
23150
|
+
const workspaceDst = path29.join(subagentDir, `${path29.basename(subagentDir)}.code-workspace`);
|
|
23151
|
+
const wakeupDst = path29.join(githubAgentsDir, "wakeup.md");
|
|
22927
23152
|
if (!dryRun) {
|
|
22928
23153
|
await ensureDir(subagentDir);
|
|
22929
23154
|
await ensureDir(githubAgentsDir);
|
|
@@ -23109,7 +23334,7 @@ var VSCodeProvider = class {
|
|
|
23109
23334
|
async function locateVSCodeExecutable(candidate) {
|
|
23110
23335
|
const includesPathSeparator = candidate.includes("/") || candidate.includes("\\");
|
|
23111
23336
|
if (includesPathSeparator) {
|
|
23112
|
-
const resolved =
|
|
23337
|
+
const resolved = path30.isAbsolute(candidate) ? candidate : path30.resolve(candidate);
|
|
23113
23338
|
try {
|
|
23114
23339
|
await access3(resolved, constants3.F_OK);
|
|
23115
23340
|
return resolved;
|
|
@@ -23138,7 +23363,7 @@ async function resolveWorkspaceTemplateFile(template) {
|
|
|
23138
23363
|
return void 0;
|
|
23139
23364
|
}
|
|
23140
23365
|
try {
|
|
23141
|
-
const stats = await stat4(
|
|
23366
|
+
const stats = await stat4(path30.resolve(template));
|
|
23142
23367
|
return stats.isFile() ? template : void 0;
|
|
23143
23368
|
} catch {
|
|
23144
23369
|
return template;
|
|
@@ -23162,7 +23387,7 @@ function buildMandatoryPrereadBlock2(attachmentFiles) {
|
|
|
23162
23387
|
return "";
|
|
23163
23388
|
}
|
|
23164
23389
|
const buildList = (files) => files.map((absolutePath) => {
|
|
23165
|
-
const fileName =
|
|
23390
|
+
const fileName = path30.basename(absolutePath);
|
|
23166
23391
|
const fileUri = pathToFileUri3(absolutePath);
|
|
23167
23392
|
return `* [${fileName}](${fileUri})`;
|
|
23168
23393
|
});
|
|
@@ -23183,7 +23408,7 @@ function collectAttachmentFiles(attachments) {
|
|
|
23183
23408
|
}
|
|
23184
23409
|
const unique = /* @__PURE__ */ new Map();
|
|
23185
23410
|
for (const attachment of attachments) {
|
|
23186
|
-
const absolutePath =
|
|
23411
|
+
const absolutePath = path30.resolve(attachment);
|
|
23187
23412
|
if (!unique.has(absolutePath)) {
|
|
23188
23413
|
unique.set(absolutePath, absolutePath);
|
|
23189
23414
|
}
|
|
@@ -23191,7 +23416,7 @@ function collectAttachmentFiles(attachments) {
|
|
|
23191
23416
|
return Array.from(unique.values());
|
|
23192
23417
|
}
|
|
23193
23418
|
function pathToFileUri3(filePath) {
|
|
23194
|
-
const absolutePath =
|
|
23419
|
+
const absolutePath = path30.isAbsolute(filePath) ? filePath : path30.resolve(filePath);
|
|
23195
23420
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
23196
23421
|
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
23197
23422
|
return `file:///${normalizedPath}`;
|
|
@@ -23204,7 +23429,7 @@ function normalizeAttachments(attachments) {
|
|
|
23204
23429
|
}
|
|
23205
23430
|
const deduped = /* @__PURE__ */ new Set();
|
|
23206
23431
|
for (const attachment of attachments) {
|
|
23207
|
-
deduped.add(
|
|
23432
|
+
deduped.add(path30.resolve(attachment));
|
|
23208
23433
|
}
|
|
23209
23434
|
return Array.from(deduped);
|
|
23210
23435
|
}
|
|
@@ -23213,7 +23438,7 @@ function mergeAttachments(all) {
|
|
|
23213
23438
|
for (const list of all) {
|
|
23214
23439
|
if (!list) continue;
|
|
23215
23440
|
for (const inputFile of list) {
|
|
23216
|
-
deduped.add(
|
|
23441
|
+
deduped.add(path30.resolve(inputFile));
|
|
23217
23442
|
}
|
|
23218
23443
|
}
|
|
23219
23444
|
return deduped.size > 0 ? Array.from(deduped) : void 0;
|
|
@@ -23293,7 +23518,7 @@ async function fileExists3(filePath) {
|
|
|
23293
23518
|
}
|
|
23294
23519
|
}
|
|
23295
23520
|
async function readTargetDefinitions(filePath) {
|
|
23296
|
-
const absolutePath =
|
|
23521
|
+
const absolutePath = path31.resolve(filePath);
|
|
23297
23522
|
if (!await fileExists3(absolutePath)) {
|
|
23298
23523
|
throw new Error(`targets.yaml not found at ${absolutePath}`);
|
|
23299
23524
|
}
|
|
@@ -23314,11 +23539,11 @@ function listTargetNames(definitions) {
|
|
|
23314
23539
|
async function discoverProviders(registry, baseDir) {
|
|
23315
23540
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
23316
23541
|
const candidateDirs = [];
|
|
23317
|
-
let dir =
|
|
23318
|
-
const root =
|
|
23542
|
+
let dir = path322.resolve(baseDir);
|
|
23543
|
+
const root = path322.parse(dir).root;
|
|
23319
23544
|
while (dir !== root) {
|
|
23320
|
-
candidateDirs.push(
|
|
23321
|
-
dir =
|
|
23545
|
+
candidateDirs.push(path322.join(dir, ".agentv", "providers"));
|
|
23546
|
+
dir = path322.dirname(dir);
|
|
23322
23547
|
}
|
|
23323
23548
|
let files = [];
|
|
23324
23549
|
for (const providersDir of candidateDirs) {
|
|
@@ -23334,7 +23559,7 @@ async function discoverProviders(registry, baseDir) {
|
|
|
23334
23559
|
}
|
|
23335
23560
|
const discoveredKinds = [];
|
|
23336
23561
|
for (const filePath of files) {
|
|
23337
|
-
const basename =
|
|
23562
|
+
const basename = path322.basename(filePath);
|
|
23338
23563
|
const kindName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
23339
23564
|
if (registry.has(kindName)) {
|
|
23340
23565
|
continue;
|
|
@@ -23350,7 +23575,7 @@ async function discoverProviders(registry, baseDir) {
|
|
|
23350
23575
|
}
|
|
23351
23576
|
function createBuiltinProviderRegistry() {
|
|
23352
23577
|
const registry = new ProviderRegistry();
|
|
23353
|
-
registry.register("openai", (t) => new OpenAIProvider(t.name, t.config)).register("openrouter", (t) => new OpenRouterProvider(t.name, t.config)).register("azure", (t) => new AzureProvider(t.name, t.config)).register("anthropic", (t) => new AnthropicProvider(t.name, t.config)).register("gemini", (t) => new GeminiProvider(t.name, t.config)).register("cli", (t) => new CliProvider(t.name, t.config)).register("codex", (t) => new CodexProvider(t.name, t.config)).register("copilot-sdk", (t) => new CopilotSdkProvider(t.name, t.config)).register("copilot-cli", (t) => new CopilotCliProvider(t.name, t.config)).register("pi-coding-agent", (t) => new PiCodingAgentProvider(t.name, t.config)).register("pi-
|
|
23578
|
+
registry.register("openai", (t) => new OpenAIProvider(t.name, t.config)).register("openrouter", (t) => new OpenRouterProvider(t.name, t.config)).register("azure", (t) => new AzureProvider(t.name, t.config)).register("anthropic", (t) => new AnthropicProvider(t.name, t.config)).register("gemini", (t) => new GeminiProvider(t.name, t.config)).register("cli", (t) => new CliProvider(t.name, t.config)).register("codex", (t) => new CodexProvider(t.name, t.config)).register("copilot-sdk", (t) => new CopilotSdkProvider(t.name, t.config)).register("copilot-cli", (t) => new CopilotCliProvider(t.name, t.config)).register("pi-coding-agent", (t) => new PiCodingAgentProvider(t.name, t.config)).register("pi-cli", (t) => new PiCliProvider(t.name, t.config)).register("claude-cli", (t) => new ClaudeCliProvider(t.name, t.config)).register("claude", (t) => new ClaudeCliProvider(t.name, t.config)).register("claude-sdk", (t) => new ClaudeSdkProvider(t.name, t.config)).register("mock", (t) => new MockProvider(t.name, t.config)).register("agentv", (t) => new AgentvProvider(t.name, t.config)).register("vscode", (t) => new VSCodeProvider(t.name, t.config, "vscode")).register(
|
|
23354
23579
|
"vscode-insiders",
|
|
23355
23580
|
(t) => new VSCodeProvider(t.name, t.config, "vscode-insiders")
|
|
23356
23581
|
);
|
|
@@ -23532,15 +23757,15 @@ async function execFileWithStdinNode(argv, stdinPayload, options) {
|
|
|
23532
23757
|
});
|
|
23533
23758
|
}
|
|
23534
23759
|
async function execShellWithStdin(command, stdinPayload, options = {}) {
|
|
23535
|
-
const { mkdir:
|
|
23760
|
+
const { mkdir: mkdir16, readFile: readFile12, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
|
|
23536
23761
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
23537
|
-
const
|
|
23538
|
-
const { randomUUID:
|
|
23539
|
-
const dir =
|
|
23540
|
-
await
|
|
23541
|
-
const stdinPath =
|
|
23542
|
-
const stdoutPath =
|
|
23543
|
-
const stderrPath =
|
|
23762
|
+
const path45 = await import("node:path");
|
|
23763
|
+
const { randomUUID: randomUUID10 } = await import("node:crypto");
|
|
23764
|
+
const dir = path45.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
|
|
23765
|
+
await mkdir16(dir, { recursive: true });
|
|
23766
|
+
const stdinPath = path45.join(dir, "stdin.txt");
|
|
23767
|
+
const stdoutPath = path45.join(dir, "stdout.txt");
|
|
23768
|
+
const stderrPath = path45.join(dir, "stderr.txt");
|
|
23544
23769
|
await writeFile9(stdinPath, stdinPayload, "utf8");
|
|
23545
23770
|
const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
|
|
23546
23771
|
const { spawn: spawn5 } = await import("node:child_process");
|
|
@@ -24191,7 +24416,7 @@ ${context2.fileChanges}`;
|
|
|
24191
24416
|
async evaluateWithRubrics(context2, graderProvider, rubrics) {
|
|
24192
24417
|
if (!rubrics || rubrics.length === 0) {
|
|
24193
24418
|
throw new Error(
|
|
24194
|
-
`No rubrics found for evaluator "${context2.evaluator?.name ?? "llm-grader"}".
|
|
24419
|
+
`No rubrics found for evaluator "${context2.evaluator?.name ?? "llm-grader"}". Add rubric criteria under assertions or use the agentv-eval-writer skill for authoring help.`
|
|
24195
24420
|
);
|
|
24196
24421
|
}
|
|
24197
24422
|
const hasScoreRanges = rubrics.some((r) => r.score_ranges && r.score_ranges.length > 0);
|
|
@@ -24857,8 +25082,8 @@ function calculateScoreRangeResult(result, rubrics) {
|
|
|
24857
25082
|
};
|
|
24858
25083
|
}
|
|
24859
25084
|
function resolveSandboxed(basePath, relativePath) {
|
|
24860
|
-
const resolved =
|
|
24861
|
-
if (!resolved.startsWith(basePath +
|
|
25085
|
+
const resolved = path33.resolve(basePath, relativePath);
|
|
25086
|
+
if (!resolved.startsWith(basePath + path33.sep) && resolved !== basePath) {
|
|
24862
25087
|
throw new Error(`Path '${relativePath}' is outside the workspace`);
|
|
24863
25088
|
}
|
|
24864
25089
|
return resolved;
|
|
@@ -24948,11 +25173,11 @@ async function searchDirectory(dirPath, workspacePath, regex, matches) {
|
|
|
24948
25173
|
for (const entry of entries) {
|
|
24949
25174
|
if (matches.length >= MAX_SEARCH_MATCHES) return;
|
|
24950
25175
|
if (SEARCH_SKIP_DIRS.has(entry.name)) continue;
|
|
24951
|
-
const fullPath =
|
|
25176
|
+
const fullPath = path33.join(dirPath, entry.name);
|
|
24952
25177
|
if (entry.isDirectory()) {
|
|
24953
25178
|
await searchDirectory(fullPath, workspacePath, regex, matches);
|
|
24954
25179
|
} else if (entry.isFile()) {
|
|
24955
|
-
const ext =
|
|
25180
|
+
const ext = path33.extname(entry.name).toLowerCase();
|
|
24956
25181
|
if (BINARY_EXTENSIONS.has(ext)) continue;
|
|
24957
25182
|
try {
|
|
24958
25183
|
const stat8 = await fs2.stat(fullPath);
|
|
@@ -24964,7 +25189,7 @@ async function searchDirectory(dirPath, workspacePath, regex, matches) {
|
|
|
24964
25189
|
regex.lastIndex = 0;
|
|
24965
25190
|
if (regex.test(lines[i])) {
|
|
24966
25191
|
matches.push({
|
|
24967
|
-
file:
|
|
25192
|
+
file: path33.relative(workspacePath, fullPath),
|
|
24968
25193
|
line: i + 1,
|
|
24969
25194
|
text: lines[i].substring(0, 200)
|
|
24970
25195
|
});
|
|
@@ -25591,115 +25816,115 @@ var FieldAccuracyEvaluator = class {
|
|
|
25591
25816
|
* Evaluate a single field against the expected value.
|
|
25592
25817
|
*/
|
|
25593
25818
|
evaluateField(fieldConfig, candidateData, expectedData) {
|
|
25594
|
-
const { path:
|
|
25595
|
-
const candidateValue = resolvePath(candidateData,
|
|
25596
|
-
const expectedValue = resolvePath(expectedData,
|
|
25819
|
+
const { path: path45, match, required = true, weight = 1 } = fieldConfig;
|
|
25820
|
+
const candidateValue = resolvePath(candidateData, path45);
|
|
25821
|
+
const expectedValue = resolvePath(expectedData, path45);
|
|
25597
25822
|
if (expectedValue === void 0) {
|
|
25598
25823
|
return {
|
|
25599
|
-
path:
|
|
25824
|
+
path: path45,
|
|
25600
25825
|
score: 1,
|
|
25601
25826
|
// No expected value means no comparison needed
|
|
25602
25827
|
weight,
|
|
25603
25828
|
hit: true,
|
|
25604
|
-
message: `${
|
|
25829
|
+
message: `${path45}: no expected value`
|
|
25605
25830
|
};
|
|
25606
25831
|
}
|
|
25607
25832
|
if (candidateValue === void 0) {
|
|
25608
25833
|
if (required) {
|
|
25609
25834
|
return {
|
|
25610
|
-
path:
|
|
25835
|
+
path: path45,
|
|
25611
25836
|
score: 0,
|
|
25612
25837
|
weight,
|
|
25613
25838
|
hit: false,
|
|
25614
|
-
message: `${
|
|
25839
|
+
message: `${path45} (required, missing)`
|
|
25615
25840
|
};
|
|
25616
25841
|
}
|
|
25617
25842
|
return {
|
|
25618
|
-
path:
|
|
25843
|
+
path: path45,
|
|
25619
25844
|
score: 1,
|
|
25620
25845
|
// Don't penalize missing optional fields
|
|
25621
25846
|
weight: 0,
|
|
25622
25847
|
// Zero weight means it won't affect the score
|
|
25623
25848
|
hit: true,
|
|
25624
|
-
message: `${
|
|
25849
|
+
message: `${path45}: optional field missing`
|
|
25625
25850
|
};
|
|
25626
25851
|
}
|
|
25627
25852
|
switch (match) {
|
|
25628
25853
|
case "exact":
|
|
25629
|
-
return this.compareExact(
|
|
25854
|
+
return this.compareExact(path45, candidateValue, expectedValue, weight);
|
|
25630
25855
|
case "numeric_tolerance":
|
|
25631
25856
|
return this.compareNumericTolerance(
|
|
25632
|
-
|
|
25857
|
+
path45,
|
|
25633
25858
|
candidateValue,
|
|
25634
25859
|
expectedValue,
|
|
25635
25860
|
fieldConfig,
|
|
25636
25861
|
weight
|
|
25637
25862
|
);
|
|
25638
25863
|
case "date":
|
|
25639
|
-
return this.compareDate(
|
|
25864
|
+
return this.compareDate(path45, candidateValue, expectedValue, fieldConfig, weight);
|
|
25640
25865
|
default:
|
|
25641
25866
|
return {
|
|
25642
|
-
path:
|
|
25867
|
+
path: path45,
|
|
25643
25868
|
score: 0,
|
|
25644
25869
|
weight,
|
|
25645
25870
|
hit: false,
|
|
25646
|
-
message: `${
|
|
25871
|
+
message: `${path45}: unknown match type "${match}"`
|
|
25647
25872
|
};
|
|
25648
25873
|
}
|
|
25649
25874
|
}
|
|
25650
25875
|
/**
|
|
25651
25876
|
* Exact equality comparison.
|
|
25652
25877
|
*/
|
|
25653
|
-
compareExact(
|
|
25878
|
+
compareExact(path45, candidateValue, expectedValue, weight) {
|
|
25654
25879
|
if (deepEqual(candidateValue, expectedValue)) {
|
|
25655
25880
|
return {
|
|
25656
|
-
path:
|
|
25881
|
+
path: path45,
|
|
25657
25882
|
score: 1,
|
|
25658
25883
|
weight,
|
|
25659
25884
|
hit: true,
|
|
25660
|
-
message:
|
|
25885
|
+
message: path45
|
|
25661
25886
|
};
|
|
25662
25887
|
}
|
|
25663
25888
|
if (typeof candidateValue !== typeof expectedValue) {
|
|
25664
25889
|
return {
|
|
25665
|
-
path:
|
|
25890
|
+
path: path45,
|
|
25666
25891
|
score: 0,
|
|
25667
25892
|
weight,
|
|
25668
25893
|
hit: false,
|
|
25669
|
-
message: `${
|
|
25894
|
+
message: `${path45} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
|
|
25670
25895
|
};
|
|
25671
25896
|
}
|
|
25672
25897
|
return {
|
|
25673
|
-
path:
|
|
25898
|
+
path: path45,
|
|
25674
25899
|
score: 0,
|
|
25675
25900
|
weight,
|
|
25676
25901
|
hit: false,
|
|
25677
|
-
message: `${
|
|
25902
|
+
message: `${path45} (value mismatch)`
|
|
25678
25903
|
};
|
|
25679
25904
|
}
|
|
25680
25905
|
/**
|
|
25681
25906
|
* Numeric comparison with absolute or relative tolerance.
|
|
25682
25907
|
*/
|
|
25683
|
-
compareNumericTolerance(
|
|
25908
|
+
compareNumericTolerance(path45, candidateValue, expectedValue, fieldConfig, weight) {
|
|
25684
25909
|
const { tolerance = 0, relative = false } = fieldConfig;
|
|
25685
25910
|
const candidateNum = toNumber(candidateValue);
|
|
25686
25911
|
const expectedNum = toNumber(expectedValue);
|
|
25687
25912
|
if (candidateNum === null || expectedNum === null) {
|
|
25688
25913
|
return {
|
|
25689
|
-
path:
|
|
25914
|
+
path: path45,
|
|
25690
25915
|
score: 0,
|
|
25691
25916
|
weight,
|
|
25692
25917
|
hit: false,
|
|
25693
|
-
message: `${
|
|
25918
|
+
message: `${path45} (non-numeric value)`
|
|
25694
25919
|
};
|
|
25695
25920
|
}
|
|
25696
25921
|
if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
|
|
25697
25922
|
return {
|
|
25698
|
-
path:
|
|
25923
|
+
path: path45,
|
|
25699
25924
|
score: 0,
|
|
25700
25925
|
weight,
|
|
25701
25926
|
hit: false,
|
|
25702
|
-
message: `${
|
|
25927
|
+
message: `${path45} (invalid numeric value)`
|
|
25703
25928
|
};
|
|
25704
25929
|
}
|
|
25705
25930
|
const diff = Math.abs(candidateNum - expectedNum);
|
|
@@ -25712,61 +25937,61 @@ var FieldAccuracyEvaluator = class {
|
|
|
25712
25937
|
}
|
|
25713
25938
|
if (withinTolerance) {
|
|
25714
25939
|
return {
|
|
25715
|
-
path:
|
|
25940
|
+
path: path45,
|
|
25716
25941
|
score: 1,
|
|
25717
25942
|
weight,
|
|
25718
25943
|
hit: true,
|
|
25719
|
-
message: `${
|
|
25944
|
+
message: `${path45} (within tolerance: diff=${diff.toFixed(2)})`
|
|
25720
25945
|
};
|
|
25721
25946
|
}
|
|
25722
25947
|
return {
|
|
25723
|
-
path:
|
|
25948
|
+
path: path45,
|
|
25724
25949
|
score: 0,
|
|
25725
25950
|
weight,
|
|
25726
25951
|
hit: false,
|
|
25727
|
-
message: `${
|
|
25952
|
+
message: `${path45} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
|
|
25728
25953
|
};
|
|
25729
25954
|
}
|
|
25730
25955
|
/**
|
|
25731
25956
|
* Date comparison with format normalization.
|
|
25732
25957
|
*/
|
|
25733
|
-
compareDate(
|
|
25958
|
+
compareDate(path45, candidateValue, expectedValue, fieldConfig, weight) {
|
|
25734
25959
|
const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
|
|
25735
25960
|
const candidateDate = parseDate(String(candidateValue), formats);
|
|
25736
25961
|
const expectedDate = parseDate(String(expectedValue), formats);
|
|
25737
25962
|
if (candidateDate === null) {
|
|
25738
25963
|
return {
|
|
25739
|
-
path:
|
|
25964
|
+
path: path45,
|
|
25740
25965
|
score: 0,
|
|
25741
25966
|
weight,
|
|
25742
25967
|
hit: false,
|
|
25743
|
-
message: `${
|
|
25968
|
+
message: `${path45} (unparseable candidate date)`
|
|
25744
25969
|
};
|
|
25745
25970
|
}
|
|
25746
25971
|
if (expectedDate === null) {
|
|
25747
25972
|
return {
|
|
25748
|
-
path:
|
|
25973
|
+
path: path45,
|
|
25749
25974
|
score: 0,
|
|
25750
25975
|
weight,
|
|
25751
25976
|
hit: false,
|
|
25752
|
-
message: `${
|
|
25977
|
+
message: `${path45} (unparseable expected date)`
|
|
25753
25978
|
};
|
|
25754
25979
|
}
|
|
25755
25980
|
if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
|
|
25756
25981
|
return {
|
|
25757
|
-
path:
|
|
25982
|
+
path: path45,
|
|
25758
25983
|
score: 1,
|
|
25759
25984
|
weight,
|
|
25760
25985
|
hit: true,
|
|
25761
|
-
message:
|
|
25986
|
+
message: path45
|
|
25762
25987
|
};
|
|
25763
25988
|
}
|
|
25764
25989
|
return {
|
|
25765
|
-
path:
|
|
25990
|
+
path: path45,
|
|
25766
25991
|
score: 0,
|
|
25767
25992
|
weight,
|
|
25768
25993
|
hit: false,
|
|
25769
|
-
message: `${
|
|
25994
|
+
message: `${path45} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
|
|
25770
25995
|
};
|
|
25771
25996
|
}
|
|
25772
25997
|
/**
|
|
@@ -25799,11 +26024,11 @@ var FieldAccuracyEvaluator = class {
|
|
|
25799
26024
|
};
|
|
25800
26025
|
}
|
|
25801
26026
|
};
|
|
25802
|
-
function resolvePath(obj,
|
|
25803
|
-
if (!
|
|
26027
|
+
function resolvePath(obj, path45) {
|
|
26028
|
+
if (!path45 || !obj) {
|
|
25804
26029
|
return void 0;
|
|
25805
26030
|
}
|
|
25806
|
-
const parts =
|
|
26031
|
+
const parts = path45.split(/\.|\[|\]/).filter((p) => p.length > 0);
|
|
25807
26032
|
let current = obj;
|
|
25808
26033
|
for (const part of parts) {
|
|
25809
26034
|
if (current === null || current === void 0) {
|
|
@@ -25965,9 +26190,7 @@ var PROVIDER_TOOL_SEMANTICS = {
|
|
|
25965
26190
|
"claude-sdk": CLAUDE_MATCHER,
|
|
25966
26191
|
codex: CODEX_MATCHER,
|
|
25967
26192
|
"pi-coding-agent": PI_CODING_AGENT_MATCHER,
|
|
25968
|
-
|
|
25969
|
-
// TODO: consider removing pi-agent-sdk provider entirely.
|
|
25970
|
-
"pi-agent-sdk": PI_CODING_AGENT_MATCHER,
|
|
26193
|
+
"pi-cli": PI_CODING_AGENT_MATCHER,
|
|
25971
26194
|
"copilot-cli": COPILOT_MATCHER,
|
|
25972
26195
|
"copilot-sdk": COPILOT_MATCHER,
|
|
25973
26196
|
vscode: COPILOT_MATCHER,
|
|
@@ -26276,8 +26499,8 @@ var TokenUsageEvaluator = class {
|
|
|
26276
26499
|
};
|
|
26277
26500
|
}
|
|
26278
26501
|
};
|
|
26279
|
-
function getNestedValue(obj,
|
|
26280
|
-
const parts =
|
|
26502
|
+
function getNestedValue(obj, path45) {
|
|
26503
|
+
const parts = path45.split(".");
|
|
26281
26504
|
let current = obj;
|
|
26282
26505
|
for (const part of parts) {
|
|
26283
26506
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -27140,7 +27363,7 @@ async function executePromptTemplate(script, context2, config, timeoutMs) {
|
|
|
27140
27363
|
};
|
|
27141
27364
|
const inputJson = JSON.stringify(toSnakeCaseDeep(payload), null, 2);
|
|
27142
27365
|
const scriptPath = script[script.length - 1];
|
|
27143
|
-
const cwd =
|
|
27366
|
+
const cwd = path34.dirname(scriptPath);
|
|
27144
27367
|
try {
|
|
27145
27368
|
const stdout = await executeScript(script, inputJson, timeoutMs, cwd);
|
|
27146
27369
|
const prompt = stdout.trim();
|
|
@@ -27411,11 +27634,11 @@ function createBuiltinRegistry() {
|
|
|
27411
27634
|
async function discoverAssertions(registry, baseDir) {
|
|
27412
27635
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
27413
27636
|
const candidateDirs = [];
|
|
27414
|
-
let dir =
|
|
27415
|
-
const root =
|
|
27637
|
+
let dir = path35.resolve(baseDir);
|
|
27638
|
+
const root = path35.parse(dir).root;
|
|
27416
27639
|
while (dir !== root) {
|
|
27417
|
-
candidateDirs.push(
|
|
27418
|
-
dir =
|
|
27640
|
+
candidateDirs.push(path35.join(dir, ".agentv", "assertions"));
|
|
27641
|
+
dir = path35.dirname(dir);
|
|
27419
27642
|
}
|
|
27420
27643
|
let files = [];
|
|
27421
27644
|
for (const assertionsDir of candidateDirs) {
|
|
@@ -27431,7 +27654,7 @@ async function discoverAssertions(registry, baseDir) {
|
|
|
27431
27654
|
}
|
|
27432
27655
|
const discoveredTypes = [];
|
|
27433
27656
|
for (const filePath of files) {
|
|
27434
|
-
const basename =
|
|
27657
|
+
const basename = path35.basename(filePath);
|
|
27435
27658
|
const typeName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
27436
27659
|
if (registry.has(typeName)) {
|
|
27437
27660
|
continue;
|
|
@@ -27450,12 +27673,12 @@ async function discoverAssertions(registry, baseDir) {
|
|
|
27450
27673
|
async function discoverGraders(registry, baseDir) {
|
|
27451
27674
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
27452
27675
|
const candidateDirs = [];
|
|
27453
|
-
let dir =
|
|
27454
|
-
const root =
|
|
27676
|
+
let dir = path36.resolve(baseDir);
|
|
27677
|
+
const root = path36.parse(dir).root;
|
|
27455
27678
|
while (dir !== root) {
|
|
27456
|
-
candidateDirs.push(
|
|
27457
|
-
candidateDirs.push(
|
|
27458
|
-
dir =
|
|
27679
|
+
candidateDirs.push(path36.join(dir, ".agentv", "graders"));
|
|
27680
|
+
candidateDirs.push(path36.join(dir, ".agentv", "judges"));
|
|
27681
|
+
dir = path36.dirname(dir);
|
|
27459
27682
|
}
|
|
27460
27683
|
let files = [];
|
|
27461
27684
|
for (const gradersDir of candidateDirs) {
|
|
@@ -27471,7 +27694,7 @@ async function discoverGraders(registry, baseDir) {
|
|
|
27471
27694
|
}
|
|
27472
27695
|
const discoveredTypes = [];
|
|
27473
27696
|
for (const filePath of files) {
|
|
27474
|
-
const basename =
|
|
27697
|
+
const basename = path36.basename(filePath);
|
|
27475
27698
|
const typeName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
27476
27699
|
if (registry.has(typeName)) {
|
|
27477
27700
|
continue;
|
|
@@ -27657,10 +27880,10 @@ async function stageNestedRepoChanges(workspacePath) {
|
|
|
27657
27880
|
}
|
|
27658
27881
|
for (const entry of entries) {
|
|
27659
27882
|
if (entry === ".git" || entry === "node_modules") continue;
|
|
27660
|
-
const childPath =
|
|
27883
|
+
const childPath = path37.join(workspacePath, entry);
|
|
27661
27884
|
try {
|
|
27662
27885
|
if (!statSync(childPath).isDirectory()) continue;
|
|
27663
|
-
if (!statSync(
|
|
27886
|
+
if (!statSync(path37.join(childPath, ".git")).isDirectory()) continue;
|
|
27664
27887
|
} catch {
|
|
27665
27888
|
continue;
|
|
27666
27889
|
}
|
|
@@ -27697,14 +27920,14 @@ async function isDirectory(filePath) {
|
|
|
27697
27920
|
}
|
|
27698
27921
|
function getWorkspacePath(evalRunId, caseId, workspaceRoot) {
|
|
27699
27922
|
const root = workspaceRoot ?? getWorkspacesRoot();
|
|
27700
|
-
return
|
|
27923
|
+
return path38.join(root, evalRunId, caseId);
|
|
27701
27924
|
}
|
|
27702
27925
|
async function copyDirectoryRecursive(src, dest) {
|
|
27703
|
-
await
|
|
27926
|
+
await mkdir12(dest, { recursive: true });
|
|
27704
27927
|
const entries = await readdir3(src, { withFileTypes: true });
|
|
27705
27928
|
for (const entry of entries) {
|
|
27706
|
-
const srcPath =
|
|
27707
|
-
const destPath =
|
|
27929
|
+
const srcPath = path38.join(src, entry.name);
|
|
27930
|
+
const destPath = path38.join(dest, entry.name);
|
|
27708
27931
|
if (entry.name === ".git") {
|
|
27709
27932
|
continue;
|
|
27710
27933
|
}
|
|
@@ -27716,7 +27939,7 @@ async function copyDirectoryRecursive(src, dest) {
|
|
|
27716
27939
|
}
|
|
27717
27940
|
}
|
|
27718
27941
|
async function createTempWorkspace(templatePath, evalRunId, caseId, workspaceRoot) {
|
|
27719
|
-
const resolvedTemplatePath =
|
|
27942
|
+
const resolvedTemplatePath = path38.resolve(templatePath);
|
|
27720
27943
|
if (!await fileExists(resolvedTemplatePath)) {
|
|
27721
27944
|
throw new TemplateNotFoundError(resolvedTemplatePath);
|
|
27722
27945
|
}
|
|
@@ -27765,7 +27988,7 @@ async function cleanupWorkspace(workspacePath) {
|
|
|
27765
27988
|
}
|
|
27766
27989
|
async function cleanupEvalWorkspaces(evalRunId, workspaceRoot) {
|
|
27767
27990
|
const root = workspaceRoot ?? getWorkspacesRoot();
|
|
27768
|
-
const evalDir =
|
|
27991
|
+
const evalDir = path38.join(root, evalRunId);
|
|
27769
27992
|
if (await fileExists(evalDir)) {
|
|
27770
27993
|
await rm4(evalDir, { recursive: true, force: true });
|
|
27771
27994
|
}
|
|
@@ -27819,11 +28042,11 @@ function computeWorkspaceFingerprint(repos) {
|
|
|
27819
28042
|
return createHash("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
27820
28043
|
}
|
|
27821
28044
|
async function copyDirectoryRecursive2(src, dest, skipDirs) {
|
|
27822
|
-
await
|
|
28045
|
+
await mkdir13(dest, { recursive: true });
|
|
27823
28046
|
const entries = await readdir4(src, { withFileTypes: true });
|
|
27824
28047
|
for (const entry of entries) {
|
|
27825
|
-
const srcPath =
|
|
27826
|
-
const destPath =
|
|
28048
|
+
const srcPath = path39.join(src, entry.name);
|
|
28049
|
+
const destPath = path39.join(dest, entry.name);
|
|
27827
28050
|
if (entry.name === ".git") {
|
|
27828
28051
|
continue;
|
|
27829
28052
|
}
|
|
@@ -27856,8 +28079,8 @@ var WorkspacePoolManager = class {
|
|
|
27856
28079
|
async acquireWorkspace(options) {
|
|
27857
28080
|
const { templatePath, repos, maxSlots, repoManager, poolReset } = options;
|
|
27858
28081
|
const fingerprint = computeWorkspaceFingerprint(repos);
|
|
27859
|
-
const poolDir =
|
|
27860
|
-
await
|
|
28082
|
+
const poolDir = path39.join(this.poolRoot, fingerprint);
|
|
28083
|
+
await mkdir13(poolDir, { recursive: true });
|
|
27861
28084
|
const drifted = await this.checkDrift(poolDir, fingerprint);
|
|
27862
28085
|
if (drifted) {
|
|
27863
28086
|
console.warn(
|
|
@@ -27866,7 +28089,7 @@ var WorkspacePoolManager = class {
|
|
|
27866
28089
|
await this.removeAllSlots(poolDir);
|
|
27867
28090
|
}
|
|
27868
28091
|
for (let i = 0; i < maxSlots; i++) {
|
|
27869
|
-
const slotPath =
|
|
28092
|
+
const slotPath = path39.join(poolDir, `slot-${i}`);
|
|
27870
28093
|
const lockPath = `${slotPath}.lock`;
|
|
27871
28094
|
const locked = await this.tryLock(lockPath);
|
|
27872
28095
|
if (!locked) {
|
|
@@ -27884,7 +28107,7 @@ var WorkspacePoolManager = class {
|
|
|
27884
28107
|
poolDir
|
|
27885
28108
|
};
|
|
27886
28109
|
}
|
|
27887
|
-
await
|
|
28110
|
+
await mkdir13(slotPath, { recursive: true });
|
|
27888
28111
|
if (templatePath) {
|
|
27889
28112
|
await copyDirectoryRecursive2(templatePath, slotPath);
|
|
27890
28113
|
}
|
|
@@ -27953,7 +28176,7 @@ var WorkspacePoolManager = class {
|
|
|
27953
28176
|
* Returns false (no drift) if metadata.json doesn't exist (first use).
|
|
27954
28177
|
*/
|
|
27955
28178
|
async checkDrift(poolDir, fingerprint) {
|
|
27956
|
-
const metadataPath =
|
|
28179
|
+
const metadataPath = path39.join(poolDir, "metadata.json");
|
|
27957
28180
|
try {
|
|
27958
28181
|
const raw = await readFile10(metadataPath, "utf-8");
|
|
27959
28182
|
const metadata = JSON.parse(raw);
|
|
@@ -27970,14 +28193,14 @@ var WorkspacePoolManager = class {
|
|
|
27970
28193
|
repos,
|
|
27971
28194
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
27972
28195
|
};
|
|
27973
|
-
await writeFile7(
|
|
28196
|
+
await writeFile7(path39.join(poolDir, "metadata.json"), JSON.stringify(metadata, null, 2));
|
|
27974
28197
|
}
|
|
27975
28198
|
/** Remove all slot directories and their lock files from a pool directory. */
|
|
27976
28199
|
async removeAllSlots(poolDir) {
|
|
27977
28200
|
const entries = await readdir4(poolDir);
|
|
27978
28201
|
for (const entry of entries) {
|
|
27979
28202
|
if (entry.startsWith("slot-") && !entry.endsWith(".lock")) {
|
|
27980
|
-
const lockPath =
|
|
28203
|
+
const lockPath = path39.join(poolDir, `${entry}.lock`);
|
|
27981
28204
|
if (existsSync2(lockPath)) {
|
|
27982
28205
|
try {
|
|
27983
28206
|
const pidStr = await readFile10(lockPath, "utf-8");
|
|
@@ -27993,12 +28216,12 @@ var WorkspacePoolManager = class {
|
|
|
27993
28216
|
} catch {
|
|
27994
28217
|
}
|
|
27995
28218
|
}
|
|
27996
|
-
await rm5(
|
|
28219
|
+
await rm5(path39.join(poolDir, entry), { recursive: true, force: true });
|
|
27997
28220
|
await rm5(lockPath, { force: true }).catch(() => {
|
|
27998
28221
|
});
|
|
27999
28222
|
}
|
|
28000
28223
|
}
|
|
28001
|
-
await rm5(
|
|
28224
|
+
await rm5(path39.join(poolDir, "metadata.json"), { force: true }).catch(() => {
|
|
28002
28225
|
});
|
|
28003
28226
|
}
|
|
28004
28227
|
/**
|
|
@@ -28008,7 +28231,7 @@ var WorkspacePoolManager = class {
|
|
|
28008
28231
|
*/
|
|
28009
28232
|
async resetSlot(slotPath, templatePath, repos, poolReset = "fast") {
|
|
28010
28233
|
for (const repo of repos) {
|
|
28011
|
-
const repoDir =
|
|
28234
|
+
const repoDir = path39.join(slotPath, repo.path);
|
|
28012
28235
|
if (!existsSync2(repoDir)) {
|
|
28013
28236
|
continue;
|
|
28014
28237
|
}
|
|
@@ -28129,7 +28352,7 @@ ${lines.join("\n")}`;
|
|
|
28129
28352
|
* Handles checkout, ref resolution, ancestor walking, shallow clone, sparse checkout.
|
|
28130
28353
|
*/
|
|
28131
28354
|
async materialize(repo, workspacePath) {
|
|
28132
|
-
const targetDir =
|
|
28355
|
+
const targetDir = path40.join(workspacePath, repo.path);
|
|
28133
28356
|
const sourceUrl = getSourceUrl(repo.source);
|
|
28134
28357
|
const startedAt = Date.now();
|
|
28135
28358
|
if (this.verbose) {
|
|
@@ -28220,7 +28443,7 @@ ${lines.join("\n")}`;
|
|
|
28220
28443
|
async reset(repos, workspacePath, reset) {
|
|
28221
28444
|
const cleanFlag = reset === "strict" ? "-fdx" : "-fd";
|
|
28222
28445
|
for (const repo of repos) {
|
|
28223
|
-
const targetDir =
|
|
28446
|
+
const targetDir = path40.join(workspacePath, repo.path);
|
|
28224
28447
|
await this.runGit(["reset", "--hard", "HEAD"], { cwd: targetDir });
|
|
28225
28448
|
await this.runGit(["clean", cleanFlag], { cwd: targetDir });
|
|
28226
28449
|
}
|
|
@@ -28230,11 +28453,11 @@ async function resolveWorkspaceTemplate(templatePath) {
|
|
|
28230
28453
|
if (!templatePath) {
|
|
28231
28454
|
return void 0;
|
|
28232
28455
|
}
|
|
28233
|
-
const resolved =
|
|
28456
|
+
const resolved = path41.resolve(templatePath);
|
|
28234
28457
|
const stats = await stat6(resolved);
|
|
28235
28458
|
if (stats.isFile()) {
|
|
28236
28459
|
return {
|
|
28237
|
-
dir:
|
|
28460
|
+
dir: path41.dirname(resolved),
|
|
28238
28461
|
workspaceFile: resolved
|
|
28239
28462
|
};
|
|
28240
28463
|
}
|
|
@@ -28246,14 +28469,14 @@ async function resolveWorkspaceTemplate(templatePath) {
|
|
|
28246
28469
|
if (workspaceFiles.length === 1) {
|
|
28247
28470
|
return {
|
|
28248
28471
|
dir: resolved,
|
|
28249
|
-
workspaceFile:
|
|
28472
|
+
workspaceFile: path41.join(resolved, workspaceFiles[0])
|
|
28250
28473
|
};
|
|
28251
28474
|
}
|
|
28252
28475
|
if (workspaceFiles.length > 1) {
|
|
28253
28476
|
const conventionFile = workspaceFiles.find((f) => f === "template.code-workspace");
|
|
28254
28477
|
return {
|
|
28255
28478
|
dir: resolved,
|
|
28256
|
-
workspaceFile: conventionFile ?
|
|
28479
|
+
workspaceFile: conventionFile ? path41.join(resolved, conventionFile) : void 0
|
|
28257
28480
|
};
|
|
28258
28481
|
}
|
|
28259
28482
|
return { dir: resolved };
|
|
@@ -28386,7 +28609,7 @@ async function runEvaluation(options) {
|
|
|
28386
28609
|
);
|
|
28387
28610
|
useCache = false;
|
|
28388
28611
|
}
|
|
28389
|
-
const evalRunId =
|
|
28612
|
+
const evalRunId = randomUUID9();
|
|
28390
28613
|
const evalCases = preloadedEvalCases ?? await loadTests(evalFilePath, repoRoot, { verbose, filter: filter2 });
|
|
28391
28614
|
const filteredEvalCases = filterEvalCases(evalCases, filter2);
|
|
28392
28615
|
if (filteredEvalCases.length === 0) {
|
|
@@ -28465,7 +28688,7 @@ async function runEvaluation(options) {
|
|
|
28465
28688
|
];
|
|
28466
28689
|
const evaluatorRegistry = buildEvaluatorRegistry(evaluators, resolveGraderProvider);
|
|
28467
28690
|
const typeRegistry = createBuiltinRegistry();
|
|
28468
|
-
const discoveryBaseDir = evalFilePath ?
|
|
28691
|
+
const discoveryBaseDir = evalFilePath ? path422.dirname(path422.resolve(evalFilePath)) : process.cwd();
|
|
28469
28692
|
const evalDir = discoveryBaseDir;
|
|
28470
28693
|
await discoverAssertions(typeRegistry, discoveryBaseDir);
|
|
28471
28694
|
await discoverGraders(typeRegistry, discoveryBaseDir);
|
|
@@ -28612,7 +28835,7 @@ async function runEvaluation(options) {
|
|
|
28612
28835
|
const isEmpty = dirExists ? (await readdir6(configuredStaticPath)).length === 0 : false;
|
|
28613
28836
|
if (isYamlConfiguredPath && (!dirExists || isEmpty)) {
|
|
28614
28837
|
if (!dirExists) {
|
|
28615
|
-
await
|
|
28838
|
+
await mkdir14(configuredStaticPath, { recursive: true });
|
|
28616
28839
|
}
|
|
28617
28840
|
if (workspaceTemplate) {
|
|
28618
28841
|
await copyDirectoryRecursive(workspaceTemplate, configuredStaticPath);
|
|
@@ -28657,12 +28880,12 @@ async function runEvaluation(options) {
|
|
|
28657
28880
|
}
|
|
28658
28881
|
} else if (suiteWorkspace?.hooks || suiteWorkspace?.repos?.length && !isPerTestIsolation) {
|
|
28659
28882
|
sharedWorkspacePath = getWorkspacePath(evalRunId, "shared");
|
|
28660
|
-
await
|
|
28883
|
+
await mkdir14(sharedWorkspacePath, { recursive: true });
|
|
28661
28884
|
setupLog(`created empty shared workspace at: ${sharedWorkspacePath}`);
|
|
28662
28885
|
}
|
|
28663
28886
|
try {
|
|
28664
28887
|
if (suiteWorkspaceFile && sharedWorkspacePath) {
|
|
28665
|
-
const copiedWorkspaceFile =
|
|
28888
|
+
const copiedWorkspaceFile = path422.join(sharedWorkspacePath, path422.basename(suiteWorkspaceFile));
|
|
28666
28889
|
try {
|
|
28667
28890
|
await stat7(copiedWorkspaceFile);
|
|
28668
28891
|
suiteWorkspaceFile = copiedWorkspaceFile;
|
|
@@ -29244,7 +29467,7 @@ async function runEvalCase(options) {
|
|
|
29244
29467
|
);
|
|
29245
29468
|
}
|
|
29246
29469
|
if (caseWorkspaceFile && workspacePath) {
|
|
29247
|
-
const copiedFile =
|
|
29470
|
+
const copiedFile = path422.join(workspacePath, path422.basename(caseWorkspaceFile));
|
|
29248
29471
|
try {
|
|
29249
29472
|
await stat7(copiedFile);
|
|
29250
29473
|
caseWorkspaceFile = copiedFile;
|
|
@@ -29254,7 +29477,7 @@ async function runEvalCase(options) {
|
|
|
29254
29477
|
}
|
|
29255
29478
|
if (!workspacePath && (evalCase.workspace?.hooks || evalCase.workspace?.repos?.length) && evalRunId) {
|
|
29256
29479
|
workspacePath = getWorkspacePath(evalRunId, evalCase.id);
|
|
29257
|
-
await
|
|
29480
|
+
await mkdir14(workspacePath, { recursive: true });
|
|
29258
29481
|
}
|
|
29259
29482
|
if (evalCase.workspace?.repos?.length && workspacePath) {
|
|
29260
29483
|
const localPathErrors = RepoManager.validateLocalPaths(evalCase.workspace.repos);
|
|
@@ -29306,10 +29529,10 @@ async function runEvalCase(options) {
|
|
|
29306
29529
|
const files = evalCase.metadata.agent_skills_files;
|
|
29307
29530
|
if (baseDir && files.length > 0) {
|
|
29308
29531
|
for (const relPath of files) {
|
|
29309
|
-
const srcPath =
|
|
29310
|
-
const destPath =
|
|
29532
|
+
const srcPath = path422.resolve(baseDir, relPath);
|
|
29533
|
+
const destPath = path422.resolve(workspacePath, relPath);
|
|
29311
29534
|
try {
|
|
29312
|
-
await
|
|
29535
|
+
await mkdir14(path422.dirname(destPath), { recursive: true });
|
|
29313
29536
|
await copyFile2(srcPath, destPath);
|
|
29314
29537
|
} catch (error) {
|
|
29315
29538
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -29955,7 +30178,7 @@ async function runEvaluatorList(options) {
|
|
|
29955
30178
|
fileChanges,
|
|
29956
30179
|
workspacePath
|
|
29957
30180
|
};
|
|
29958
|
-
const evalFileDir = evalCase.file_paths[0] ?
|
|
30181
|
+
const evalFileDir = evalCase.file_paths[0] ? path422.dirname(evalCase.file_paths[0]) : process.cwd();
|
|
29959
30182
|
const dispatchContext = {
|
|
29960
30183
|
graderProvider,
|
|
29961
30184
|
targetResolver,
|
|
@@ -30318,7 +30541,7 @@ async function evaluate(config) {
|
|
|
30318
30541
|
}
|
|
30319
30542
|
const gitRoot = await findGitRoot(process.cwd());
|
|
30320
30543
|
const repoRoot = gitRoot ?? process.cwd();
|
|
30321
|
-
const testFilePath = config.specFile ?
|
|
30544
|
+
const testFilePath = config.specFile ? path43.resolve(config.specFile) : path43.join(process.cwd(), "__programmatic__.yaml");
|
|
30322
30545
|
await loadEnvHierarchy(repoRoot, testFilePath);
|
|
30323
30546
|
let resolvedTarget;
|
|
30324
30547
|
let taskProvider;
|
|
@@ -30439,10 +30662,10 @@ function computeSummary(results, durationMs) {
|
|
|
30439
30662
|
var TARGET_FILE_CANDIDATES = [".agentv/targets.yaml", ".agentv/targets.yml"];
|
|
30440
30663
|
async function discoverDefaultTarget(repoRoot) {
|
|
30441
30664
|
const cwd = process.cwd();
|
|
30442
|
-
const chain = buildDirectoryChain(
|
|
30665
|
+
const chain = buildDirectoryChain(path43.join(cwd, "_placeholder"), repoRoot);
|
|
30443
30666
|
for (const dir of chain) {
|
|
30444
30667
|
for (const candidate of TARGET_FILE_CANDIDATES) {
|
|
30445
|
-
const targetsPath =
|
|
30668
|
+
const targetsPath = path43.join(dir, candidate);
|
|
30446
30669
|
if (!existsSync4(targetsPath)) continue;
|
|
30447
30670
|
try {
|
|
30448
30671
|
const definitions = await readTargetDefinitions(targetsPath);
|
|
@@ -30459,7 +30682,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
|
|
|
30459
30682
|
const chain = buildDirectoryChain(startPath, repoRoot);
|
|
30460
30683
|
const envFiles = [];
|
|
30461
30684
|
for (const dir of chain) {
|
|
30462
|
-
const envPath =
|
|
30685
|
+
const envPath = path43.join(dir, ".env");
|
|
30463
30686
|
if (existsSync4(envPath)) envFiles.push(envPath);
|
|
30464
30687
|
}
|
|
30465
30688
|
for (let i = 0; i < envFiles.length; i++) {
|
|
@@ -30648,13 +30871,13 @@ var ResponseCache = class {
|
|
|
30648
30871
|
}
|
|
30649
30872
|
async set(key, value) {
|
|
30650
30873
|
const filePath = this.keyToPath(key);
|
|
30651
|
-
const dir =
|
|
30652
|
-
await
|
|
30874
|
+
const dir = path44.dirname(filePath);
|
|
30875
|
+
await mkdir15(dir, { recursive: true });
|
|
30653
30876
|
await writeFile8(filePath, JSON.stringify(value, null, 2), "utf8");
|
|
30654
30877
|
}
|
|
30655
30878
|
keyToPath(key) {
|
|
30656
30879
|
const prefix = key.slice(0, 2);
|
|
30657
|
-
return
|
|
30880
|
+
return path44.join(this.cachePath, prefix, `${key}.json`);
|
|
30658
30881
|
}
|
|
30659
30882
|
};
|
|
30660
30883
|
function shouldEnableCache(params) {
|
|
@@ -30784,7 +31007,7 @@ var OtelTraceExporter = class {
|
|
|
30784
31007
|
);
|
|
30785
31008
|
}
|
|
30786
31009
|
if (this.options.traceFilePath) {
|
|
30787
|
-
const { SimpleTraceFileExporter: SimpleTraceFileExporter2 } = await import("./simple-trace-file-exporter-
|
|
31010
|
+
const { SimpleTraceFileExporter: SimpleTraceFileExporter2 } = await import("./simple-trace-file-exporter-CRIO5HDZ-QYYT2QQT.js");
|
|
30788
31011
|
processors.push(
|
|
30789
31012
|
new SimpleSpanProcessor(new SimpleTraceFileExporter2(this.options.traceFilePath))
|
|
30790
31013
|
);
|
|
@@ -30848,6 +31071,17 @@ var OtelTraceExporter = class {
|
|
|
30848
31071
|
if (result.durationMs != null)
|
|
30849
31072
|
rootSpan.setAttribute("agentv.trace.duration_ms", result.durationMs);
|
|
30850
31073
|
if (result.costUsd != null) rootSpan.setAttribute("agentv.trace.cost_usd", result.costUsd);
|
|
31074
|
+
if (result.tokenUsage) {
|
|
31075
|
+
if (result.tokenUsage.input != null) {
|
|
31076
|
+
rootSpan.setAttribute("agentv.trace.token_input", result.tokenUsage.input);
|
|
31077
|
+
}
|
|
31078
|
+
if (result.tokenUsage.output != null) {
|
|
31079
|
+
rootSpan.setAttribute("agentv.trace.token_output", result.tokenUsage.output);
|
|
31080
|
+
}
|
|
31081
|
+
if (result.tokenUsage.cached != null) {
|
|
31082
|
+
rootSpan.setAttribute("agentv.trace.token_cached", result.tokenUsage.cached);
|
|
31083
|
+
}
|
|
31084
|
+
}
|
|
30851
31085
|
if (result.trace) {
|
|
30852
31086
|
const t = result.trace;
|
|
30853
31087
|
rootSpan.setAttribute("agentv.trace.event_count", t.eventCount);
|
|
@@ -30950,6 +31184,7 @@ var OtelTraceExporter = class {
|
|
|
30950
31184
|
tracer.startActiveSpan(
|
|
30951
31185
|
spanName,
|
|
30952
31186
|
{ startTime: startHr },
|
|
31187
|
+
parentCtx,
|
|
30953
31188
|
(span) => {
|
|
30954
31189
|
if (isAssistant) {
|
|
30955
31190
|
span.setAttribute("gen_ai.operation.name", "chat");
|
|
@@ -30982,6 +31217,7 @@ var OtelTraceExporter = class {
|
|
|
30982
31217
|
tracer.startActiveSpan(
|
|
30983
31218
|
`execute_tool ${tc.tool}`,
|
|
30984
31219
|
{},
|
|
31220
|
+
msgCtx,
|
|
30985
31221
|
(toolSpan) => {
|
|
30986
31222
|
toolSpan.setAttribute("gen_ai.tool.name", tc.tool);
|
|
30987
31223
|
if (tc.id) toolSpan.setAttribute("gen_ai.tool.call.id", tc.id);
|
|
@@ -31022,8 +31258,12 @@ var OtelStreamingObserver = class {
|
|
|
31022
31258
|
rootSpan = null;
|
|
31023
31259
|
// biome-ignore lint/suspicious/noExplicitAny: OTel context loaded dynamically
|
|
31024
31260
|
rootCtx = null;
|
|
31261
|
+
observedChildSpans = false;
|
|
31262
|
+
pendingMetrics = null;
|
|
31025
31263
|
/** Create root eval span immediately (visible in backend right away) */
|
|
31026
31264
|
startEvalCase(testId, target, evalSet) {
|
|
31265
|
+
this.pendingMetrics = null;
|
|
31266
|
+
this.observedChildSpans = false;
|
|
31027
31267
|
const ctx = this.parentCtx ?? this.api.context.active();
|
|
31028
31268
|
this.rootSpan = this.tracer.startSpan("agentv.eval", void 0, ctx);
|
|
31029
31269
|
this.rootSpan.setAttribute("gen_ai.operation.name", "evaluate");
|
|
@@ -31036,8 +31276,9 @@ var OtelStreamingObserver = class {
|
|
|
31036
31276
|
/** Create and immediately export a tool span */
|
|
31037
31277
|
onToolCall(name21, input, output, _durationMs, toolCallId) {
|
|
31038
31278
|
if (!this.rootCtx) return;
|
|
31279
|
+
this.observedChildSpans = true;
|
|
31039
31280
|
this.api.context.with(this.rootCtx, () => {
|
|
31040
|
-
const span = this.tracer.startSpan(`execute_tool ${name21}
|
|
31281
|
+
const span = this.tracer.startSpan(`execute_tool ${name21}`, void 0, this.rootCtx);
|
|
31041
31282
|
span.setAttribute("gen_ai.tool.name", name21);
|
|
31042
31283
|
if (toolCallId) span.setAttribute("gen_ai.tool.call.id", toolCallId);
|
|
31043
31284
|
if (this.captureContent) {
|
|
@@ -31058,8 +31299,9 @@ var OtelStreamingObserver = class {
|
|
|
31058
31299
|
/** Create and immediately export an LLM span */
|
|
31059
31300
|
onLlmCall(model, tokenUsage) {
|
|
31060
31301
|
if (!this.rootCtx) return;
|
|
31302
|
+
this.observedChildSpans = true;
|
|
31061
31303
|
this.api.context.with(this.rootCtx, () => {
|
|
31062
|
-
const span = this.tracer.startSpan(`chat ${model}
|
|
31304
|
+
const span = this.tracer.startSpan(`chat ${model}`, void 0, this.rootCtx);
|
|
31063
31305
|
span.setAttribute("gen_ai.operation.name", "chat");
|
|
31064
31306
|
span.setAttribute("gen_ai.request.model", model);
|
|
31065
31307
|
span.setAttribute("gen_ai.response.model", model);
|
|
@@ -31074,10 +31316,53 @@ var OtelStreamingObserver = class {
|
|
|
31074
31316
|
span.end();
|
|
31075
31317
|
});
|
|
31076
31318
|
}
|
|
31319
|
+
/** Record final execution metrics before the root span is finalized. */
|
|
31320
|
+
recordEvalMetrics(result) {
|
|
31321
|
+
this.pendingMetrics = result;
|
|
31322
|
+
}
|
|
31077
31323
|
/** Finalize root span with score/verdict after evaluation completes */
|
|
31078
31324
|
finalizeEvalCase(score, error) {
|
|
31079
31325
|
if (!this.rootSpan) return;
|
|
31080
31326
|
this.rootSpan.setAttribute("agentv.score", score);
|
|
31327
|
+
if (this.pendingMetrics?.durationMs != null) {
|
|
31328
|
+
this.rootSpan.setAttribute("agentv.trace.duration_ms", this.pendingMetrics.durationMs);
|
|
31329
|
+
}
|
|
31330
|
+
if (this.pendingMetrics?.costUsd != null) {
|
|
31331
|
+
this.rootSpan.setAttribute("agentv.trace.cost_usd", this.pendingMetrics.costUsd);
|
|
31332
|
+
}
|
|
31333
|
+
if (this.pendingMetrics?.tokenUsage) {
|
|
31334
|
+
if (this.pendingMetrics.tokenUsage.input != null) {
|
|
31335
|
+
this.rootSpan.setAttribute(
|
|
31336
|
+
"agentv.trace.token_input",
|
|
31337
|
+
this.pendingMetrics.tokenUsage.input
|
|
31338
|
+
);
|
|
31339
|
+
}
|
|
31340
|
+
if (this.pendingMetrics.tokenUsage.output != null) {
|
|
31341
|
+
this.rootSpan.setAttribute(
|
|
31342
|
+
"agentv.trace.token_output",
|
|
31343
|
+
this.pendingMetrics.tokenUsage.output
|
|
31344
|
+
);
|
|
31345
|
+
}
|
|
31346
|
+
if (this.pendingMetrics.tokenUsage.cached != null) {
|
|
31347
|
+
this.rootSpan.setAttribute(
|
|
31348
|
+
"agentv.trace.token_cached",
|
|
31349
|
+
this.pendingMetrics.tokenUsage.cached
|
|
31350
|
+
);
|
|
31351
|
+
}
|
|
31352
|
+
}
|
|
31353
|
+
if (this.pendingMetrics?.trace) {
|
|
31354
|
+
this.rootSpan.setAttribute("agentv.trace.event_count", this.pendingMetrics.trace.eventCount);
|
|
31355
|
+
this.rootSpan.setAttribute(
|
|
31356
|
+
"agentv.trace.tool_names",
|
|
31357
|
+
Object.keys(this.pendingMetrics.trace.toolCalls).sort().join(",")
|
|
31358
|
+
);
|
|
31359
|
+
if (this.pendingMetrics.trace.llmCallCount != null) {
|
|
31360
|
+
this.rootSpan.setAttribute(
|
|
31361
|
+
"agentv.trace.llm_call_count",
|
|
31362
|
+
this.pendingMetrics.trace.llmCallCount
|
|
31363
|
+
);
|
|
31364
|
+
}
|
|
31365
|
+
}
|
|
31081
31366
|
if (error) {
|
|
31082
31367
|
this.rootSpan.setStatus({ code: this.api.SpanStatusCode.ERROR, message: error });
|
|
31083
31368
|
} else {
|
|
@@ -31086,6 +31371,33 @@ var OtelStreamingObserver = class {
|
|
|
31086
31371
|
this.rootSpan.end();
|
|
31087
31372
|
this.rootSpan = null;
|
|
31088
31373
|
this.rootCtx = null;
|
|
31374
|
+
this.observedChildSpans = false;
|
|
31375
|
+
this.pendingMetrics = null;
|
|
31376
|
+
}
|
|
31377
|
+
/** Backfill child spans from the completed result when the provider emitted no live callbacks. */
|
|
31378
|
+
completeFromResult(result) {
|
|
31379
|
+
this.recordEvalMetrics({
|
|
31380
|
+
durationMs: result.durationMs,
|
|
31381
|
+
costUsd: result.costUsd,
|
|
31382
|
+
tokenUsage: result.tokenUsage,
|
|
31383
|
+
trace: result.trace
|
|
31384
|
+
});
|
|
31385
|
+
if (this.observedChildSpans || !this.rootCtx) {
|
|
31386
|
+
return;
|
|
31387
|
+
}
|
|
31388
|
+
const model = result.output.find((msg) => msg.role === "assistant")?.metadata?.model ?? result.target ?? "unknown";
|
|
31389
|
+
this.onLlmCall(String(model), result.tokenUsage);
|
|
31390
|
+
for (const message of result.output) {
|
|
31391
|
+
for (const toolCall of message.toolCalls ?? []) {
|
|
31392
|
+
this.onToolCall(
|
|
31393
|
+
toolCall.tool,
|
|
31394
|
+
toolCall.input,
|
|
31395
|
+
toolCall.output,
|
|
31396
|
+
toolCall.durationMs ?? 0,
|
|
31397
|
+
toolCall.id
|
|
31398
|
+
);
|
|
31399
|
+
}
|
|
31400
|
+
}
|
|
31089
31401
|
}
|
|
31090
31402
|
/** Return the active eval span's trace ID and span ID for Braintrust trace bridging */
|
|
31091
31403
|
getActiveSpanIds() {
|
|
@@ -31276,4 +31588,4 @@ export {
|
|
|
31276
31588
|
OtelStreamingObserver,
|
|
31277
31589
|
createAgentKernel
|
|
31278
31590
|
};
|
|
31279
|
-
//# sourceMappingURL=chunk-
|
|
31591
|
+
//# sourceMappingURL=chunk-UYBLUYHN.js.map
|