@agentv/core 4.9.1 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-VCVVKCC4.js → chunk-BWHUWLGW.js} +1 -1
- package/dist/chunk-BWHUWLGW.js.map +1 -0
- package/dist/evaluation/validation/index.cjs.map +1 -1
- package/dist/evaluation/validation/index.js +1 -1
- package/dist/index.cjs +1006 -728
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -5
- package/dist/index.d.ts +20 -5
- package/dist/index.js +833 -556
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-VCVVKCC4.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveDelegatedTargetDefinition,
|
|
26
26
|
resolveFileReference,
|
|
27
27
|
resolveTargetDefinition
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-BWHUWLGW.js";
|
|
29
29
|
import {
|
|
30
30
|
AgentvProvider
|
|
31
31
|
} from "./chunk-PRNXHNLF.js";
|
|
@@ -152,8 +152,8 @@ function mergeExecutionMetrics(computed, metrics) {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
// src/evaluation/yaml-parser.ts
|
|
155
|
-
import { readFile as
|
|
156
|
-
import
|
|
155
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
156
|
+
import path8 from "node:path";
|
|
157
157
|
import micromatch2 from "micromatch";
|
|
158
158
|
import { parse as parse2 } from "yaml";
|
|
159
159
|
|
|
@@ -684,10 +684,318 @@ function logWarning(message) {
|
|
|
684
684
|
}
|
|
685
685
|
|
|
686
686
|
// src/evaluation/loaders/evaluator-parser.ts
|
|
687
|
+
import path5 from "node:path";
|
|
688
|
+
|
|
689
|
+
// src/evaluation/content-preprocessor.ts
|
|
690
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
687
691
|
import path4 from "node:path";
|
|
692
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
693
|
+
|
|
694
|
+
// src/runtime/exec.ts
|
|
695
|
+
function shellEscapePath(value) {
|
|
696
|
+
if (process.platform === "win32") {
|
|
697
|
+
return `"${value.replaceAll('"', '""')}"`;
|
|
698
|
+
}
|
|
699
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
700
|
+
}
|
|
701
|
+
async function execFileWithStdin(argv, stdinPayload, options = {}) {
|
|
702
|
+
if (argv.length === 0) {
|
|
703
|
+
throw new Error("Executable argv must include at least one entry");
|
|
704
|
+
}
|
|
705
|
+
if (typeof Bun !== "undefined") {
|
|
706
|
+
return execFileWithStdinBun(argv, stdinPayload, options);
|
|
707
|
+
}
|
|
708
|
+
return execFileWithStdinNode(argv, stdinPayload, options);
|
|
709
|
+
}
|
|
710
|
+
async function execFileWithStdinBun(argv, stdinPayload, options) {
|
|
711
|
+
const command = [...argv];
|
|
712
|
+
const encoder = new TextEncoder();
|
|
713
|
+
const proc = Bun.spawn(command, {
|
|
714
|
+
cwd: options.cwd,
|
|
715
|
+
stdin: encoder.encode(stdinPayload),
|
|
716
|
+
stdout: "pipe",
|
|
717
|
+
stderr: "pipe",
|
|
718
|
+
// Merge additional env vars with process.env
|
|
719
|
+
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
720
|
+
});
|
|
721
|
+
let timedOut = false;
|
|
722
|
+
const timeout = options.timeoutMs !== void 0 ? setTimeout(() => {
|
|
723
|
+
timedOut = true;
|
|
724
|
+
proc.kill("SIGKILL");
|
|
725
|
+
}, options.timeoutMs) : void 0;
|
|
726
|
+
try {
|
|
727
|
+
const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve("");
|
|
728
|
+
const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve("");
|
|
729
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
730
|
+
stdoutPromise,
|
|
731
|
+
stderrPromise,
|
|
732
|
+
proc.exited
|
|
733
|
+
]);
|
|
734
|
+
if (timedOut) {
|
|
735
|
+
throw new Error(`Process timed out after ${options.timeoutMs}ms`);
|
|
736
|
+
}
|
|
737
|
+
return {
|
|
738
|
+
stdout: stdout.replace(/\r\n/g, "\n"),
|
|
739
|
+
stderr: stderr.replace(/\r\n/g, "\n"),
|
|
740
|
+
exitCode
|
|
741
|
+
};
|
|
742
|
+
} finally {
|
|
743
|
+
if (timeout !== void 0) {
|
|
744
|
+
clearTimeout(timeout);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
async function execFileWithStdinNode(argv, stdinPayload, options) {
|
|
749
|
+
const { spawn: spawn5 } = await import("node:child_process");
|
|
750
|
+
return new Promise((resolve, reject) => {
|
|
751
|
+
const [cmd, ...args] = argv;
|
|
752
|
+
const child = spawn5(cmd, args, {
|
|
753
|
+
cwd: options.cwd,
|
|
754
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
755
|
+
// Merge additional env vars with process.env
|
|
756
|
+
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
757
|
+
});
|
|
758
|
+
const stdoutChunks = [];
|
|
759
|
+
const stderrChunks = [];
|
|
760
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
761
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
762
|
+
let timedOut = false;
|
|
763
|
+
const timeout = options.timeoutMs !== void 0 ? setTimeout(() => {
|
|
764
|
+
timedOut = true;
|
|
765
|
+
child.kill("SIGKILL");
|
|
766
|
+
}, options.timeoutMs) : void 0;
|
|
767
|
+
child.on("error", (error) => {
|
|
768
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
769
|
+
reject(error);
|
|
770
|
+
});
|
|
771
|
+
child.on("close", (code) => {
|
|
772
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
773
|
+
if (timedOut) {
|
|
774
|
+
reject(new Error(`Process timed out after ${options.timeoutMs}ms`));
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
const stdout = Buffer.concat(stdoutChunks).toString("utf8").replace(/\r\n/g, "\n");
|
|
778
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8").replace(/\r\n/g, "\n");
|
|
779
|
+
resolve({
|
|
780
|
+
stdout,
|
|
781
|
+
stderr,
|
|
782
|
+
exitCode: code ?? 0
|
|
783
|
+
});
|
|
784
|
+
});
|
|
785
|
+
if (child.stdin) {
|
|
786
|
+
child.stdin.write(stdinPayload);
|
|
787
|
+
child.stdin.end();
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
async function execShellWithStdin(command, stdinPayload, options = {}) {
|
|
792
|
+
const { mkdir: mkdir16, readFile: readFile17, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
|
|
793
|
+
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
794
|
+
const path52 = await import("node:path");
|
|
795
|
+
const { randomUUID: randomUUID10 } = await import("node:crypto");
|
|
796
|
+
const dir = path52.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
|
|
797
|
+
await mkdir16(dir, { recursive: true });
|
|
798
|
+
const stdinPath = path52.join(dir, "stdin.txt");
|
|
799
|
+
const stdoutPath = path52.join(dir, "stdout.txt");
|
|
800
|
+
const stderrPath = path52.join(dir, "stderr.txt");
|
|
801
|
+
await writeFile9(stdinPath, stdinPayload, "utf8");
|
|
802
|
+
const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
|
|
803
|
+
const { spawn: spawn5 } = await import("node:child_process");
|
|
804
|
+
try {
|
|
805
|
+
const exitCode = await new Promise((resolve, reject) => {
|
|
806
|
+
const child = spawn5(wrappedCommand, {
|
|
807
|
+
shell: true,
|
|
808
|
+
cwd: options.cwd,
|
|
809
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
810
|
+
// Merge additional env vars with process.env
|
|
811
|
+
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
812
|
+
});
|
|
813
|
+
const timeout = options.timeoutMs ? setTimeout(() => {
|
|
814
|
+
child.kill();
|
|
815
|
+
reject(new Error(`Process timed out after ${options.timeoutMs}ms`));
|
|
816
|
+
}, options.timeoutMs) : void 0;
|
|
817
|
+
child.on("error", (error) => {
|
|
818
|
+
if (timeout !== void 0) {
|
|
819
|
+
clearTimeout(timeout);
|
|
820
|
+
}
|
|
821
|
+
reject(error);
|
|
822
|
+
});
|
|
823
|
+
child.on("exit", (code) => {
|
|
824
|
+
if (timeout !== void 0) {
|
|
825
|
+
clearTimeout(timeout);
|
|
826
|
+
}
|
|
827
|
+
resolve(code ?? 0);
|
|
828
|
+
});
|
|
829
|
+
});
|
|
830
|
+
const stdout = (await readFile17(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
|
|
831
|
+
const stderr = (await readFile17(stderrPath, "utf8")).replace(/\r\n/g, "\n");
|
|
832
|
+
return { stdout, stderr, exitCode };
|
|
833
|
+
} finally {
|
|
834
|
+
await rm6(dir, { recursive: true, force: true });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// src/evaluation/content-preprocessor.ts
|
|
839
|
+
var MIME_TYPE_ALIASES = {
|
|
840
|
+
csv: "text/csv",
|
|
841
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
842
|
+
htm: "text/html",
|
|
843
|
+
html: "text/html",
|
|
844
|
+
json: "application/json",
|
|
845
|
+
markdown: "text/markdown",
|
|
846
|
+
md: "text/markdown",
|
|
847
|
+
pdf: "application/pdf",
|
|
848
|
+
sql: "application/sql",
|
|
849
|
+
txt: "text/plain",
|
|
850
|
+
xhtml: "application/xhtml+xml",
|
|
851
|
+
xls: "application/vnd.ms-excel",
|
|
852
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
853
|
+
xml: "application/xml",
|
|
854
|
+
yaml: "application/yaml",
|
|
855
|
+
yml: "application/yaml"
|
|
856
|
+
};
|
|
857
|
+
var REPLACEMENT_CHAR = "\uFFFD";
|
|
858
|
+
async function extractTextWithPreprocessors(content, preprocessors, options = {}) {
|
|
859
|
+
if (typeof content === "string") {
|
|
860
|
+
return { text: content, warnings: [] };
|
|
861
|
+
}
|
|
862
|
+
if (!content || content.length === 0) {
|
|
863
|
+
return { text: "", warnings: [] };
|
|
864
|
+
}
|
|
865
|
+
const parts = [];
|
|
866
|
+
const warnings = [];
|
|
867
|
+
for (const block of content) {
|
|
868
|
+
if (block.type === "text") {
|
|
869
|
+
parts.push(block.text);
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
if (block.type !== "file") {
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
const result = await preprocessContentFile(block, preprocessors, options.basePath);
|
|
876
|
+
if (result.text) {
|
|
877
|
+
parts.push(result.text);
|
|
878
|
+
}
|
|
879
|
+
warnings.push(...result.warnings);
|
|
880
|
+
}
|
|
881
|
+
return { text: parts.join("\n"), warnings };
|
|
882
|
+
}
|
|
883
|
+
async function preprocessContentFile(block, preprocessors, basePath) {
|
|
884
|
+
const mediaType = normalizePreprocessorType(block.media_type);
|
|
885
|
+
const resolvedPath = resolveLocalFilePath(block.path, basePath);
|
|
886
|
+
if (!resolvedPath) {
|
|
887
|
+
return {
|
|
888
|
+
text: "",
|
|
889
|
+
warnings: [
|
|
890
|
+
{
|
|
891
|
+
file: block.path,
|
|
892
|
+
mediaType: block.media_type,
|
|
893
|
+
reason: "remote file paths are not supported for preprocessing"
|
|
894
|
+
}
|
|
895
|
+
]
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
const preprocessor = preprocessors?.find(
|
|
899
|
+
(entry) => normalizePreprocessorType(entry.type) === mediaType
|
|
900
|
+
);
|
|
901
|
+
if (preprocessor) {
|
|
902
|
+
return runContentPreprocessor(block, resolvedPath, preprocessor);
|
|
903
|
+
}
|
|
904
|
+
try {
|
|
905
|
+
const buffer = await readFile3(resolvedPath);
|
|
906
|
+
const text = buffer.toString("utf8").replace(/\r\n/g, "\n");
|
|
907
|
+
if (buffer.includes(0) || text.includes(REPLACEMENT_CHAR)) {
|
|
908
|
+
return {
|
|
909
|
+
text: "",
|
|
910
|
+
warnings: [
|
|
911
|
+
{
|
|
912
|
+
file: block.path,
|
|
913
|
+
mediaType: block.media_type,
|
|
914
|
+
reason: "default UTF-8 read produced binary or invalid text; configure a preprocessor"
|
|
915
|
+
}
|
|
916
|
+
]
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
return { text: formatFileText(block.path, text), warnings: [] };
|
|
920
|
+
} catch (error) {
|
|
921
|
+
return {
|
|
922
|
+
text: "",
|
|
923
|
+
warnings: [
|
|
924
|
+
{
|
|
925
|
+
file: block.path,
|
|
926
|
+
mediaType: block.media_type,
|
|
927
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
928
|
+
}
|
|
929
|
+
]
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
async function runContentPreprocessor(block, resolvedPath, preprocessor) {
|
|
934
|
+
try {
|
|
935
|
+
const argv = preprocessor.resolvedCommand ?? preprocessor.command;
|
|
936
|
+
const { stdout, stderr, exitCode } = await execFileWithStdin(
|
|
937
|
+
argv,
|
|
938
|
+
JSON.stringify({
|
|
939
|
+
path: resolvedPath,
|
|
940
|
+
original_path: block.path,
|
|
941
|
+
media_type: block.media_type
|
|
942
|
+
})
|
|
943
|
+
);
|
|
944
|
+
if (exitCode !== 0) {
|
|
945
|
+
return {
|
|
946
|
+
text: "",
|
|
947
|
+
warnings: [
|
|
948
|
+
{
|
|
949
|
+
file: block.path,
|
|
950
|
+
mediaType: block.media_type,
|
|
951
|
+
reason: stderr.trim() || `preprocessor exited with code ${exitCode}`
|
|
952
|
+
}
|
|
953
|
+
]
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
return { text: formatFileText(block.path, stdout.trim()), warnings: [] };
|
|
957
|
+
} catch (error) {
|
|
958
|
+
return {
|
|
959
|
+
text: "",
|
|
960
|
+
warnings: [
|
|
961
|
+
{
|
|
962
|
+
file: block.path,
|
|
963
|
+
mediaType: block.media_type,
|
|
964
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
965
|
+
}
|
|
966
|
+
]
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
function appendPreprocessingWarnings(text, warnings) {
|
|
971
|
+
if (warnings.length === 0) {
|
|
972
|
+
return text;
|
|
973
|
+
}
|
|
974
|
+
const notes = warnings.map(
|
|
975
|
+
(warning) => `[file preprocessing warning] ${warning.file} (${warning.mediaType}): ${warning.reason}`
|
|
976
|
+
);
|
|
977
|
+
return [text, ...notes].filter((part) => part.length > 0).join("\n");
|
|
978
|
+
}
|
|
979
|
+
function normalizePreprocessorType(value) {
|
|
980
|
+
const normalized = value.trim().toLowerCase();
|
|
981
|
+
return MIME_TYPE_ALIASES[normalized] ?? normalized;
|
|
982
|
+
}
|
|
983
|
+
function resolveLocalFilePath(value, basePath) {
|
|
984
|
+
if (value.startsWith("file://")) {
|
|
985
|
+
return fileURLToPath2(value);
|
|
986
|
+
}
|
|
987
|
+
if (/^[a-z]+:\/\//i.test(value)) {
|
|
988
|
+
return void 0;
|
|
989
|
+
}
|
|
990
|
+
return basePath ? path4.resolve(basePath, value) : path4.resolve(value);
|
|
991
|
+
}
|
|
992
|
+
function formatFileText(filePath, text) {
|
|
993
|
+
return `[[ file: ${filePath} ]]
|
|
994
|
+
${text}`;
|
|
995
|
+
}
|
|
688
996
|
|
|
689
997
|
// src/evaluation/validation/prompt-validator.ts
|
|
690
|
-
import { readFile as
|
|
998
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
691
999
|
|
|
692
1000
|
// src/evaluation/template-variables.ts
|
|
693
1001
|
var TEMPLATE_VARIABLES = {
|
|
@@ -718,7 +1026,7 @@ var DEPRECATED_TEMPLATE_VARIABLES = /* @__PURE__ */ new Map([
|
|
|
718
1026
|
var ANSI_YELLOW2 = "\x1B[33m";
|
|
719
1027
|
var ANSI_RESET3 = "\x1B[0m";
|
|
720
1028
|
async function validateCustomPromptContent(promptPath) {
|
|
721
|
-
const content = await
|
|
1029
|
+
const content = await readFile4(promptPath, "utf8");
|
|
722
1030
|
validateTemplateVariables(content, promptPath);
|
|
723
1031
|
}
|
|
724
1032
|
function validateTemplateVariables(content, source) {
|
|
@@ -775,22 +1083,32 @@ function normalizeEvaluatorType(type) {
|
|
|
775
1083
|
function isDeprecatedJudgeType(type) {
|
|
776
1084
|
return type === "code-judge" || type === "llm-judge";
|
|
777
1085
|
}
|
|
778
|
-
async function parseEvaluators(rawEvalCase, globalExecution, searchRoots, evalId) {
|
|
1086
|
+
async function parseEvaluators(rawEvalCase, globalExecution, searchRoots, evalId, defaultPreprocessors) {
|
|
779
1087
|
const execution = rawEvalCase.execution;
|
|
780
1088
|
const executionObject = isJsonObject2(execution) ? execution : void 0;
|
|
781
1089
|
const caseEvaluators = rawEvalCase.assertions ?? rawEvalCase.assert ?? (executionObject ? executionObject.evaluators : void 0) ?? // deprecated: use assertions
|
|
782
1090
|
rawEvalCase.evaluators;
|
|
783
1091
|
const skipDefaults = executionObject?.skip_defaults === true;
|
|
784
1092
|
const rootEvaluators = skipDefaults ? void 0 : globalExecution?.assertions ?? globalExecution?.assert ?? globalExecution?.evaluators;
|
|
785
|
-
const parsedCase = await parseEvaluatorList(
|
|
786
|
-
|
|
1093
|
+
const parsedCase = await parseEvaluatorList(
|
|
1094
|
+
caseEvaluators,
|
|
1095
|
+
searchRoots,
|
|
1096
|
+
evalId,
|
|
1097
|
+
defaultPreprocessors
|
|
1098
|
+
);
|
|
1099
|
+
const parsedRoot = await parseEvaluatorList(
|
|
1100
|
+
rootEvaluators,
|
|
1101
|
+
searchRoots,
|
|
1102
|
+
evalId,
|
|
1103
|
+
defaultPreprocessors
|
|
1104
|
+
);
|
|
787
1105
|
if (!parsedCase && !parsedRoot) {
|
|
788
1106
|
return void 0;
|
|
789
1107
|
}
|
|
790
1108
|
const evaluators = [...parsedCase ?? [], ...parsedRoot ?? []];
|
|
791
1109
|
return evaluators.length > 0 ? evaluators : void 0;
|
|
792
1110
|
}
|
|
793
|
-
async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
1111
|
+
async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId, defaultPreprocessors) {
|
|
794
1112
|
if (candidateEvaluators === void 0) {
|
|
795
1113
|
return void 0;
|
|
796
1114
|
}
|
|
@@ -855,6 +1173,13 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
855
1173
|
continue;
|
|
856
1174
|
}
|
|
857
1175
|
const negate = rawEvaluator.negate === true ? true : void 0;
|
|
1176
|
+
const mergedPreprocessors = await parseMergedPreprocessors(
|
|
1177
|
+
rawEvaluator.preprocessors,
|
|
1178
|
+
defaultPreprocessors,
|
|
1179
|
+
searchRoots,
|
|
1180
|
+
name,
|
|
1181
|
+
evalId
|
|
1182
|
+
);
|
|
858
1183
|
if (isCustomType) {
|
|
859
1184
|
const weight2 = validateWeight(rawEvaluator.weight, name, evalId);
|
|
860
1185
|
const { required: required2, min_score: min_score2 } = parseRequiredAndMinScore(
|
|
@@ -913,7 +1238,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
913
1238
|
if (cwd) {
|
|
914
1239
|
const resolved = await resolveFileReference2(cwd, searchRoots);
|
|
915
1240
|
if (resolved.resolvedPath) {
|
|
916
|
-
resolvedCwd =
|
|
1241
|
+
resolvedCwd = path5.resolve(resolved.resolvedPath);
|
|
917
1242
|
} else {
|
|
918
1243
|
logWarning2(
|
|
919
1244
|
`Code-grader evaluator '${name}' in '${evalId}': cwd not found (${resolved.displayPath})`,
|
|
@@ -959,6 +1284,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
959
1284
|
"cwd",
|
|
960
1285
|
"weight",
|
|
961
1286
|
"target",
|
|
1287
|
+
"preprocessors",
|
|
962
1288
|
"required",
|
|
963
1289
|
"negate"
|
|
964
1290
|
]);
|
|
@@ -979,6 +1305,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
979
1305
|
...min_score2 !== void 0 ? { min_score: min_score2 } : {},
|
|
980
1306
|
...negate !== void 0 ? { negate } : {},
|
|
981
1307
|
...Object.keys(config2).length > 0 ? { config: config2 } : {},
|
|
1308
|
+
...mergedPreprocessors ? { preprocessors: mergedPreprocessors } : {},
|
|
982
1309
|
...targetConfig !== void 0 ? { target: targetConfig } : {}
|
|
983
1310
|
});
|
|
984
1311
|
continue;
|
|
@@ -1088,7 +1415,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1088
1415
|
aggregatorPrompt = fileRef;
|
|
1089
1416
|
const resolved = await resolveFileReference2(fileRef, searchRoots);
|
|
1090
1417
|
if (resolved.resolvedPath) {
|
|
1091
|
-
promptPath2 =
|
|
1418
|
+
promptPath2 = path5.resolve(resolved.resolvedPath);
|
|
1092
1419
|
} else {
|
|
1093
1420
|
throw new Error(
|
|
1094
1421
|
`Composite aggregator in '${evalId}': prompt file not found: ${resolved.displayPath}`
|
|
@@ -1742,7 +2069,8 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1742
2069
|
...weight2 !== void 0 ? { weight: weight2 } : {},
|
|
1743
2070
|
...required2 !== void 0 ? { required: required2 } : {},
|
|
1744
2071
|
...min_score2 !== void 0 ? { min_score: min_score2 } : {},
|
|
1745
|
-
...negate !== void 0 ? { negate } : {}
|
|
2072
|
+
...negate !== void 0 ? { negate } : {},
|
|
2073
|
+
...mergedPreprocessors ? { preprocessors: mergedPreprocessors } : {}
|
|
1746
2074
|
});
|
|
1747
2075
|
continue;
|
|
1748
2076
|
}
|
|
@@ -1767,7 +2095,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1767
2095
|
const commandPath = commandArray[commandArray.length - 1];
|
|
1768
2096
|
const resolved = await resolveFileReference2(commandPath, searchRoots);
|
|
1769
2097
|
if (resolved.resolvedPath) {
|
|
1770
|
-
resolvedPromptScript = [...commandArray.slice(0, -1),
|
|
2098
|
+
resolvedPromptScript = [...commandArray.slice(0, -1), path5.resolve(resolved.resolvedPath)];
|
|
1771
2099
|
} else {
|
|
1772
2100
|
throw new Error(
|
|
1773
2101
|
`Evaluator '${name}' in '${evalId}': prompt command file not found: ${resolved.displayPath}`
|
|
@@ -1782,7 +2110,7 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1782
2110
|
prompt = fileRef;
|
|
1783
2111
|
const resolved = await resolveFileReference2(fileRef, searchRoots);
|
|
1784
2112
|
if (resolved.resolvedPath) {
|
|
1785
|
-
promptPath =
|
|
2113
|
+
promptPath = path5.resolve(resolved.resolvedPath);
|
|
1786
2114
|
try {
|
|
1787
2115
|
await validateCustomPromptContent(promptPath);
|
|
1788
2116
|
} catch (error) {
|
|
@@ -1825,7 +2153,8 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1825
2153
|
...weight2 !== void 0 ? { weight: weight2 } : {},
|
|
1826
2154
|
...required2 !== void 0 ? { required: required2 } : {},
|
|
1827
2155
|
...min_score2 !== void 0 ? { min_score: min_score2 } : {},
|
|
1828
|
-
...negate !== void 0 ? { negate } : {}
|
|
2156
|
+
...negate !== void 0 ? { negate } : {},
|
|
2157
|
+
...mergedPreprocessors ? { preprocessors: mergedPreprocessors } : {}
|
|
1829
2158
|
});
|
|
1830
2159
|
continue;
|
|
1831
2160
|
}
|
|
@@ -1850,7 +2179,8 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1850
2179
|
"negate",
|
|
1851
2180
|
"max_steps",
|
|
1852
2181
|
"maxSteps",
|
|
1853
|
-
"temperature"
|
|
2182
|
+
"temperature",
|
|
2183
|
+
"preprocessors"
|
|
1854
2184
|
]);
|
|
1855
2185
|
const config = {};
|
|
1856
2186
|
for (const [key, value] of Object.entries(rawEvaluator)) {
|
|
@@ -1880,30 +2210,70 @@ async function parseEvaluatorList(candidateEvaluators, searchRoots, evalId) {
|
|
|
1880
2210
|
...negate !== void 0 ? { negate } : {},
|
|
1881
2211
|
...finalConfig ? { config: finalConfig } : {},
|
|
1882
2212
|
...llmMaxSteps !== void 0 ? { max_steps: llmMaxSteps } : {},
|
|
1883
|
-
...llmTemperature !== void 0 ? { temperature: llmTemperature } : {}
|
|
2213
|
+
...llmTemperature !== void 0 ? { temperature: llmTemperature } : {},
|
|
2214
|
+
...mergedPreprocessors ? { preprocessors: mergedPreprocessors } : {}
|
|
1884
2215
|
});
|
|
1885
2216
|
}
|
|
1886
2217
|
return evaluators.length > 0 ? evaluators : void 0;
|
|
1887
2218
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
function
|
|
1904
|
-
if (
|
|
2219
|
+
async function parseMergedPreprocessors(rawValue, defaultPreprocessors, searchRoots, evaluatorName, evalId) {
|
|
2220
|
+
const parsedDefaults = defaultPreprocessors ?? [];
|
|
2221
|
+
const parsedOverrides = await parsePreprocessors(rawValue, searchRoots, evaluatorName, evalId);
|
|
2222
|
+
if (parsedDefaults.length === 0 && (!parsedOverrides || parsedOverrides.length === 0)) {
|
|
2223
|
+
return void 0;
|
|
2224
|
+
}
|
|
2225
|
+
const merged = /* @__PURE__ */ new Map();
|
|
2226
|
+
for (const entry of parsedDefaults) {
|
|
2227
|
+
merged.set(normalizePreprocessorType(entry.type), entry);
|
|
2228
|
+
}
|
|
2229
|
+
for (const entry of parsedOverrides ?? []) {
|
|
2230
|
+
merged.set(normalizePreprocessorType(entry.type), entry);
|
|
2231
|
+
}
|
|
2232
|
+
return [...merged.values()];
|
|
2233
|
+
}
|
|
2234
|
+
async function parsePreprocessors(rawValue, searchRoots, evaluatorName, evalId) {
|
|
2235
|
+
if (rawValue === void 0) {
|
|
1905
2236
|
return void 0;
|
|
1906
2237
|
}
|
|
2238
|
+
if (!Array.isArray(rawValue)) {
|
|
2239
|
+
throw new Error(`Evaluator '${evaluatorName}' in '${evalId}': preprocessors must be an array`);
|
|
2240
|
+
}
|
|
2241
|
+
const preprocessors = [];
|
|
2242
|
+
for (const rawEntry of rawValue) {
|
|
2243
|
+
if (!isJsonObject2(rawEntry)) {
|
|
2244
|
+
throw new Error(
|
|
2245
|
+
`Evaluator '${evaluatorName}' in '${evalId}': each preprocessor must be an object`
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
const type = asString(rawEntry.type)?.trim();
|
|
2249
|
+
if (!type) {
|
|
2250
|
+
throw new Error(`Evaluator '${evaluatorName}' in '${evalId}': preprocessor.type is required`);
|
|
2251
|
+
}
|
|
2252
|
+
const command = asStringArray(
|
|
2253
|
+
rawEntry.command,
|
|
2254
|
+
`preprocessor command for evaluator '${evaluatorName}' in '${evalId}'`
|
|
2255
|
+
);
|
|
2256
|
+
if (!command || command.length === 0) {
|
|
2257
|
+
throw new Error(
|
|
2258
|
+
`Evaluator '${evaluatorName}' in '${evalId}': preprocessor '${type}' requires command`
|
|
2259
|
+
);
|
|
2260
|
+
}
|
|
2261
|
+
const commandPath = command[command.length - 1];
|
|
2262
|
+
const resolved = await resolveFileReference2(commandPath, searchRoots);
|
|
2263
|
+
if (!resolved.resolvedPath) {
|
|
2264
|
+
throw new Error(
|
|
2265
|
+
`Evaluator '${evaluatorName}' in '${evalId}': preprocessor command file not found: ${resolved.displayPath}`
|
|
2266
|
+
);
|
|
2267
|
+
}
|
|
2268
|
+
preprocessors.push({
|
|
2269
|
+
type,
|
|
2270
|
+
command,
|
|
2271
|
+
resolvedCommand: [...command.slice(0, -1), path5.resolve(resolved.resolvedPath)]
|
|
2272
|
+
});
|
|
2273
|
+
}
|
|
2274
|
+
return preprocessors;
|
|
2275
|
+
}
|
|
2276
|
+
function generateAssertionName(typeValue, rawEvaluator) {
|
|
1907
2277
|
const value = asString(rawEvaluator.value);
|
|
1908
2278
|
const arrayValue = Array.isArray(rawEvaluator.value) ? rawEvaluator.value : void 0;
|
|
1909
2279
|
switch (typeValue) {
|
|
@@ -1936,7 +2306,7 @@ function generateAssertionName(typeValue, rawEvaluator) {
|
|
|
1936
2306
|
case "rubrics":
|
|
1937
2307
|
return "rubrics";
|
|
1938
2308
|
default:
|
|
1939
|
-
return
|
|
2309
|
+
return typeValue;
|
|
1940
2310
|
}
|
|
1941
2311
|
}
|
|
1942
2312
|
function coerceEvaluator(candidate, contextId) {
|
|
@@ -2294,14 +2664,14 @@ function parseInlineRubrics(rawRubrics) {
|
|
|
2294
2664
|
}
|
|
2295
2665
|
|
|
2296
2666
|
// src/evaluation/loaders/jsonl-parser.ts
|
|
2297
|
-
import { readFile as
|
|
2298
|
-
import
|
|
2667
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
2668
|
+
import path7 from "node:path";
|
|
2299
2669
|
import micromatch from "micromatch";
|
|
2300
2670
|
import { parse as parseYaml } from "yaml";
|
|
2301
2671
|
|
|
2302
2672
|
// src/evaluation/loaders/message-processor.ts
|
|
2303
|
-
import { readFile as
|
|
2304
|
-
import
|
|
2673
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
2674
|
+
import path6 from "node:path";
|
|
2305
2675
|
|
|
2306
2676
|
// src/evaluation/formatting/segment-formatter.ts
|
|
2307
2677
|
function formatFileContents(parts) {
|
|
@@ -2367,7 +2737,7 @@ var IMAGE_MEDIA_TYPES = {
|
|
|
2367
2737
|
".bmp": "image/bmp"
|
|
2368
2738
|
};
|
|
2369
2739
|
function detectImageMediaType(filePath) {
|
|
2370
|
-
const ext =
|
|
2740
|
+
const ext = path6.extname(filePath).toLowerCase();
|
|
2371
2741
|
return IMAGE_MEDIA_TYPES[ext];
|
|
2372
2742
|
}
|
|
2373
2743
|
var ANSI_YELLOW4 = "\x1B[33m";
|
|
@@ -2417,12 +2787,12 @@ async function processMessages(options) {
|
|
|
2417
2787
|
continue;
|
|
2418
2788
|
}
|
|
2419
2789
|
try {
|
|
2420
|
-
const fileContent = (await
|
|
2790
|
+
const fileContent = (await readFile5(resolvedPath, "utf8")).replace(/\r\n/g, "\n");
|
|
2421
2791
|
processedContent.push({
|
|
2422
2792
|
...cloneJsonObject(rawSegment),
|
|
2423
2793
|
path: displayPath,
|
|
2424
2794
|
text: fileContent,
|
|
2425
|
-
resolvedPath:
|
|
2795
|
+
resolvedPath: path6.resolve(resolvedPath)
|
|
2426
2796
|
});
|
|
2427
2797
|
if (verbose) {
|
|
2428
2798
|
const label = messageType === "input" ? "[File]" : "[Expected Output File]";
|
|
@@ -2458,7 +2828,7 @@ async function processMessages(options) {
|
|
|
2458
2828
|
continue;
|
|
2459
2829
|
}
|
|
2460
2830
|
try {
|
|
2461
|
-
const imageBuffer = await
|
|
2831
|
+
const imageBuffer = await readFile5(resolvedPath);
|
|
2462
2832
|
const base64 = imageBuffer.toString("base64");
|
|
2463
2833
|
processedContent.push({
|
|
2464
2834
|
type: "image",
|
|
@@ -2535,12 +2905,12 @@ async function processExpectedMessages(options) {
|
|
|
2535
2905
|
continue;
|
|
2536
2906
|
}
|
|
2537
2907
|
try {
|
|
2538
|
-
const fileContent = (await
|
|
2908
|
+
const fileContent = (await readFile5(resolvedPath, "utf8")).replace(/\r\n/g, "\n");
|
|
2539
2909
|
processedContent.push({
|
|
2540
2910
|
type: "file",
|
|
2541
2911
|
path: displayPath,
|
|
2542
2912
|
text: fileContent,
|
|
2543
|
-
resolvedPath:
|
|
2913
|
+
resolvedPath: path6.resolve(resolvedPath)
|
|
2544
2914
|
});
|
|
2545
2915
|
if (verbose) {
|
|
2546
2916
|
console.log(` [Expected Output File] Found: ${displayPath}`);
|
|
@@ -2575,7 +2945,7 @@ async function processExpectedMessages(options) {
|
|
|
2575
2945
|
continue;
|
|
2576
2946
|
}
|
|
2577
2947
|
try {
|
|
2578
|
-
const imageBuffer = await
|
|
2948
|
+
const imageBuffer = await readFile5(resolvedPath);
|
|
2579
2949
|
const base64 = imageBuffer.toString("base64");
|
|
2580
2950
|
processedContent.push({
|
|
2581
2951
|
type: "image",
|
|
@@ -2684,7 +3054,7 @@ function matchesFilter(id, filter) {
|
|
|
2684
3054
|
return typeof filter === "string" ? micromatch.isMatch(id, filter) : filter.some((pattern) => micromatch.isMatch(id, pattern));
|
|
2685
3055
|
}
|
|
2686
3056
|
function detectFormat(filePath) {
|
|
2687
|
-
const ext =
|
|
3057
|
+
const ext = path7.extname(filePath).toLowerCase();
|
|
2688
3058
|
if (ext === ".jsonl") return "jsonl";
|
|
2689
3059
|
if (ext === ".yaml" || ext === ".yml") return "yaml";
|
|
2690
3060
|
if (ext === ".json") return "agent-skills-json";
|
|
@@ -2693,9 +3063,9 @@ function detectFormat(filePath) {
|
|
|
2693
3063
|
);
|
|
2694
3064
|
}
|
|
2695
3065
|
async function loadSidecarMetadata(jsonlPath, verbose) {
|
|
2696
|
-
const dir =
|
|
2697
|
-
const base =
|
|
2698
|
-
const sidecarPath =
|
|
3066
|
+
const dir = path7.dirname(jsonlPath);
|
|
3067
|
+
const base = path7.basename(jsonlPath, ".jsonl");
|
|
3068
|
+
const sidecarPath = path7.join(dir, `${base}.yaml`);
|
|
2699
3069
|
if (!await fileExists2(sidecarPath)) {
|
|
2700
3070
|
if (verbose) {
|
|
2701
3071
|
logWarning4(`Sidecar metadata file not found: ${sidecarPath} (using defaults)`);
|
|
@@ -2703,7 +3073,7 @@ async function loadSidecarMetadata(jsonlPath, verbose) {
|
|
|
2703
3073
|
return {};
|
|
2704
3074
|
}
|
|
2705
3075
|
try {
|
|
2706
|
-
const content = await
|
|
3076
|
+
const content = await readFile6(sidecarPath, "utf8");
|
|
2707
3077
|
const parsed = interpolateEnv(parseYaml(content), process.env);
|
|
2708
3078
|
if (!isJsonObject(parsed)) {
|
|
2709
3079
|
logWarning4(`Invalid sidecar metadata format in ${sidecarPath}`);
|
|
@@ -2744,13 +3114,13 @@ function parseJsonlContent(content, filePath) {
|
|
|
2744
3114
|
async function loadTestsFromJsonl(evalFilePath, repoRoot, options) {
|
|
2745
3115
|
const verbose = options?.verbose ?? false;
|
|
2746
3116
|
const filterPattern = options?.filter;
|
|
2747
|
-
const absoluteTestPath =
|
|
3117
|
+
const absoluteTestPath = path7.resolve(evalFilePath);
|
|
2748
3118
|
const repoRootPath = resolveToAbsolutePath(repoRoot);
|
|
2749
3119
|
const searchRoots = buildSearchRoots2(absoluteTestPath, repoRootPath);
|
|
2750
3120
|
const sidecar = await loadSidecarMetadata(absoluteTestPath, verbose);
|
|
2751
|
-
const rawFile = await
|
|
3121
|
+
const rawFile = await readFile6(absoluteTestPath, "utf8");
|
|
2752
3122
|
const rawCases = parseJsonlContent(rawFile, evalFilePath);
|
|
2753
|
-
const fallbackSuiteName =
|
|
3123
|
+
const fallbackSuiteName = path7.basename(absoluteTestPath, ".jsonl") || "eval";
|
|
2754
3124
|
const suiteName = sidecar.name && sidecar.name.trim().length > 0 ? sidecar.name : fallbackSuiteName;
|
|
2755
3125
|
const globalEvaluator = coerceEvaluator(sidecar.evaluator, "sidecar") ?? "llm-grader";
|
|
2756
3126
|
const globalExecution = sidecar.execution;
|
|
@@ -3109,8 +3479,8 @@ function resolveTests(suite) {
|
|
|
3109
3479
|
}
|
|
3110
3480
|
async function readTestSuiteMetadata(testFilePath) {
|
|
3111
3481
|
try {
|
|
3112
|
-
const absolutePath =
|
|
3113
|
-
const content = await
|
|
3482
|
+
const absolutePath = path8.resolve(testFilePath);
|
|
3483
|
+
const content = await readFile7(absolutePath, "utf8");
|
|
3114
3484
|
const parsed = interpolateEnv(parse2(content), process.env);
|
|
3115
3485
|
if (!isJsonObject(parsed)) {
|
|
3116
3486
|
return {};
|
|
@@ -3164,25 +3534,31 @@ var loadEvalCases = loadTests;
|
|
|
3164
3534
|
async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
|
|
3165
3535
|
const verbose = options?.verbose ?? false;
|
|
3166
3536
|
const filterPattern = options?.filter;
|
|
3167
|
-
const absoluteTestPath =
|
|
3537
|
+
const absoluteTestPath = path8.resolve(evalFilePath);
|
|
3168
3538
|
const repoRootPath = resolveToAbsolutePath(repoRoot);
|
|
3169
3539
|
const searchRoots = buildSearchRoots2(absoluteTestPath, repoRootPath);
|
|
3170
3540
|
const config = await loadConfig(absoluteTestPath, repoRootPath);
|
|
3171
|
-
const rawFile = await
|
|
3541
|
+
const rawFile = await readFile7(absoluteTestPath, "utf8");
|
|
3172
3542
|
const interpolated = interpolateEnv(parse2(rawFile), process.env);
|
|
3173
3543
|
if (!isJsonObject(interpolated)) {
|
|
3174
3544
|
throw new Error(`Invalid test file format: ${evalFilePath}`);
|
|
3175
3545
|
}
|
|
3176
3546
|
const suite = interpolated;
|
|
3177
3547
|
const suiteNameFromFile = asString5(suite.name)?.trim();
|
|
3178
|
-
const fallbackSuiteName =
|
|
3548
|
+
const fallbackSuiteName = path8.basename(absoluteTestPath).replace(/\.eval\.ya?ml$/i, "").replace(/\.ya?ml$/i, "") || "eval";
|
|
3179
3549
|
const suiteName = suiteNameFromFile && suiteNameFromFile.length > 0 ? suiteNameFromFile : fallbackSuiteName;
|
|
3180
3550
|
const rawTestCases = resolveTests(suite);
|
|
3181
3551
|
const globalEvaluator = coerceEvaluator(suite.evaluator, "global") ?? "llm-grader";
|
|
3182
|
-
const
|
|
3552
|
+
const suitePreprocessors = await parsePreprocessors(
|
|
3553
|
+
suite.preprocessors,
|
|
3554
|
+
searchRoots,
|
|
3555
|
+
"<suite>",
|
|
3556
|
+
absoluteTestPath
|
|
3557
|
+
);
|
|
3558
|
+
const evalFileDir = path8.dirname(absoluteTestPath);
|
|
3183
3559
|
let expandedTestCases;
|
|
3184
3560
|
if (typeof rawTestCases === "string") {
|
|
3185
|
-
const externalPath =
|
|
3561
|
+
const externalPath = path8.resolve(evalFileDir, rawTestCases);
|
|
3186
3562
|
expandedTestCases = await loadCasesFromFile(externalPath);
|
|
3187
3563
|
} else if (Array.isArray(rawTestCases)) {
|
|
3188
3564
|
expandedTestCases = await expandFileReferences(rawTestCases, evalFileDir);
|
|
@@ -3280,7 +3656,8 @@ async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
|
|
|
3280
3656
|
testCaseConfig,
|
|
3281
3657
|
globalExecution,
|
|
3282
3658
|
searchRoots,
|
|
3283
|
-
id ?? "unknown"
|
|
3659
|
+
id ?? "unknown",
|
|
3660
|
+
suitePreprocessors
|
|
3284
3661
|
);
|
|
3285
3662
|
} catch (error) {
|
|
3286
3663
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -3313,6 +3690,7 @@ async function loadTestsFromYaml(evalFilePath, repoRoot, options) {
|
|
|
3313
3690
|
criteria: outcome ?? "",
|
|
3314
3691
|
evaluator: testCaseEvaluatorKind,
|
|
3315
3692
|
assertions: evaluators,
|
|
3693
|
+
...suitePreprocessors ? { preprocessors: suitePreprocessors } : {},
|
|
3316
3694
|
workspace: mergedWorkspace,
|
|
3317
3695
|
metadata,
|
|
3318
3696
|
targets: caseTargets,
|
|
@@ -3353,8 +3731,8 @@ function parseWorkspaceScriptConfig(raw, evalFileDir) {
|
|
|
3353
3731
|
if (!command) return void 0;
|
|
3354
3732
|
const timeoutMs = typeof obj.timeout_ms === "number" ? obj.timeout_ms : void 0;
|
|
3355
3733
|
let cwd = typeof obj.cwd === "string" ? obj.cwd : void 0;
|
|
3356
|
-
if (cwd && !
|
|
3357
|
-
cwd =
|
|
3734
|
+
if (cwd && !path8.isAbsolute(cwd)) {
|
|
3735
|
+
cwd = path8.resolve(evalFileDir, cwd);
|
|
3358
3736
|
}
|
|
3359
3737
|
const config = { command };
|
|
3360
3738
|
if (timeoutMs !== void 0) {
|
|
@@ -3392,10 +3770,10 @@ function parseWorkspaceHooksConfig(raw, evalFileDir) {
|
|
|
3392
3770
|
}
|
|
3393
3771
|
async function resolveWorkspaceConfig(raw, evalFileDir) {
|
|
3394
3772
|
if (typeof raw === "string") {
|
|
3395
|
-
const workspaceFilePath =
|
|
3773
|
+
const workspaceFilePath = path8.resolve(evalFileDir, raw);
|
|
3396
3774
|
let content;
|
|
3397
3775
|
try {
|
|
3398
|
-
content = await
|
|
3776
|
+
content = await readFile7(workspaceFilePath, "utf8");
|
|
3399
3777
|
} catch {
|
|
3400
3778
|
throw new Error(`Workspace file not found: ${raw} (resolved to ${workspaceFilePath})`);
|
|
3401
3779
|
}
|
|
@@ -3405,7 +3783,7 @@ async function resolveWorkspaceConfig(raw, evalFileDir) {
|
|
|
3405
3783
|
`Invalid workspace file format: ${workspaceFilePath} (expected a YAML object)`
|
|
3406
3784
|
);
|
|
3407
3785
|
}
|
|
3408
|
-
const workspaceFileDir =
|
|
3786
|
+
const workspaceFileDir = path8.dirname(workspaceFilePath);
|
|
3409
3787
|
return parseWorkspaceConfig(parsed, workspaceFileDir);
|
|
3410
3788
|
}
|
|
3411
3789
|
return parseWorkspaceConfig(raw, evalFileDir);
|
|
@@ -3425,8 +3803,8 @@ function parseWorkspaceConfig(raw, evalFileDir) {
|
|
|
3425
3803
|
throw new Error("workspace.static has been removed. Use workspace.mode='static'.");
|
|
3426
3804
|
}
|
|
3427
3805
|
let template = typeof obj.template === "string" ? obj.template : void 0;
|
|
3428
|
-
if (template && !
|
|
3429
|
-
template =
|
|
3806
|
+
if (template && !path8.isAbsolute(template)) {
|
|
3807
|
+
template = path8.resolve(evalFileDir, template);
|
|
3430
3808
|
}
|
|
3431
3809
|
const isolation = obj.isolation === "shared" || obj.isolation === "per_test" ? obj.isolation : void 0;
|
|
3432
3810
|
const repos = Array.isArray(obj.repos) ? obj.repos.map(parseRepoConfig).filter(Boolean) : void 0;
|
|
@@ -3497,7 +3875,7 @@ ${detailBlock}${ANSI_RESET7}`);
|
|
|
3497
3875
|
|
|
3498
3876
|
// src/evaluation/loaders/eval-yaml-transpiler.ts
|
|
3499
3877
|
import { readFileSync } from "node:fs";
|
|
3500
|
-
import
|
|
3878
|
+
import path9 from "node:path";
|
|
3501
3879
|
import { parse as parse3 } from "yaml";
|
|
3502
3880
|
function codeGraderInstruction(graderName, description) {
|
|
3503
3881
|
const desc = description ? ` This grader: ${description}.` : "";
|
|
@@ -3738,7 +4116,7 @@ function transpileEvalYaml(suite, source = "EVAL.yaml") {
|
|
|
3738
4116
|
function transpileEvalYamlFile(evalYamlPath) {
|
|
3739
4117
|
const content = readFileSync(evalYamlPath, "utf8");
|
|
3740
4118
|
const parsed = parse3(content);
|
|
3741
|
-
return transpileEvalYaml(parsed,
|
|
4119
|
+
return transpileEvalYaml(parsed, path9.basename(evalYamlPath));
|
|
3742
4120
|
}
|
|
3743
4121
|
function getOutputFilenames(result) {
|
|
3744
4122
|
const names = /* @__PURE__ */ new Map();
|
|
@@ -4176,7 +4554,7 @@ import { spawn } from "node:child_process";
|
|
|
4176
4554
|
import { randomUUID } from "node:crypto";
|
|
4177
4555
|
import { createWriteStream } from "node:fs";
|
|
4178
4556
|
import { mkdir } from "node:fs/promises";
|
|
4179
|
-
import
|
|
4557
|
+
import path11 from "node:path";
|
|
4180
4558
|
|
|
4181
4559
|
// src/evaluation/providers/claude-content.ts
|
|
4182
4560
|
function toContentArray(content) {
|
|
@@ -4275,7 +4653,7 @@ function subscribeToClaudeLogEntries(listener) {
|
|
|
4275
4653
|
}
|
|
4276
4654
|
|
|
4277
4655
|
// src/evaluation/providers/preread.ts
|
|
4278
|
-
import
|
|
4656
|
+
import path10 from "node:path";
|
|
4279
4657
|
function buildPromptDocument(request, inputFiles) {
|
|
4280
4658
|
const parts = [];
|
|
4281
4659
|
const inputFilesList = collectInputFiles(inputFiles);
|
|
@@ -4292,7 +4670,7 @@ function normalizeInputFiles(inputFiles) {
|
|
|
4292
4670
|
}
|
|
4293
4671
|
const deduped = /* @__PURE__ */ new Map();
|
|
4294
4672
|
for (const inputFile of inputFiles) {
|
|
4295
|
-
const absolutePath =
|
|
4673
|
+
const absolutePath = path10.resolve(inputFile);
|
|
4296
4674
|
if (!deduped.has(absolutePath)) {
|
|
4297
4675
|
deduped.set(absolutePath, absolutePath);
|
|
4298
4676
|
}
|
|
@@ -4305,7 +4683,7 @@ function collectInputFiles(inputFiles) {
|
|
|
4305
4683
|
}
|
|
4306
4684
|
const unique = /* @__PURE__ */ new Map();
|
|
4307
4685
|
for (const inputFile of inputFiles) {
|
|
4308
|
-
const absolutePath =
|
|
4686
|
+
const absolutePath = path10.resolve(inputFile);
|
|
4309
4687
|
if (!unique.has(absolutePath)) {
|
|
4310
4688
|
unique.set(absolutePath, absolutePath);
|
|
4311
4689
|
}
|
|
@@ -4317,7 +4695,7 @@ function buildMandatoryPrereadBlock(inputFiles) {
|
|
|
4317
4695
|
return "";
|
|
4318
4696
|
}
|
|
4319
4697
|
const buildList = (files) => files.map((absolutePath) => {
|
|
4320
|
-
const fileName =
|
|
4698
|
+
const fileName = path10.basename(absolutePath);
|
|
4321
4699
|
const fileUri = pathToFileUri(absolutePath);
|
|
4322
4700
|
return `* [${fileName}](${fileUri})`;
|
|
4323
4701
|
});
|
|
@@ -4333,7 +4711,7 @@ ${buildList(inputFiles).join("\n")}.`);
|
|
|
4333
4711
|
return sections.join("\n");
|
|
4334
4712
|
}
|
|
4335
4713
|
function pathToFileUri(filePath) {
|
|
4336
|
-
const absolutePath =
|
|
4714
|
+
const absolutePath = path10.isAbsolute(filePath) ? filePath : path10.resolve(filePath);
|
|
4337
4715
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
4338
4716
|
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
4339
4717
|
return `file:///${normalizedPath}`;
|
|
@@ -4481,10 +4859,10 @@ var ClaudeCliProvider = class {
|
|
|
4481
4859
|
}
|
|
4482
4860
|
resolveCwd(cwdOverride) {
|
|
4483
4861
|
if (cwdOverride) {
|
|
4484
|
-
return
|
|
4862
|
+
return path11.resolve(cwdOverride);
|
|
4485
4863
|
}
|
|
4486
4864
|
if (this.config.cwd) {
|
|
4487
|
-
return
|
|
4865
|
+
return path11.resolve(this.config.cwd);
|
|
4488
4866
|
}
|
|
4489
4867
|
return void 0;
|
|
4490
4868
|
}
|
|
@@ -4494,9 +4872,9 @@ var ClaudeCliProvider = class {
|
|
|
4494
4872
|
return void 0;
|
|
4495
4873
|
}
|
|
4496
4874
|
if (this.config.logDir) {
|
|
4497
|
-
return
|
|
4875
|
+
return path11.resolve(this.config.logDir);
|
|
4498
4876
|
}
|
|
4499
|
-
return
|
|
4877
|
+
return path11.join(process.cwd(), ".agentv", "logs", "claude-cli");
|
|
4500
4878
|
}
|
|
4501
4879
|
async createStreamLogger(request) {
|
|
4502
4880
|
const logDir = this.resolveLogDirectory();
|
|
@@ -4510,7 +4888,7 @@ var ClaudeCliProvider = class {
|
|
|
4510
4888
|
console.warn(`Skipping Claude CLI stream logging (could not create ${logDir}): ${message}`);
|
|
4511
4889
|
return void 0;
|
|
4512
4890
|
}
|
|
4513
|
-
const filePath =
|
|
4891
|
+
const filePath = path11.join(logDir, buildLogFilename(request, this.targetName));
|
|
4514
4892
|
try {
|
|
4515
4893
|
const logger = await ClaudeCliStreamLogger.create({
|
|
4516
4894
|
filePath,
|
|
@@ -4812,7 +5190,7 @@ function tryParseJson(line) {
|
|
|
4812
5190
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
4813
5191
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
4814
5192
|
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
4815
|
-
import
|
|
5193
|
+
import path12 from "node:path";
|
|
4816
5194
|
var claudeSdkModule = null;
|
|
4817
5195
|
async function loadClaudeSdk() {
|
|
4818
5196
|
if (!claudeSdkModule) {
|
|
@@ -4973,10 +5351,10 @@ var ClaudeSdkProvider = class {
|
|
|
4973
5351
|
}
|
|
4974
5352
|
resolveCwd(cwdOverride) {
|
|
4975
5353
|
if (cwdOverride) {
|
|
4976
|
-
return
|
|
5354
|
+
return path12.resolve(cwdOverride);
|
|
4977
5355
|
}
|
|
4978
5356
|
if (this.config.cwd) {
|
|
4979
|
-
return
|
|
5357
|
+
return path12.resolve(this.config.cwd);
|
|
4980
5358
|
}
|
|
4981
5359
|
return void 0;
|
|
4982
5360
|
}
|
|
@@ -4986,9 +5364,9 @@ var ClaudeSdkProvider = class {
|
|
|
4986
5364
|
return void 0;
|
|
4987
5365
|
}
|
|
4988
5366
|
if (this.config.logDir) {
|
|
4989
|
-
return
|
|
5367
|
+
return path12.resolve(this.config.logDir);
|
|
4990
5368
|
}
|
|
4991
|
-
return
|
|
5369
|
+
return path12.join(process.cwd(), ".agentv", "logs", "claude");
|
|
4992
5370
|
}
|
|
4993
5371
|
async createStreamLogger(request) {
|
|
4994
5372
|
const logDir = this.resolveLogDirectory();
|
|
@@ -5002,7 +5380,7 @@ var ClaudeSdkProvider = class {
|
|
|
5002
5380
|
console.warn(`Skipping Claude stream logging (could not create ${logDir}): ${message}`);
|
|
5003
5381
|
return void 0;
|
|
5004
5382
|
}
|
|
5005
|
-
const filePath =
|
|
5383
|
+
const filePath = path12.join(logDir, buildLogFilename2(request, this.targetName));
|
|
5006
5384
|
try {
|
|
5007
5385
|
const logger = await ClaudeStreamLogger.create({
|
|
5008
5386
|
filePath,
|
|
@@ -5190,7 +5568,7 @@ function formatElapsed2(startedAt) {
|
|
|
5190
5568
|
import { exec as execWithCallback } from "node:child_process";
|
|
5191
5569
|
import fs from "node:fs/promises";
|
|
5192
5570
|
import os from "node:os";
|
|
5193
|
-
import
|
|
5571
|
+
import path13 from "node:path";
|
|
5194
5572
|
import { promisify } from "node:util";
|
|
5195
5573
|
import { z as z2 } from "zod";
|
|
5196
5574
|
var ToolCallSchema = z2.object({
|
|
@@ -5693,7 +6071,7 @@ function normalizeInputFiles2(inputFiles) {
|
|
|
5693
6071
|
}
|
|
5694
6072
|
const unique = /* @__PURE__ */ new Map();
|
|
5695
6073
|
for (const inputFile of inputFiles) {
|
|
5696
|
-
const absolutePath =
|
|
6074
|
+
const absolutePath = path13.resolve(inputFile);
|
|
5697
6075
|
if (!unique.has(absolutePath)) {
|
|
5698
6076
|
unique.set(absolutePath, absolutePath);
|
|
5699
6077
|
}
|
|
@@ -5707,7 +6085,7 @@ function formatFileList(files, template) {
|
|
|
5707
6085
|
const formatter = template ?? "{path}";
|
|
5708
6086
|
return files.map((filePath) => {
|
|
5709
6087
|
const escapedPath = shellEscape(filePath);
|
|
5710
|
-
const escapedName = shellEscape(
|
|
6088
|
+
const escapedName = shellEscape(path13.basename(filePath));
|
|
5711
6089
|
return formatter.replaceAll("{path}", escapedPath).replaceAll("{basename}", escapedName);
|
|
5712
6090
|
}).join(" ");
|
|
5713
6091
|
}
|
|
@@ -5731,7 +6109,7 @@ function generateOutputFilePath(evalCaseId, extension = ".json") {
|
|
|
5731
6109
|
const safeEvalId = evalCaseId || "unknown";
|
|
5732
6110
|
const timestamp = Date.now();
|
|
5733
6111
|
const random = Math.random().toString(36).substring(2, 9);
|
|
5734
|
-
return
|
|
6112
|
+
return path13.join(os.tmpdir(), `agentv-${safeEvalId}-${timestamp}-${random}${extension}`);
|
|
5735
6113
|
}
|
|
5736
6114
|
function formatTimeoutSuffix2(timeoutMs) {
|
|
5737
6115
|
if (!timeoutMs || timeoutMs <= 0) {
|
|
@@ -5745,7 +6123,7 @@ function formatTimeoutSuffix2(timeoutMs) {
|
|
|
5745
6123
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
5746
6124
|
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
5747
6125
|
import { mkdir as mkdir3 } from "node:fs/promises";
|
|
5748
|
-
import
|
|
6126
|
+
import path14 from "node:path";
|
|
5749
6127
|
|
|
5750
6128
|
// src/evaluation/providers/codex-log-tracker.ts
|
|
5751
6129
|
var GLOBAL_LOGS_KEY2 = Symbol.for("agentv.codexLogs");
|
|
@@ -5980,10 +6358,10 @@ ${basePrompt}` : basePrompt;
|
|
|
5980
6358
|
}
|
|
5981
6359
|
resolveCwd(cwdOverride) {
|
|
5982
6360
|
if (cwdOverride) {
|
|
5983
|
-
return
|
|
6361
|
+
return path14.resolve(cwdOverride);
|
|
5984
6362
|
}
|
|
5985
6363
|
if (this.config.cwd) {
|
|
5986
|
-
return
|
|
6364
|
+
return path14.resolve(this.config.cwd);
|
|
5987
6365
|
}
|
|
5988
6366
|
return void 0;
|
|
5989
6367
|
}
|
|
@@ -5993,9 +6371,9 @@ ${basePrompt}` : basePrompt;
|
|
|
5993
6371
|
return void 0;
|
|
5994
6372
|
}
|
|
5995
6373
|
if (this.config.logDir) {
|
|
5996
|
-
return
|
|
6374
|
+
return path14.resolve(this.config.logDir);
|
|
5997
6375
|
}
|
|
5998
|
-
return
|
|
6376
|
+
return path14.join(process.cwd(), ".agentv", "logs", "codex");
|
|
5999
6377
|
}
|
|
6000
6378
|
async createStreamLogger(request) {
|
|
6001
6379
|
const logDir = this.resolveLogDirectory();
|
|
@@ -6009,7 +6387,7 @@ ${basePrompt}` : basePrompt;
|
|
|
6009
6387
|
console.warn(`Skipping Codex SDK stream logging (could not create ${logDir}): ${message}`);
|
|
6010
6388
|
return void 0;
|
|
6011
6389
|
}
|
|
6012
|
-
const filePath =
|
|
6390
|
+
const filePath = path14.join(logDir, buildLogFilename3(request, this.targetName));
|
|
6013
6391
|
try {
|
|
6014
6392
|
const logger = await CodexSdkStreamLogger.create({
|
|
6015
6393
|
filePath,
|
|
@@ -6153,7 +6531,7 @@ function formatElapsed3(startedAt) {
|
|
|
6153
6531
|
// src/evaluation/providers/copilot-cli.ts
|
|
6154
6532
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
6155
6533
|
import { mkdir as mkdir4 } from "node:fs/promises";
|
|
6156
|
-
import
|
|
6534
|
+
import path16 from "node:path";
|
|
6157
6535
|
import { Readable, Writable } from "node:stream";
|
|
6158
6536
|
import { spawn as spawn2 } from "node:child_process";
|
|
6159
6537
|
import * as acp from "@agentclientprotocol/sdk";
|
|
@@ -6215,8 +6593,8 @@ function subscribeToCopilotCliLogEntries(listener) {
|
|
|
6215
6593
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
6216
6594
|
import { createWriteStream as createWriteStream4, existsSync, readdirSync } from "node:fs";
|
|
6217
6595
|
import { arch, platform } from "node:os";
|
|
6218
|
-
import
|
|
6219
|
-
import { fileURLToPath as
|
|
6596
|
+
import path15 from "node:path";
|
|
6597
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6220
6598
|
function resolvePlatformCliPath() {
|
|
6221
6599
|
const os3 = platform();
|
|
6222
6600
|
const cpu = arch();
|
|
@@ -6238,8 +6616,8 @@ function resolvePlatformCliPath() {
|
|
|
6238
6616
|
const binaryName = os3 === "win32" ? "copilot.exe" : "copilot";
|
|
6239
6617
|
try {
|
|
6240
6618
|
const resolved = import.meta.resolve(`${packageName}/package.json`);
|
|
6241
|
-
const packageJsonPath = resolved.startsWith("file:") ?
|
|
6242
|
-
const binaryPath =
|
|
6619
|
+
const packageJsonPath = resolved.startsWith("file:") ? fileURLToPath3(resolved) : resolved;
|
|
6620
|
+
const binaryPath = path15.join(path15.dirname(packageJsonPath), binaryName);
|
|
6243
6621
|
if (existsSync(binaryPath)) {
|
|
6244
6622
|
return binaryPath;
|
|
6245
6623
|
}
|
|
@@ -6247,7 +6625,7 @@ function resolvePlatformCliPath() {
|
|
|
6247
6625
|
}
|
|
6248
6626
|
let searchDir = process.cwd();
|
|
6249
6627
|
for (let i = 0; i < 10; i++) {
|
|
6250
|
-
const standardPath =
|
|
6628
|
+
const standardPath = path15.join(
|
|
6251
6629
|
searchDir,
|
|
6252
6630
|
"node_modules",
|
|
6253
6631
|
...packageName.split("/"),
|
|
@@ -6256,13 +6634,13 @@ function resolvePlatformCliPath() {
|
|
|
6256
6634
|
if (existsSync(standardPath)) {
|
|
6257
6635
|
return standardPath;
|
|
6258
6636
|
}
|
|
6259
|
-
const bunDir =
|
|
6637
|
+
const bunDir = path15.join(searchDir, "node_modules", ".bun");
|
|
6260
6638
|
const prefix = `@github+copilot-${osPart}-${archPart}@`;
|
|
6261
6639
|
try {
|
|
6262
6640
|
const entries = readdirSync(bunDir);
|
|
6263
6641
|
for (const entry of entries) {
|
|
6264
6642
|
if (entry.startsWith(prefix)) {
|
|
6265
|
-
const candidate =
|
|
6643
|
+
const candidate = path15.join(
|
|
6266
6644
|
bunDir,
|
|
6267
6645
|
entry,
|
|
6268
6646
|
"node_modules",
|
|
@@ -6277,7 +6655,7 @@ function resolvePlatformCliPath() {
|
|
|
6277
6655
|
}
|
|
6278
6656
|
} catch {
|
|
6279
6657
|
}
|
|
6280
|
-
const parent =
|
|
6658
|
+
const parent = path15.dirname(searchDir);
|
|
6281
6659
|
if (parent === searchDir) break;
|
|
6282
6660
|
searchDir = parent;
|
|
6283
6661
|
}
|
|
@@ -6621,10 +6999,10 @@ var CopilotCliProvider = class {
|
|
|
6621
6999
|
}
|
|
6622
7000
|
resolveCwd(cwdOverride) {
|
|
6623
7001
|
if (cwdOverride) {
|
|
6624
|
-
return
|
|
7002
|
+
return path16.resolve(cwdOverride);
|
|
6625
7003
|
}
|
|
6626
7004
|
if (this.config.cwd) {
|
|
6627
|
-
return
|
|
7005
|
+
return path16.resolve(this.config.cwd);
|
|
6628
7006
|
}
|
|
6629
7007
|
return void 0;
|
|
6630
7008
|
}
|
|
@@ -6643,9 +7021,9 @@ var CopilotCliProvider = class {
|
|
|
6643
7021
|
return void 0;
|
|
6644
7022
|
}
|
|
6645
7023
|
if (this.config.logDir) {
|
|
6646
|
-
return
|
|
7024
|
+
return path16.resolve(this.config.logDir);
|
|
6647
7025
|
}
|
|
6648
|
-
return
|
|
7026
|
+
return path16.join(process.cwd(), ".agentv", "logs", "copilot-cli");
|
|
6649
7027
|
}
|
|
6650
7028
|
async createStreamLogger(request) {
|
|
6651
7029
|
const logDir = this.resolveLogDirectory();
|
|
@@ -6659,7 +7037,7 @@ var CopilotCliProvider = class {
|
|
|
6659
7037
|
console.warn(`Skipping Copilot CLI stream logging (could not create ${logDir}): ${message}`);
|
|
6660
7038
|
return void 0;
|
|
6661
7039
|
}
|
|
6662
|
-
const filePath =
|
|
7040
|
+
const filePath = path16.join(logDir, buildLogFilename4(request, this.targetName, "copilot-cli"));
|
|
6663
7041
|
try {
|
|
6664
7042
|
const logger = await CopilotStreamLogger.create(
|
|
6665
7043
|
{
|
|
@@ -6752,9 +7130,9 @@ function summarizeAcpEvent(eventType, data) {
|
|
|
6752
7130
|
}
|
|
6753
7131
|
|
|
6754
7132
|
// src/evaluation/providers/copilot-log.ts
|
|
6755
|
-
import { readFile as
|
|
7133
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
6756
7134
|
import { homedir as homedir2 } from "node:os";
|
|
6757
|
-
import
|
|
7135
|
+
import path18 from "node:path";
|
|
6758
7136
|
|
|
6759
7137
|
// src/evaluation/providers/copilot-log-parser.ts
|
|
6760
7138
|
function parseCopilotEvents(eventsJsonl) {
|
|
@@ -6886,11 +7264,11 @@ function parseCopilotEvents(eventsJsonl) {
|
|
|
6886
7264
|
}
|
|
6887
7265
|
|
|
6888
7266
|
// src/evaluation/providers/copilot-session-discovery.ts
|
|
6889
|
-
import { readFile as
|
|
7267
|
+
import { readFile as readFile8, readdir, stat } from "node:fs/promises";
|
|
6890
7268
|
import { homedir } from "node:os";
|
|
6891
|
-
import
|
|
7269
|
+
import path17 from "node:path";
|
|
6892
7270
|
import { parse as parseYaml2 } from "yaml";
|
|
6893
|
-
var DEFAULT_SESSION_STATE_DIR = () =>
|
|
7271
|
+
var DEFAULT_SESSION_STATE_DIR = () => path17.join(homedir(), ".copilot", "session-state");
|
|
6894
7272
|
async function discoverCopilotSessions(opts) {
|
|
6895
7273
|
const sessionStateDir = opts?.sessionStateDir ?? DEFAULT_SESSION_STATE_DIR();
|
|
6896
7274
|
const limit = opts?.limit ?? 10;
|
|
@@ -6902,11 +7280,11 @@ async function discoverCopilotSessions(opts) {
|
|
|
6902
7280
|
}
|
|
6903
7281
|
const sessions = [];
|
|
6904
7282
|
for (const entry of entries) {
|
|
6905
|
-
const sessionDir =
|
|
6906
|
-
const workspacePath =
|
|
6907
|
-
const eventsPath =
|
|
7283
|
+
const sessionDir = path17.join(sessionStateDir, entry);
|
|
7284
|
+
const workspacePath = path17.join(sessionDir, "workspace.yaml");
|
|
7285
|
+
const eventsPath = path17.join(sessionDir, "events.jsonl");
|
|
6908
7286
|
try {
|
|
6909
|
-
const workspaceContent = await
|
|
7287
|
+
const workspaceContent = await readFile8(workspacePath, "utf8");
|
|
6910
7288
|
const workspace = parseYaml2(workspaceContent) ?? {};
|
|
6911
7289
|
const cwd = String(workspace.cwd ?? "");
|
|
6912
7290
|
let updatedAt;
|
|
@@ -6965,10 +7343,10 @@ var CopilotLogProvider = class {
|
|
|
6965
7343
|
}
|
|
6966
7344
|
async invoke(_request) {
|
|
6967
7345
|
const sessionDir = await this.resolveSessionDir();
|
|
6968
|
-
const eventsPath =
|
|
7346
|
+
const eventsPath = path18.join(sessionDir, "events.jsonl");
|
|
6969
7347
|
let eventsContent;
|
|
6970
7348
|
try {
|
|
6971
|
-
eventsContent = await
|
|
7349
|
+
eventsContent = await readFile9(eventsPath, "utf8");
|
|
6972
7350
|
} catch (err) {
|
|
6973
7351
|
throw new Error(
|
|
6974
7352
|
`Failed to read Copilot session transcript at ${eventsPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -6987,8 +7365,8 @@ var CopilotLogProvider = class {
|
|
|
6987
7365
|
return this.config.sessionDir;
|
|
6988
7366
|
}
|
|
6989
7367
|
if (this.config.sessionId) {
|
|
6990
|
-
const stateDir = this.config.sessionStateDir ??
|
|
6991
|
-
return
|
|
7368
|
+
const stateDir = this.config.sessionStateDir ?? path18.join(homedir2(), ".copilot", "session-state");
|
|
7369
|
+
return path18.join(stateDir, this.config.sessionId);
|
|
6992
7370
|
}
|
|
6993
7371
|
if (this.config.discover === "latest") {
|
|
6994
7372
|
const sessions = await discoverCopilotSessions({
|
|
@@ -7013,7 +7391,7 @@ var CopilotLogProvider = class {
|
|
|
7013
7391
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
7014
7392
|
import { existsSync as existsSync2 } from "node:fs";
|
|
7015
7393
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
7016
|
-
import
|
|
7394
|
+
import path19 from "node:path";
|
|
7017
7395
|
|
|
7018
7396
|
// src/evaluation/providers/copilot-sdk-log-tracker.ts
|
|
7019
7397
|
var GLOBAL_LOGS_KEY4 = Symbol.for("agentv.copilotSdkLogs");
|
|
@@ -7323,10 +7701,10 @@ var CopilotSdkProvider = class {
|
|
|
7323
7701
|
}
|
|
7324
7702
|
resolveCwd(cwdOverride) {
|
|
7325
7703
|
if (cwdOverride) {
|
|
7326
|
-
return
|
|
7704
|
+
return path19.resolve(cwdOverride);
|
|
7327
7705
|
}
|
|
7328
7706
|
if (this.config.cwd) {
|
|
7329
|
-
return
|
|
7707
|
+
return path19.resolve(this.config.cwd);
|
|
7330
7708
|
}
|
|
7331
7709
|
return void 0;
|
|
7332
7710
|
}
|
|
@@ -7335,9 +7713,9 @@ var CopilotSdkProvider = class {
|
|
|
7335
7713
|
return void 0;
|
|
7336
7714
|
}
|
|
7337
7715
|
if (this.config.logDir) {
|
|
7338
|
-
return
|
|
7716
|
+
return path19.resolve(this.config.logDir);
|
|
7339
7717
|
}
|
|
7340
|
-
return
|
|
7718
|
+
return path19.join(process.cwd(), ".agentv", "logs", "copilot-sdk");
|
|
7341
7719
|
}
|
|
7342
7720
|
async createStreamLogger(request) {
|
|
7343
7721
|
const logDir = this.resolveLogDirectory();
|
|
@@ -7351,7 +7729,7 @@ var CopilotSdkProvider = class {
|
|
|
7351
7729
|
console.warn(`Skipping Copilot SDK stream logging (could not create ${logDir}): ${message}`);
|
|
7352
7730
|
return void 0;
|
|
7353
7731
|
}
|
|
7354
|
-
const filePath =
|
|
7732
|
+
const filePath = path19.join(logDir, buildLogFilename4(request, this.targetName, "copilot-sdk"));
|
|
7355
7733
|
try {
|
|
7356
7734
|
const logger = await CopilotStreamLogger.create(
|
|
7357
7735
|
{
|
|
@@ -7380,9 +7758,9 @@ var CopilotSdkProvider = class {
|
|
|
7380
7758
|
};
|
|
7381
7759
|
function resolveSkillDirectories(cwd) {
|
|
7382
7760
|
const candidates = [
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7761
|
+
path19.join(cwd, ".claude", "skills"),
|
|
7762
|
+
path19.join(cwd, ".agents", "skills"),
|
|
7763
|
+
path19.join(cwd, ".codex", "skills")
|
|
7386
7764
|
];
|
|
7387
7765
|
return candidates.filter((dir) => existsSync2(dir));
|
|
7388
7766
|
}
|
|
@@ -7466,7 +7844,7 @@ import { randomUUID as randomUUID7 } from "node:crypto";
|
|
|
7466
7844
|
import { accessSync, createWriteStream as createWriteStream5, readFileSync as readFileSync2 } from "node:fs";
|
|
7467
7845
|
import { mkdir as mkdir6, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
7468
7846
|
import { tmpdir } from "node:os";
|
|
7469
|
-
import
|
|
7847
|
+
import path20 from "node:path";
|
|
7470
7848
|
|
|
7471
7849
|
// src/evaluation/providers/pi-log-tracker.ts
|
|
7472
7850
|
var GLOBAL_LOGS_KEY5 = Symbol.for("agentv.piLogs");
|
|
@@ -7672,7 +8050,7 @@ var PiCliProvider = class {
|
|
|
7672
8050
|
const cwd = this.resolveCwd(workspaceRoot, request.cwd);
|
|
7673
8051
|
const logger = await this.createStreamLogger(request).catch(() => void 0);
|
|
7674
8052
|
try {
|
|
7675
|
-
const promptFile =
|
|
8053
|
+
const promptFile = path20.join(cwd, PROMPT_FILENAME);
|
|
7676
8054
|
await writeFile(promptFile, request.question, "utf8");
|
|
7677
8055
|
const args = this.buildPiArgs(request.question, inputFiles);
|
|
7678
8056
|
const result = await this.executePi(args, cwd, request.signal, logger);
|
|
@@ -7735,10 +8113,10 @@ var PiCliProvider = class {
|
|
|
7735
8113
|
}
|
|
7736
8114
|
resolveCwd(workspaceRoot, cwdOverride) {
|
|
7737
8115
|
if (cwdOverride) {
|
|
7738
|
-
return
|
|
8116
|
+
return path20.resolve(cwdOverride);
|
|
7739
8117
|
}
|
|
7740
8118
|
if (this.config.cwd) {
|
|
7741
|
-
return
|
|
8119
|
+
return path20.resolve(this.config.cwd);
|
|
7742
8120
|
}
|
|
7743
8121
|
if (workspaceRoot) {
|
|
7744
8122
|
return workspaceRoot;
|
|
@@ -7844,7 +8222,7 @@ ${prompt}` : prompt;
|
|
|
7844
8222
|
return env;
|
|
7845
8223
|
}
|
|
7846
8224
|
async createWorkspace() {
|
|
7847
|
-
return await mkdtemp(
|
|
8225
|
+
return await mkdtemp(path20.join(tmpdir(), WORKSPACE_PREFIX));
|
|
7848
8226
|
}
|
|
7849
8227
|
async cleanupWorkspace(workspaceRoot) {
|
|
7850
8228
|
try {
|
|
@@ -7854,9 +8232,9 @@ ${prompt}` : prompt;
|
|
|
7854
8232
|
}
|
|
7855
8233
|
resolveLogDirectory() {
|
|
7856
8234
|
if (this.config.logDir) {
|
|
7857
|
-
return
|
|
8235
|
+
return path20.resolve(this.config.logDir);
|
|
7858
8236
|
}
|
|
7859
|
-
return
|
|
8237
|
+
return path20.join(process.cwd(), ".agentv", "logs", "pi-cli");
|
|
7860
8238
|
}
|
|
7861
8239
|
async createStreamLogger(request) {
|
|
7862
8240
|
const logDir = this.resolveLogDirectory();
|
|
@@ -7870,7 +8248,7 @@ ${prompt}` : prompt;
|
|
|
7870
8248
|
console.warn(`Skipping Pi stream logging (could not create ${logDir}): ${message}`);
|
|
7871
8249
|
return void 0;
|
|
7872
8250
|
}
|
|
7873
|
-
const filePath =
|
|
8251
|
+
const filePath = path20.join(logDir, buildLogFilename5(request, this.targetName));
|
|
7874
8252
|
try {
|
|
7875
8253
|
const logger = await PiStreamLogger.create({
|
|
7876
8254
|
filePath,
|
|
@@ -8341,8 +8719,8 @@ function resolveWindowsCmd(executable) {
|
|
|
8341
8719
|
const content = readFileSync2(cmdPath, "utf-8");
|
|
8342
8720
|
const match = content.match(/"?%_prog%"?\s+"([^"]+\.js)"/);
|
|
8343
8721
|
if (match) {
|
|
8344
|
-
const dp0 =
|
|
8345
|
-
const scriptPath = match[1].replace(/%dp0%[/\\]?/gi, `${dp0}${
|
|
8722
|
+
const dp0 = path20.dirname(path20.resolve(cmdPath));
|
|
8723
|
+
const scriptPath = match[1].replace(/%dp0%[/\\]?/gi, `${dp0}${path20.sep}`);
|
|
8346
8724
|
try {
|
|
8347
8725
|
accessSync(scriptPath);
|
|
8348
8726
|
return ["node", [scriptPath]];
|
|
@@ -8421,13 +8799,13 @@ import { execSync as execSync2 } from "node:child_process";
|
|
|
8421
8799
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
8422
8800
|
import { accessSync as accessSync2, createWriteStream as createWriteStream6, mkdirSync } from "node:fs";
|
|
8423
8801
|
import { mkdir as mkdir7 } from "node:fs/promises";
|
|
8424
|
-
import
|
|
8802
|
+
import path22 from "node:path";
|
|
8425
8803
|
import { createInterface } from "node:readline";
|
|
8426
|
-
import { fileURLToPath as
|
|
8804
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL } from "node:url";
|
|
8427
8805
|
|
|
8428
8806
|
// src/paths.ts
|
|
8429
8807
|
import os2 from "node:os";
|
|
8430
|
-
import
|
|
8808
|
+
import path21 from "node:path";
|
|
8431
8809
|
var logged = false;
|
|
8432
8810
|
function getAgentvHome() {
|
|
8433
8811
|
const envHome = process.env.AGENTV_HOME;
|
|
@@ -8438,19 +8816,19 @@ function getAgentvHome() {
|
|
|
8438
8816
|
}
|
|
8439
8817
|
return envHome;
|
|
8440
8818
|
}
|
|
8441
|
-
return
|
|
8819
|
+
return path21.join(os2.homedir(), ".agentv");
|
|
8442
8820
|
}
|
|
8443
8821
|
function getWorkspacesRoot() {
|
|
8444
|
-
return
|
|
8822
|
+
return path21.join(getAgentvHome(), "workspaces");
|
|
8445
8823
|
}
|
|
8446
8824
|
function getSubagentsRoot() {
|
|
8447
|
-
return
|
|
8825
|
+
return path21.join(getAgentvHome(), "subagents");
|
|
8448
8826
|
}
|
|
8449
8827
|
function getTraceStateRoot() {
|
|
8450
|
-
return
|
|
8828
|
+
return path21.join(getAgentvHome(), "trace-state");
|
|
8451
8829
|
}
|
|
8452
8830
|
function getWorkspacePoolRoot() {
|
|
8453
|
-
return
|
|
8831
|
+
return path21.join(getAgentvHome(), "workspace-pool");
|
|
8454
8832
|
}
|
|
8455
8833
|
|
|
8456
8834
|
// src/evaluation/providers/pi-coding-agent.ts
|
|
@@ -8472,7 +8850,7 @@ async function promptInstall() {
|
|
|
8472
8850
|
}
|
|
8473
8851
|
}
|
|
8474
8852
|
function findManagedSdkInstallRoot() {
|
|
8475
|
-
return
|
|
8853
|
+
return path22.join(getAgentvHome(), "deps", "pi-sdk");
|
|
8476
8854
|
}
|
|
8477
8855
|
function resolveGlobalNpmRoot() {
|
|
8478
8856
|
try {
|
|
@@ -8486,7 +8864,7 @@ function resolveGlobalNpmRoot() {
|
|
|
8486
8864
|
}
|
|
8487
8865
|
}
|
|
8488
8866
|
function buildGlobalModuleEntry(moduleName, globalNpmRoot) {
|
|
8489
|
-
return
|
|
8867
|
+
return path22.join(globalNpmRoot, ...moduleName.split("/"), "dist", "index.js");
|
|
8490
8868
|
}
|
|
8491
8869
|
function findAccessiblePath(paths) {
|
|
8492
8870
|
for (const candidate of paths) {
|
|
@@ -8512,11 +8890,11 @@ async function tryImportLocalSdkModules() {
|
|
|
8512
8890
|
async function tryImportManagedSdkModules() {
|
|
8513
8891
|
const managedRoot = findManagedSdkInstallRoot();
|
|
8514
8892
|
const piCodingAgentEntry = findAccessiblePath([
|
|
8515
|
-
|
|
8893
|
+
path22.join(managedRoot, "node_modules", "@mariozechner", "pi-coding-agent", "dist", "index.js")
|
|
8516
8894
|
]);
|
|
8517
8895
|
const piAiEntry = findAccessiblePath([
|
|
8518
|
-
|
|
8519
|
-
|
|
8896
|
+
path22.join(managedRoot, "node_modules", "@mariozechner", "pi-ai", "dist", "index.js"),
|
|
8897
|
+
path22.join(
|
|
8520
8898
|
managedRoot,
|
|
8521
8899
|
"node_modules",
|
|
8522
8900
|
"@mariozechner",
|
|
@@ -8547,7 +8925,7 @@ async function tryImportGlobalSdkModules() {
|
|
|
8547
8925
|
]);
|
|
8548
8926
|
const piAiEntry = findAccessiblePath([
|
|
8549
8927
|
buildGlobalModuleEntry("@mariozechner/pi-ai", globalNpmRoot),
|
|
8550
|
-
|
|
8928
|
+
path22.join(
|
|
8551
8929
|
globalNpmRoot,
|
|
8552
8930
|
"@mariozechner",
|
|
8553
8931
|
"pi-coding-agent",
|
|
@@ -8848,10 +9226,10 @@ ${fileList}`;
|
|
|
8848
9226
|
}
|
|
8849
9227
|
resolveCwd(cwdOverride) {
|
|
8850
9228
|
if (cwdOverride) {
|
|
8851
|
-
return
|
|
9229
|
+
return path22.resolve(cwdOverride);
|
|
8852
9230
|
}
|
|
8853
9231
|
if (this.config.cwd) {
|
|
8854
|
-
return
|
|
9232
|
+
return path22.resolve(this.config.cwd);
|
|
8855
9233
|
}
|
|
8856
9234
|
return process.cwd();
|
|
8857
9235
|
}
|
|
@@ -8870,9 +9248,9 @@ ${fileList}`;
|
|
|
8870
9248
|
}
|
|
8871
9249
|
resolveLogDirectory() {
|
|
8872
9250
|
if (this.config.logDir) {
|
|
8873
|
-
return
|
|
9251
|
+
return path22.resolve(this.config.logDir);
|
|
8874
9252
|
}
|
|
8875
|
-
return
|
|
9253
|
+
return path22.join(process.cwd(), ".agentv", "logs", "pi-coding-agent");
|
|
8876
9254
|
}
|
|
8877
9255
|
async createStreamLogger(request) {
|
|
8878
9256
|
const logDir = this.resolveLogDirectory();
|
|
@@ -8886,7 +9264,7 @@ ${fileList}`;
|
|
|
8886
9264
|
console.warn(`Skipping Pi stream logging (could not create ${logDir}): ${message}`);
|
|
8887
9265
|
return void 0;
|
|
8888
9266
|
}
|
|
8889
|
-
const filePath =
|
|
9267
|
+
const filePath = path22.join(logDir, buildLogFilename6(request, this.targetName));
|
|
8890
9268
|
try {
|
|
8891
9269
|
const logger = await PiStreamLogger2.create({
|
|
8892
9270
|
filePath,
|
|
@@ -9101,17 +9479,17 @@ var ProviderRegistry = class {
|
|
|
9101
9479
|
// src/evaluation/providers/vscode-provider.ts
|
|
9102
9480
|
import { exec as exec2 } from "node:child_process";
|
|
9103
9481
|
import { constants as constants3, access as access3, stat as stat5 } from "node:fs/promises";
|
|
9104
|
-
import
|
|
9482
|
+
import path33 from "node:path";
|
|
9105
9483
|
import { promisify as promisify3 } from "node:util";
|
|
9106
9484
|
|
|
9107
9485
|
// src/evaluation/providers/vscode/dispatch/agentDispatch.ts
|
|
9108
9486
|
import { stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
|
|
9109
|
-
import
|
|
9487
|
+
import path31 from "node:path";
|
|
9110
9488
|
|
|
9111
9489
|
// src/evaluation/providers/vscode/utils/fs.ts
|
|
9112
9490
|
import { constants as constants2 } from "node:fs";
|
|
9113
9491
|
import { access as access2, mkdir as mkdir8, readdir as readdir2, rm as rm2, stat as stat2 } from "node:fs/promises";
|
|
9114
|
-
import
|
|
9492
|
+
import path23 from "node:path";
|
|
9115
9493
|
async function pathExists(target) {
|
|
9116
9494
|
try {
|
|
9117
9495
|
await access2(target, constants2.F_OK);
|
|
@@ -9127,7 +9505,7 @@ async function readDirEntries(target) {
|
|
|
9127
9505
|
const entries = await readdir2(target, { withFileTypes: true });
|
|
9128
9506
|
return entries.map((entry) => ({
|
|
9129
9507
|
name: entry.name,
|
|
9130
|
-
absolutePath:
|
|
9508
|
+
absolutePath: path23.join(target, entry.name),
|
|
9131
9509
|
isDirectory: entry.isDirectory()
|
|
9132
9510
|
}));
|
|
9133
9511
|
}
|
|
@@ -9142,9 +9520,9 @@ async function removeIfExists(target) {
|
|
|
9142
9520
|
}
|
|
9143
9521
|
|
|
9144
9522
|
// src/evaluation/providers/vscode/utils/path.ts
|
|
9145
|
-
import
|
|
9523
|
+
import path24 from "node:path";
|
|
9146
9524
|
function pathToFileUri2(filePath) {
|
|
9147
|
-
const absolutePath =
|
|
9525
|
+
const absolutePath = path24.isAbsolute(filePath) ? filePath : path24.resolve(filePath);
|
|
9148
9526
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
9149
9527
|
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
9150
9528
|
return `file:///${normalizedPath}`;
|
|
@@ -9153,7 +9531,7 @@ function pathToFileUri2(filePath) {
|
|
|
9153
9531
|
}
|
|
9154
9532
|
|
|
9155
9533
|
// src/evaluation/providers/vscode/dispatch/promptBuilder.ts
|
|
9156
|
-
import
|
|
9534
|
+
import path25 from "node:path";
|
|
9157
9535
|
|
|
9158
9536
|
// src/evaluation/providers/vscode/utils/template.ts
|
|
9159
9537
|
function renderTemplate2(content, variables) {
|
|
@@ -9245,8 +9623,8 @@ function createBatchRequestPrompt(userQuery, responseFileTmp, responseFileFinal,
|
|
|
9245
9623
|
});
|
|
9246
9624
|
}
|
|
9247
9625
|
function createBatchOrchestratorPrompt(requestFiles, responseFiles, templateContent) {
|
|
9248
|
-
const requestLines = requestFiles.map((file, index) => `${index + 1}. messages/${
|
|
9249
|
-
const responseList = responseFiles.map((file) => `"${
|
|
9626
|
+
const requestLines = requestFiles.map((file, index) => `${index + 1}. messages/${path25.basename(file)}`).join("\n");
|
|
9627
|
+
const responseList = responseFiles.map((file) => `"${path25.basename(file)}"`).join(", ");
|
|
9250
9628
|
return renderTemplate2(templateContent, {
|
|
9251
9629
|
requestFiles: requestLines,
|
|
9252
9630
|
responseList
|
|
@@ -9254,8 +9632,8 @@ function createBatchOrchestratorPrompt(requestFiles, responseFiles, templateCont
|
|
|
9254
9632
|
}
|
|
9255
9633
|
|
|
9256
9634
|
// src/evaluation/providers/vscode/dispatch/responseWaiter.ts
|
|
9257
|
-
import { readFile as
|
|
9258
|
-
import
|
|
9635
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
9636
|
+
import path26 from "node:path";
|
|
9259
9637
|
|
|
9260
9638
|
// src/evaluation/providers/vscode/utils/time.ts
|
|
9261
9639
|
function sleep2(ms) {
|
|
@@ -9293,7 +9671,7 @@ async function waitForResponseOutput(responseFileFinal, pollInterval = 1e3, sile
|
|
|
9293
9671
|
const maxAttempts = 10;
|
|
9294
9672
|
while (attempts < maxAttempts) {
|
|
9295
9673
|
try {
|
|
9296
|
-
const content = await
|
|
9674
|
+
const content = await readFile10(responseFileFinal, { encoding: "utf8" });
|
|
9297
9675
|
if (!silent) {
|
|
9298
9676
|
process.stdout.write(`${content}
|
|
9299
9677
|
`);
|
|
@@ -9314,7 +9692,7 @@ async function waitForResponseOutput(responseFileFinal, pollInterval = 1e3, sile
|
|
|
9314
9692
|
}
|
|
9315
9693
|
async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, silent = false, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
9316
9694
|
if (!silent) {
|
|
9317
|
-
const fileList = responseFilesFinal.map((file) =>
|
|
9695
|
+
const fileList = responseFilesFinal.map((file) => path26.basename(file)).join(", ");
|
|
9318
9696
|
console.error(`waiting for ${responseFilesFinal.length} batch response(s): ${fileList}`);
|
|
9319
9697
|
}
|
|
9320
9698
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -9323,7 +9701,7 @@ async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, sil
|
|
|
9323
9701
|
while (pending.size > 0) {
|
|
9324
9702
|
if (Date.now() >= deadline) {
|
|
9325
9703
|
if (!silent) {
|
|
9326
|
-
const remaining = [...pending].map((f) =>
|
|
9704
|
+
const remaining = [...pending].map((f) => path26.basename(f)).join(", ");
|
|
9327
9705
|
console.error(
|
|
9328
9706
|
`error: timed out after ${Math.round(timeoutMs / 1e3)}s waiting for batch responses. Still pending: ${remaining}`
|
|
9329
9707
|
);
|
|
@@ -9350,7 +9728,7 @@ async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, sil
|
|
|
9350
9728
|
const maxAttempts = 10;
|
|
9351
9729
|
while (attempts < maxAttempts) {
|
|
9352
9730
|
try {
|
|
9353
|
-
const content = await
|
|
9731
|
+
const content = await readFile10(file, { encoding: "utf8" });
|
|
9354
9732
|
if (!silent) {
|
|
9355
9733
|
process.stdout.write(`${content}
|
|
9356
9734
|
`);
|
|
@@ -9374,16 +9752,16 @@ async function waitForBatchResponses(responseFilesFinal, pollInterval = 1e3, sil
|
|
|
9374
9752
|
// src/evaluation/providers/vscode/dispatch/vscodeProcess.ts
|
|
9375
9753
|
import { exec, spawn as spawn4 } from "node:child_process";
|
|
9376
9754
|
import { mkdir as mkdir9, writeFile as writeFile2 } from "node:fs/promises";
|
|
9377
|
-
import
|
|
9755
|
+
import path28 from "node:path";
|
|
9378
9756
|
import { promisify as promisify2 } from "node:util";
|
|
9379
9757
|
|
|
9380
9758
|
// src/evaluation/providers/vscode/dispatch/constants.ts
|
|
9381
|
-
import
|
|
9759
|
+
import path27 from "node:path";
|
|
9382
9760
|
var DEFAULT_LOCK_NAME = "subagent.lock";
|
|
9383
9761
|
var DEFAULT_ALIVE_FILENAME = ".alive";
|
|
9384
9762
|
function getDefaultSubagentRoot(vscodeCmd = "code") {
|
|
9385
9763
|
const folder = vscodeCmd === "code-insiders" ? "vscode-insiders-agents" : "vscode-agents";
|
|
9386
|
-
return
|
|
9764
|
+
return path27.join(getSubagentsRoot(), folder);
|
|
9387
9765
|
}
|
|
9388
9766
|
var DEFAULT_SUBAGENT_ROOT = getDefaultSubagentRoot();
|
|
9389
9767
|
|
|
@@ -9450,11 +9828,11 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
9450
9828
|
await raceSpawnError(child);
|
|
9451
9829
|
return true;
|
|
9452
9830
|
}
|
|
9453
|
-
const aliveFile =
|
|
9831
|
+
const aliveFile = path28.join(subagentDir, DEFAULT_ALIVE_FILENAME);
|
|
9454
9832
|
await removeIfExists(aliveFile);
|
|
9455
|
-
const githubAgentsDir =
|
|
9833
|
+
const githubAgentsDir = path28.join(subagentDir, ".github", "agents");
|
|
9456
9834
|
await mkdir9(githubAgentsDir, { recursive: true });
|
|
9457
|
-
const wakeupDst =
|
|
9835
|
+
const wakeupDst = path28.join(githubAgentsDir, "wakeup.md");
|
|
9458
9836
|
await writeFile2(wakeupDst, DEFAULT_WAKEUP_CONTENT, "utf8");
|
|
9459
9837
|
const workspaceChild = spawnVsCode(vscodeCmd, [workspacePath], {
|
|
9460
9838
|
label: "open-workspace"
|
|
@@ -9467,7 +9845,7 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
9467
9845
|
"chat",
|
|
9468
9846
|
"-m",
|
|
9469
9847
|
wakeupChatId,
|
|
9470
|
-
`create a file named .alive in the ${
|
|
9848
|
+
`create a file named .alive in the ${path28.basename(subagentDir)} folder`
|
|
9471
9849
|
];
|
|
9472
9850
|
const wakeupChild = spawnVsCode(vscodeCmd, chatArgs, { label: "send-wakeup-chat" });
|
|
9473
9851
|
await raceSpawnError(wakeupChild);
|
|
@@ -9482,10 +9860,10 @@ async function ensureWorkspaceFocused(workspacePath, workspaceName, subagentDir,
|
|
|
9482
9860
|
return true;
|
|
9483
9861
|
}
|
|
9484
9862
|
async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, requestInstructions, timestamp, vscodeCmd) {
|
|
9485
|
-
const workspacePath =
|
|
9486
|
-
const messagesDir =
|
|
9863
|
+
const workspacePath = path28.join(subagentDir, `${path28.basename(subagentDir)}.code-workspace`);
|
|
9864
|
+
const messagesDir = path28.join(subagentDir, "messages");
|
|
9487
9865
|
await mkdir9(messagesDir, { recursive: true });
|
|
9488
|
-
const reqFile =
|
|
9866
|
+
const reqFile = path28.join(messagesDir, `${timestamp}_req.md`);
|
|
9489
9867
|
await writeFile2(reqFile, requestInstructions, { encoding: "utf8" });
|
|
9490
9868
|
const reqUri = pathToFileUri2(reqFile);
|
|
9491
9869
|
const chatArgs = ["-r", "chat", "-m", chatId];
|
|
@@ -9493,16 +9871,16 @@ async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, reques
|
|
|
9493
9871
|
chatArgs.push("-a", attachment);
|
|
9494
9872
|
}
|
|
9495
9873
|
chatArgs.push("-a", reqFile);
|
|
9496
|
-
chatArgs.push(`Follow instructions in [${
|
|
9874
|
+
chatArgs.push(`Follow instructions in [${path28.basename(reqFile)}](${reqUri})`);
|
|
9497
9875
|
const workspaceReady = await ensureWorkspaceFocused(
|
|
9498
9876
|
workspacePath,
|
|
9499
|
-
|
|
9877
|
+
path28.basename(subagentDir),
|
|
9500
9878
|
subagentDir,
|
|
9501
9879
|
vscodeCmd
|
|
9502
9880
|
);
|
|
9503
9881
|
if (!workspaceReady) {
|
|
9504
9882
|
throw new Error(
|
|
9505
|
-
`VS Code workspace '${
|
|
9883
|
+
`VS Code workspace '${path28.basename(subagentDir)}' failed to become ready within the timeout. Check that '${vscodeCmd}' can open workspaces.`
|
|
9506
9884
|
);
|
|
9507
9885
|
}
|
|
9508
9886
|
await sleep2(500);
|
|
@@ -9510,8 +9888,8 @@ async function launchVsCodeWithChat(subagentDir, chatId, attachmentPaths, reques
|
|
|
9510
9888
|
await raceSpawnError(child);
|
|
9511
9889
|
}
|
|
9512
9890
|
async function launchVsCodeWithBatchChat(subagentDir, chatId, attachmentPaths, chatInstruction, vscodeCmd) {
|
|
9513
|
-
const workspacePath =
|
|
9514
|
-
const messagesDir =
|
|
9891
|
+
const workspacePath = path28.join(subagentDir, `${path28.basename(subagentDir)}.code-workspace`);
|
|
9892
|
+
const messagesDir = path28.join(subagentDir, "messages");
|
|
9515
9893
|
await mkdir9(messagesDir, { recursive: true });
|
|
9516
9894
|
const chatArgs = ["-r", "chat", "-m", chatId];
|
|
9517
9895
|
for (const attachment of attachmentPaths) {
|
|
@@ -9520,13 +9898,13 @@ async function launchVsCodeWithBatchChat(subagentDir, chatId, attachmentPaths, c
|
|
|
9520
9898
|
chatArgs.push(chatInstruction);
|
|
9521
9899
|
const workspaceReady = await ensureWorkspaceFocused(
|
|
9522
9900
|
workspacePath,
|
|
9523
|
-
|
|
9901
|
+
path28.basename(subagentDir),
|
|
9524
9902
|
subagentDir,
|
|
9525
9903
|
vscodeCmd
|
|
9526
9904
|
);
|
|
9527
9905
|
if (!workspaceReady) {
|
|
9528
9906
|
throw new Error(
|
|
9529
|
-
`VS Code workspace '${
|
|
9907
|
+
`VS Code workspace '${path28.basename(subagentDir)}' failed to become ready within the timeout. Check that '${vscodeCmd}' can open workspaces.`
|
|
9530
9908
|
);
|
|
9531
9909
|
}
|
|
9532
9910
|
await sleep2(500);
|
|
@@ -9535,11 +9913,11 @@ async function launchVsCodeWithBatchChat(subagentDir, chatId, attachmentPaths, c
|
|
|
9535
9913
|
}
|
|
9536
9914
|
|
|
9537
9915
|
// src/evaluation/providers/vscode/dispatch/workspaceManager.ts
|
|
9538
|
-
import { copyFile, mkdir as mkdir10, readFile as
|
|
9539
|
-
import
|
|
9916
|
+
import { copyFile, mkdir as mkdir10, readFile as readFile11, readdir as readdir3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
|
|
9917
|
+
import path30 from "node:path";
|
|
9540
9918
|
|
|
9541
9919
|
// src/evaluation/providers/vscode/utils/workspace.ts
|
|
9542
|
-
import
|
|
9920
|
+
import path29 from "node:path";
|
|
9543
9921
|
import JSON5 from "json5";
|
|
9544
9922
|
function transformWorkspacePaths(workspaceContent, templateDir) {
|
|
9545
9923
|
let workspace;
|
|
@@ -9556,10 +9934,10 @@ function transformWorkspacePaths(workspaceContent, templateDir) {
|
|
|
9556
9934
|
}
|
|
9557
9935
|
const transformedFolders = workspace.folders.map((folder) => {
|
|
9558
9936
|
const folderPath = folder.path;
|
|
9559
|
-
if (
|
|
9937
|
+
if (path29.isAbsolute(folderPath)) {
|
|
9560
9938
|
return folder;
|
|
9561
9939
|
}
|
|
9562
|
-
const absolutePath =
|
|
9940
|
+
const absolutePath = path29.resolve(templateDir, folderPath);
|
|
9563
9941
|
return {
|
|
9564
9942
|
...folder,
|
|
9565
9943
|
path: absolutePath
|
|
@@ -9581,19 +9959,19 @@ function transformWorkspacePaths(workspaceContent, templateDir) {
|
|
|
9581
9959
|
if (locationMap && typeof locationMap === "object") {
|
|
9582
9960
|
const transformedMap = {};
|
|
9583
9961
|
for (const [locationPath, value] of Object.entries(locationMap)) {
|
|
9584
|
-
const isAbsolute =
|
|
9962
|
+
const isAbsolute = path29.isAbsolute(locationPath);
|
|
9585
9963
|
if (isAbsolute) {
|
|
9586
9964
|
transformedMap[locationPath] = value;
|
|
9587
9965
|
} else {
|
|
9588
9966
|
const firstGlobIndex = locationPath.search(/[*]/);
|
|
9589
9967
|
if (firstGlobIndex === -1) {
|
|
9590
|
-
const resolvedPath =
|
|
9968
|
+
const resolvedPath = path29.resolve(templateDir, locationPath).replace(/\\/g, "/");
|
|
9591
9969
|
transformedMap[resolvedPath] = value;
|
|
9592
9970
|
} else {
|
|
9593
9971
|
const basePathEnd = locationPath.lastIndexOf("/", firstGlobIndex);
|
|
9594
9972
|
const basePath = basePathEnd !== -1 ? locationPath.substring(0, basePathEnd) : ".";
|
|
9595
9973
|
const patternPath = locationPath.substring(basePathEnd !== -1 ? basePathEnd : 0);
|
|
9596
|
-
const resolvedPath = (
|
|
9974
|
+
const resolvedPath = (path29.resolve(templateDir, basePath) + patternPath).replace(
|
|
9597
9975
|
/\\/g,
|
|
9598
9976
|
"/"
|
|
9599
9977
|
);
|
|
@@ -9634,7 +10012,7 @@ async function findUnlockedSubagent(subagentRoot) {
|
|
|
9634
10012
|
number: Number.parseInt(entry.name.split("-")[1] ?? "", 10)
|
|
9635
10013
|
})).filter((entry) => Number.isInteger(entry.number)).sort((a, b) => a.number - b.number);
|
|
9636
10014
|
for (const subagent of subagents) {
|
|
9637
|
-
const lockFile =
|
|
10015
|
+
const lockFile = path30.join(subagent.absolutePath, DEFAULT_LOCK_NAME);
|
|
9638
10016
|
if (!await pathExists(lockFile)) {
|
|
9639
10017
|
return subagent.absolutePath;
|
|
9640
10018
|
}
|
|
@@ -9644,7 +10022,7 @@ async function findUnlockedSubagent(subagentRoot) {
|
|
|
9644
10022
|
async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
9645
10023
|
let workspaceContent;
|
|
9646
10024
|
if (workspaceTemplate) {
|
|
9647
|
-
const workspaceSrc =
|
|
10025
|
+
const workspaceSrc = path30.resolve(workspaceTemplate);
|
|
9648
10026
|
if (!await pathExists(workspaceSrc)) {
|
|
9649
10027
|
throw new Error(`workspace template not found: ${workspaceSrc}`);
|
|
9650
10028
|
}
|
|
@@ -9652,18 +10030,18 @@ async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
|
9652
10030
|
if (!stats.isFile()) {
|
|
9653
10031
|
throw new Error(`workspace template must be a file, not a directory: ${workspaceSrc}`);
|
|
9654
10032
|
}
|
|
9655
|
-
const templateText = await
|
|
10033
|
+
const templateText = await readFile11(workspaceSrc, "utf8");
|
|
9656
10034
|
workspaceContent = JSON.parse(templateText);
|
|
9657
10035
|
} else {
|
|
9658
10036
|
workspaceContent = DEFAULT_WORKSPACE_TEMPLATE;
|
|
9659
10037
|
}
|
|
9660
|
-
const workspaceName = `${
|
|
9661
|
-
const workspaceDst =
|
|
9662
|
-
const templateDir = workspaceTemplate ?
|
|
10038
|
+
const workspaceName = `${path30.basename(subagentDir)}.code-workspace`;
|
|
10039
|
+
const workspaceDst = path30.join(subagentDir, workspaceName);
|
|
10040
|
+
const templateDir = workspaceTemplate ? path30.dirname(path30.resolve(workspaceTemplate)) : subagentDir;
|
|
9663
10041
|
const workspaceJson = JSON.stringify(workspaceContent, null, 2);
|
|
9664
10042
|
let transformedContent = transformWorkspacePaths(workspaceJson, templateDir);
|
|
9665
10043
|
if (cwd) {
|
|
9666
|
-
const absCwd =
|
|
10044
|
+
const absCwd = path30.resolve(cwd);
|
|
9667
10045
|
const parsed = JSON.parse(transformedContent);
|
|
9668
10046
|
const alreadyPresent = parsed.folders.some((f) => f.path === absCwd);
|
|
9669
10047
|
if (!alreadyPresent) {
|
|
@@ -9672,35 +10050,35 @@ async function copyAgentConfig(subagentDir, workspaceTemplate, cwd) {
|
|
|
9672
10050
|
}
|
|
9673
10051
|
}
|
|
9674
10052
|
await writeFile3(workspaceDst, transformedContent, "utf8");
|
|
9675
|
-
const messagesDir =
|
|
10053
|
+
const messagesDir = path30.join(subagentDir, "messages");
|
|
9676
10054
|
await mkdir10(messagesDir, { recursive: true });
|
|
9677
10055
|
return { workspace: workspaceDst, messagesDir };
|
|
9678
10056
|
}
|
|
9679
10057
|
async function createSubagentLock(subagentDir) {
|
|
9680
|
-
const messagesDir =
|
|
10058
|
+
const messagesDir = path30.join(subagentDir, "messages");
|
|
9681
10059
|
if (await pathExists(messagesDir)) {
|
|
9682
10060
|
const files = await readdir3(messagesDir);
|
|
9683
10061
|
await Promise.all(
|
|
9684
10062
|
files.map(async (file) => {
|
|
9685
|
-
const target =
|
|
10063
|
+
const target = path30.join(messagesDir, file);
|
|
9686
10064
|
await removeIfExists(target);
|
|
9687
10065
|
})
|
|
9688
10066
|
);
|
|
9689
10067
|
}
|
|
9690
|
-
const githubAgentsDir =
|
|
10068
|
+
const githubAgentsDir = path30.join(subagentDir, ".github", "agents");
|
|
9691
10069
|
if (await pathExists(githubAgentsDir)) {
|
|
9692
10070
|
const agentFiles = await readdir3(githubAgentsDir);
|
|
9693
10071
|
const preservedFiles = /* @__PURE__ */ new Set(["wakeup.md", "subagent.md"]);
|
|
9694
10072
|
await Promise.all(
|
|
9695
|
-
agentFiles.filter((file) => file.endsWith(".md") && !preservedFiles.has(file)).map((file) => removeIfExists(
|
|
10073
|
+
agentFiles.filter((file) => file.endsWith(".md") && !preservedFiles.has(file)).map((file) => removeIfExists(path30.join(githubAgentsDir, file)))
|
|
9696
10074
|
);
|
|
9697
10075
|
}
|
|
9698
|
-
const lockFile =
|
|
10076
|
+
const lockFile = path30.join(subagentDir, DEFAULT_LOCK_NAME);
|
|
9699
10077
|
await writeFile3(lockFile, "", { encoding: "utf8" });
|
|
9700
10078
|
return lockFile;
|
|
9701
10079
|
}
|
|
9702
10080
|
async function removeSubagentLock(subagentDir) {
|
|
9703
|
-
const lockFile =
|
|
10081
|
+
const lockFile = path30.join(subagentDir, DEFAULT_LOCK_NAME);
|
|
9704
10082
|
await removeIfExists(lockFile);
|
|
9705
10083
|
}
|
|
9706
10084
|
async function prepareSubagentDirectory(subagentDir, promptFile, chatId, workspaceTemplate, dryRun, cwd) {
|
|
@@ -9720,9 +10098,9 @@ async function prepareSubagentDirectory(subagentDir, promptFile, chatId, workspa
|
|
|
9720
10098
|
return 1;
|
|
9721
10099
|
}
|
|
9722
10100
|
if (promptFile) {
|
|
9723
|
-
const githubAgentsDir =
|
|
10101
|
+
const githubAgentsDir = path30.join(subagentDir, ".github", "agents");
|
|
9724
10102
|
await mkdir10(githubAgentsDir, { recursive: true });
|
|
9725
|
-
const agentFile =
|
|
10103
|
+
const agentFile = path30.join(githubAgentsDir, `${chatId}.md`);
|
|
9726
10104
|
try {
|
|
9727
10105
|
await copyFile(promptFile, agentFile);
|
|
9728
10106
|
} catch (error) {
|
|
@@ -9741,7 +10119,7 @@ async function resolvePromptFile(promptFile) {
|
|
|
9741
10119
|
if (!promptFile) {
|
|
9742
10120
|
return void 0;
|
|
9743
10121
|
}
|
|
9744
|
-
const resolvedPrompt =
|
|
10122
|
+
const resolvedPrompt = path31.resolve(promptFile);
|
|
9745
10123
|
if (!await pathExists(resolvedPrompt)) {
|
|
9746
10124
|
throw new Error(`Prompt file not found: ${resolvedPrompt}`);
|
|
9747
10125
|
}
|
|
@@ -9757,7 +10135,7 @@ async function resolveAttachments(extraAttachments) {
|
|
|
9757
10135
|
}
|
|
9758
10136
|
const resolved = [];
|
|
9759
10137
|
for (const attachment of extraAttachments) {
|
|
9760
|
-
const resolvedPath =
|
|
10138
|
+
const resolvedPath = path31.resolve(attachment);
|
|
9761
10139
|
if (!await pathExists(resolvedPath)) {
|
|
9762
10140
|
throw new Error(`Attachment not found: ${resolvedPath}`);
|
|
9763
10141
|
}
|
|
@@ -9799,7 +10177,7 @@ async function dispatchAgentSession(options) {
|
|
|
9799
10177
|
error: "No unlocked subagents available. Provision additional subagents with: subagent code provision --subagents <desired_total>"
|
|
9800
10178
|
};
|
|
9801
10179
|
}
|
|
9802
|
-
const subagentName =
|
|
10180
|
+
const subagentName = path31.basename(subagentDir);
|
|
9803
10181
|
const chatId = Math.random().toString(16).slice(2, 10);
|
|
9804
10182
|
const preparationResult = await prepareSubagentDirectory(
|
|
9805
10183
|
subagentDir,
|
|
@@ -9827,9 +10205,9 @@ async function dispatchAgentSession(options) {
|
|
|
9827
10205
|
};
|
|
9828
10206
|
}
|
|
9829
10207
|
const timestamp = generateTimestamp();
|
|
9830
|
-
const messagesDir =
|
|
9831
|
-
const responseFileTmp =
|
|
9832
|
-
const responseFileFinal =
|
|
10208
|
+
const messagesDir = path31.join(subagentDir, "messages");
|
|
10209
|
+
const responseFileTmp = path31.join(messagesDir, `${timestamp}_res.tmp.md`);
|
|
10210
|
+
const responseFileFinal = path31.join(messagesDir, `${timestamp}_res.md`);
|
|
9833
10211
|
const requestInstructions = createRequestPrompt(
|
|
9834
10212
|
userQuery,
|
|
9835
10213
|
responseFileTmp,
|
|
@@ -9934,7 +10312,7 @@ async function dispatchBatchAgent(options) {
|
|
|
9934
10312
|
error: "No unlocked subagents available. Provision additional subagents with: subagent code provision --subagents <desired_total>"
|
|
9935
10313
|
};
|
|
9936
10314
|
}
|
|
9937
|
-
subagentName =
|
|
10315
|
+
subagentName = path31.basename(subagentDir);
|
|
9938
10316
|
const chatId = Math.random().toString(16).slice(2, 10);
|
|
9939
10317
|
const preparationResult = await prepareSubagentDirectory(
|
|
9940
10318
|
subagentDir,
|
|
@@ -9965,17 +10343,17 @@ async function dispatchBatchAgent(options) {
|
|
|
9965
10343
|
};
|
|
9966
10344
|
}
|
|
9967
10345
|
const timestamp = generateTimestamp();
|
|
9968
|
-
const messagesDir =
|
|
10346
|
+
const messagesDir = path31.join(subagentDir, "messages");
|
|
9969
10347
|
requestFiles = userQueries.map(
|
|
9970
|
-
(_, index) =>
|
|
10348
|
+
(_, index) => path31.join(messagesDir, `${timestamp}_${index}_req.md`)
|
|
9971
10349
|
);
|
|
9972
10350
|
const responseTmpFiles = userQueries.map(
|
|
9973
|
-
(_, index) =>
|
|
10351
|
+
(_, index) => path31.join(messagesDir, `${timestamp}_${index}_res.tmp.md`)
|
|
9974
10352
|
);
|
|
9975
10353
|
responseFilesFinal = userQueries.map(
|
|
9976
|
-
(_, index) =>
|
|
10354
|
+
(_, index) => path31.join(messagesDir, `${timestamp}_${index}_res.md`)
|
|
9977
10355
|
);
|
|
9978
|
-
const orchestratorFile =
|
|
10356
|
+
const orchestratorFile = path31.join(messagesDir, `${timestamp}_orchestrator.md`);
|
|
9979
10357
|
if (!dryRun) {
|
|
9980
10358
|
await Promise.all(
|
|
9981
10359
|
userQueries.map((query, index) => {
|
|
@@ -10061,7 +10439,7 @@ async function dispatchBatchAgent(options) {
|
|
|
10061
10439
|
|
|
10062
10440
|
// src/evaluation/providers/vscode/dispatch/provision.ts
|
|
10063
10441
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
10064
|
-
import
|
|
10442
|
+
import path32 from "node:path";
|
|
10065
10443
|
var DEFAULT_WORKSPACE_TEMPLATE2 = {
|
|
10066
10444
|
folders: [
|
|
10067
10445
|
{
|
|
@@ -10092,7 +10470,7 @@ async function provisionSubagents(options) {
|
|
|
10092
10470
|
if (!Number.isInteger(subagents) || subagents < 1) {
|
|
10093
10471
|
throw new Error("subagents must be a positive integer");
|
|
10094
10472
|
}
|
|
10095
|
-
const targetPath =
|
|
10473
|
+
const targetPath = path32.resolve(targetRoot);
|
|
10096
10474
|
if (!dryRun) {
|
|
10097
10475
|
await ensureDir(targetPath);
|
|
10098
10476
|
}
|
|
@@ -10112,7 +10490,7 @@ async function provisionSubagents(options) {
|
|
|
10112
10490
|
continue;
|
|
10113
10491
|
}
|
|
10114
10492
|
highestNumber = Math.max(highestNumber, parsed);
|
|
10115
|
-
const lockFile =
|
|
10493
|
+
const lockFile = path32.join(entry.absolutePath, lockName);
|
|
10116
10494
|
const locked = await pathExists(lockFile);
|
|
10117
10495
|
if (locked) {
|
|
10118
10496
|
lockedSubagents.add(entry.absolutePath);
|
|
@@ -10129,10 +10507,10 @@ async function provisionSubagents(options) {
|
|
|
10129
10507
|
break;
|
|
10130
10508
|
}
|
|
10131
10509
|
const subagentDir = subagent.absolutePath;
|
|
10132
|
-
const githubAgentsDir =
|
|
10133
|
-
const lockFile =
|
|
10134
|
-
const workspaceDst =
|
|
10135
|
-
const wakeupDst =
|
|
10510
|
+
const githubAgentsDir = path32.join(subagentDir, ".github", "agents");
|
|
10511
|
+
const lockFile = path32.join(subagentDir, lockName);
|
|
10512
|
+
const workspaceDst = path32.join(subagentDir, `${path32.basename(subagentDir)}.code-workspace`);
|
|
10513
|
+
const wakeupDst = path32.join(githubAgentsDir, "wakeup.md");
|
|
10136
10514
|
const isLocked = await pathExists(lockFile);
|
|
10137
10515
|
if (isLocked && !force) {
|
|
10138
10516
|
continue;
|
|
@@ -10170,10 +10548,10 @@ async function provisionSubagents(options) {
|
|
|
10170
10548
|
let nextIndex = highestNumber;
|
|
10171
10549
|
while (subagentsProvisioned < subagents) {
|
|
10172
10550
|
nextIndex += 1;
|
|
10173
|
-
const subagentDir =
|
|
10174
|
-
const githubAgentsDir =
|
|
10175
|
-
const workspaceDst =
|
|
10176
|
-
const wakeupDst =
|
|
10551
|
+
const subagentDir = path32.join(targetPath, `subagent-${nextIndex}`);
|
|
10552
|
+
const githubAgentsDir = path32.join(subagentDir, ".github", "agents");
|
|
10553
|
+
const workspaceDst = path32.join(subagentDir, `${path32.basename(subagentDir)}.code-workspace`);
|
|
10554
|
+
const wakeupDst = path32.join(githubAgentsDir, "wakeup.md");
|
|
10177
10555
|
if (!dryRun) {
|
|
10178
10556
|
await ensureDir(subagentDir);
|
|
10179
10557
|
await ensureDir(githubAgentsDir);
|
|
@@ -10363,7 +10741,7 @@ var VSCodeProvider = class {
|
|
|
10363
10741
|
async function locateVSCodeExecutable(candidate) {
|
|
10364
10742
|
const includesPathSeparator = candidate.includes("/") || candidate.includes("\\");
|
|
10365
10743
|
if (includesPathSeparator) {
|
|
10366
|
-
const resolved =
|
|
10744
|
+
const resolved = path33.isAbsolute(candidate) ? candidate : path33.resolve(candidate);
|
|
10367
10745
|
try {
|
|
10368
10746
|
await access3(resolved, constants3.F_OK);
|
|
10369
10747
|
return resolved;
|
|
@@ -10392,7 +10770,7 @@ async function resolveWorkspaceTemplateFile(template) {
|
|
|
10392
10770
|
return void 0;
|
|
10393
10771
|
}
|
|
10394
10772
|
try {
|
|
10395
|
-
const stats = await stat5(
|
|
10773
|
+
const stats = await stat5(path33.resolve(template));
|
|
10396
10774
|
return stats.isFile() ? template : void 0;
|
|
10397
10775
|
} catch {
|
|
10398
10776
|
return template;
|
|
@@ -10416,7 +10794,7 @@ function buildMandatoryPrereadBlock2(attachmentFiles) {
|
|
|
10416
10794
|
return "";
|
|
10417
10795
|
}
|
|
10418
10796
|
const buildList = (files) => files.map((absolutePath) => {
|
|
10419
|
-
const fileName =
|
|
10797
|
+
const fileName = path33.basename(absolutePath);
|
|
10420
10798
|
const fileUri = pathToFileUri3(absolutePath);
|
|
10421
10799
|
return `* [${fileName}](${fileUri})`;
|
|
10422
10800
|
});
|
|
@@ -10437,7 +10815,7 @@ function collectAttachmentFiles(attachments) {
|
|
|
10437
10815
|
}
|
|
10438
10816
|
const unique = /* @__PURE__ */ new Map();
|
|
10439
10817
|
for (const attachment of attachments) {
|
|
10440
|
-
const absolutePath =
|
|
10818
|
+
const absolutePath = path33.resolve(attachment);
|
|
10441
10819
|
if (!unique.has(absolutePath)) {
|
|
10442
10820
|
unique.set(absolutePath, absolutePath);
|
|
10443
10821
|
}
|
|
@@ -10445,7 +10823,7 @@ function collectAttachmentFiles(attachments) {
|
|
|
10445
10823
|
return Array.from(unique.values());
|
|
10446
10824
|
}
|
|
10447
10825
|
function pathToFileUri3(filePath) {
|
|
10448
|
-
const absolutePath =
|
|
10826
|
+
const absolutePath = path33.isAbsolute(filePath) ? filePath : path33.resolve(filePath);
|
|
10449
10827
|
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
10450
10828
|
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
10451
10829
|
return `file:///${normalizedPath}`;
|
|
@@ -10458,7 +10836,7 @@ function normalizeAttachments(attachments) {
|
|
|
10458
10836
|
}
|
|
10459
10837
|
const deduped = /* @__PURE__ */ new Set();
|
|
10460
10838
|
for (const attachment of attachments) {
|
|
10461
|
-
deduped.add(
|
|
10839
|
+
deduped.add(path33.resolve(attachment));
|
|
10462
10840
|
}
|
|
10463
10841
|
return Array.from(deduped);
|
|
10464
10842
|
}
|
|
@@ -10467,7 +10845,7 @@ function mergeAttachments(all) {
|
|
|
10467
10845
|
for (const list of all) {
|
|
10468
10846
|
if (!list) continue;
|
|
10469
10847
|
for (const inputFile of list) {
|
|
10470
|
-
deduped.add(
|
|
10848
|
+
deduped.add(path33.resolve(inputFile));
|
|
10471
10849
|
}
|
|
10472
10850
|
}
|
|
10473
10851
|
return deduped.size > 0 ? Array.from(deduped) : void 0;
|
|
@@ -10515,8 +10893,8 @@ total unlocked subagents available: ${result.created.length + result.skippedExis
|
|
|
10515
10893
|
|
|
10516
10894
|
// src/evaluation/providers/targets-file.ts
|
|
10517
10895
|
import { constants as constants4 } from "node:fs";
|
|
10518
|
-
import { access as access4, readFile as
|
|
10519
|
-
import
|
|
10896
|
+
import { access as access4, readFile as readFile12 } from "node:fs/promises";
|
|
10897
|
+
import path34 from "node:path";
|
|
10520
10898
|
import { parse as parse4 } from "yaml";
|
|
10521
10899
|
function isRecord(value) {
|
|
10522
10900
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -10556,11 +10934,11 @@ async function fileExists3(filePath) {
|
|
|
10556
10934
|
}
|
|
10557
10935
|
}
|
|
10558
10936
|
async function readTargetDefinitions(filePath) {
|
|
10559
|
-
const absolutePath =
|
|
10937
|
+
const absolutePath = path34.resolve(filePath);
|
|
10560
10938
|
if (!await fileExists3(absolutePath)) {
|
|
10561
10939
|
throw new Error(`targets.yaml not found at ${absolutePath}`);
|
|
10562
10940
|
}
|
|
10563
|
-
const raw = await
|
|
10941
|
+
const raw = await readFile12(absolutePath, "utf8");
|
|
10564
10942
|
const parsed = parse4(raw);
|
|
10565
10943
|
if (!isRecord(parsed)) {
|
|
10566
10944
|
throw new Error(`targets.yaml at ${absolutePath} must be a YAML object with a 'targets' field`);
|
|
@@ -10576,16 +10954,16 @@ function listTargetNames(definitions) {
|
|
|
10576
10954
|
}
|
|
10577
10955
|
|
|
10578
10956
|
// src/evaluation/providers/provider-discovery.ts
|
|
10579
|
-
import
|
|
10957
|
+
import path35 from "node:path";
|
|
10580
10958
|
import fg from "fast-glob";
|
|
10581
10959
|
async function discoverProviders(registry, baseDir) {
|
|
10582
10960
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
10583
10961
|
const candidateDirs = [];
|
|
10584
|
-
let dir =
|
|
10585
|
-
const root =
|
|
10962
|
+
let dir = path35.resolve(baseDir);
|
|
10963
|
+
const root = path35.parse(dir).root;
|
|
10586
10964
|
while (dir !== root) {
|
|
10587
|
-
candidateDirs.push(
|
|
10588
|
-
dir =
|
|
10965
|
+
candidateDirs.push(path35.join(dir, ".agentv", "providers"));
|
|
10966
|
+
dir = path35.dirname(dir);
|
|
10589
10967
|
}
|
|
10590
10968
|
let files = [];
|
|
10591
10969
|
for (const providersDir of candidateDirs) {
|
|
@@ -10601,7 +10979,7 @@ async function discoverProviders(registry, baseDir) {
|
|
|
10601
10979
|
}
|
|
10602
10980
|
const discoveredKinds = [];
|
|
10603
10981
|
for (const filePath of files) {
|
|
10604
|
-
const basename =
|
|
10982
|
+
const basename = path35.basename(filePath);
|
|
10605
10983
|
const kindName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
10606
10984
|
if (registry.has(kindName)) {
|
|
10607
10985
|
continue;
|
|
@@ -10727,150 +11105,6 @@ import { mkdtemp as mkdtemp2, rm as rm3, writeFile as writeFile6 } from "node:fs
|
|
|
10727
11105
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
10728
11106
|
import { dirname, join } from "node:path";
|
|
10729
11107
|
|
|
10730
|
-
// src/runtime/exec.ts
|
|
10731
|
-
function shellEscapePath(value) {
|
|
10732
|
-
if (process.platform === "win32") {
|
|
10733
|
-
return `"${value.replaceAll('"', '""')}"`;
|
|
10734
|
-
}
|
|
10735
|
-
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
10736
|
-
}
|
|
10737
|
-
async function execFileWithStdin(argv, stdinPayload, options = {}) {
|
|
10738
|
-
if (argv.length === 0) {
|
|
10739
|
-
throw new Error("Executable argv must include at least one entry");
|
|
10740
|
-
}
|
|
10741
|
-
if (typeof Bun !== "undefined") {
|
|
10742
|
-
return execFileWithStdinBun(argv, stdinPayload, options);
|
|
10743
|
-
}
|
|
10744
|
-
return execFileWithStdinNode(argv, stdinPayload, options);
|
|
10745
|
-
}
|
|
10746
|
-
async function execFileWithStdinBun(argv, stdinPayload, options) {
|
|
10747
|
-
const command = [...argv];
|
|
10748
|
-
const encoder = new TextEncoder();
|
|
10749
|
-
const proc = Bun.spawn(command, {
|
|
10750
|
-
cwd: options.cwd,
|
|
10751
|
-
stdin: encoder.encode(stdinPayload),
|
|
10752
|
-
stdout: "pipe",
|
|
10753
|
-
stderr: "pipe",
|
|
10754
|
-
// Merge additional env vars with process.env
|
|
10755
|
-
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
10756
|
-
});
|
|
10757
|
-
let timedOut = false;
|
|
10758
|
-
const timeout = options.timeoutMs !== void 0 ? setTimeout(() => {
|
|
10759
|
-
timedOut = true;
|
|
10760
|
-
proc.kill("SIGKILL");
|
|
10761
|
-
}, options.timeoutMs) : void 0;
|
|
10762
|
-
try {
|
|
10763
|
-
const stdoutPromise = proc.stdout ? new Response(proc.stdout).text() : Promise.resolve("");
|
|
10764
|
-
const stderrPromise = proc.stderr ? new Response(proc.stderr).text() : Promise.resolve("");
|
|
10765
|
-
const [stdout, stderr, exitCode] = await Promise.all([
|
|
10766
|
-
stdoutPromise,
|
|
10767
|
-
stderrPromise,
|
|
10768
|
-
proc.exited
|
|
10769
|
-
]);
|
|
10770
|
-
if (timedOut) {
|
|
10771
|
-
throw new Error(`Process timed out after ${options.timeoutMs}ms`);
|
|
10772
|
-
}
|
|
10773
|
-
return {
|
|
10774
|
-
stdout: stdout.replace(/\r\n/g, "\n"),
|
|
10775
|
-
stderr: stderr.replace(/\r\n/g, "\n"),
|
|
10776
|
-
exitCode
|
|
10777
|
-
};
|
|
10778
|
-
} finally {
|
|
10779
|
-
if (timeout !== void 0) {
|
|
10780
|
-
clearTimeout(timeout);
|
|
10781
|
-
}
|
|
10782
|
-
}
|
|
10783
|
-
}
|
|
10784
|
-
async function execFileWithStdinNode(argv, stdinPayload, options) {
|
|
10785
|
-
const { spawn: spawn5 } = await import("node:child_process");
|
|
10786
|
-
return new Promise((resolve, reject) => {
|
|
10787
|
-
const [cmd, ...args] = argv;
|
|
10788
|
-
const child = spawn5(cmd, args, {
|
|
10789
|
-
cwd: options.cwd,
|
|
10790
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
10791
|
-
// Merge additional env vars with process.env
|
|
10792
|
-
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
10793
|
-
});
|
|
10794
|
-
const stdoutChunks = [];
|
|
10795
|
-
const stderrChunks = [];
|
|
10796
|
-
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
10797
|
-
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
10798
|
-
let timedOut = false;
|
|
10799
|
-
const timeout = options.timeoutMs !== void 0 ? setTimeout(() => {
|
|
10800
|
-
timedOut = true;
|
|
10801
|
-
child.kill("SIGKILL");
|
|
10802
|
-
}, options.timeoutMs) : void 0;
|
|
10803
|
-
child.on("error", (error) => {
|
|
10804
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
10805
|
-
reject(error);
|
|
10806
|
-
});
|
|
10807
|
-
child.on("close", (code) => {
|
|
10808
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
10809
|
-
if (timedOut) {
|
|
10810
|
-
reject(new Error(`Process timed out after ${options.timeoutMs}ms`));
|
|
10811
|
-
return;
|
|
10812
|
-
}
|
|
10813
|
-
const stdout = Buffer.concat(stdoutChunks).toString("utf8").replace(/\r\n/g, "\n");
|
|
10814
|
-
const stderr = Buffer.concat(stderrChunks).toString("utf8").replace(/\r\n/g, "\n");
|
|
10815
|
-
resolve({
|
|
10816
|
-
stdout,
|
|
10817
|
-
stderr,
|
|
10818
|
-
exitCode: code ?? 0
|
|
10819
|
-
});
|
|
10820
|
-
});
|
|
10821
|
-
if (child.stdin) {
|
|
10822
|
-
child.stdin.write(stdinPayload);
|
|
10823
|
-
child.stdin.end();
|
|
10824
|
-
}
|
|
10825
|
-
});
|
|
10826
|
-
}
|
|
10827
|
-
async function execShellWithStdin(command, stdinPayload, options = {}) {
|
|
10828
|
-
const { mkdir: mkdir16, readFile: readFile16, rm: rm6, writeFile: writeFile9 } = await import("node:fs/promises");
|
|
10829
|
-
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
10830
|
-
const path51 = await import("node:path");
|
|
10831
|
-
const { randomUUID: randomUUID10 } = await import("node:crypto");
|
|
10832
|
-
const dir = path51.join(tmpdir3(), `agentv-exec-${randomUUID10()}`);
|
|
10833
|
-
await mkdir16(dir, { recursive: true });
|
|
10834
|
-
const stdinPath = path51.join(dir, "stdin.txt");
|
|
10835
|
-
const stdoutPath = path51.join(dir, "stdout.txt");
|
|
10836
|
-
const stderrPath = path51.join(dir, "stderr.txt");
|
|
10837
|
-
await writeFile9(stdinPath, stdinPayload, "utf8");
|
|
10838
|
-
const wrappedCommand = process.platform === "win32" ? `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}` : `(${command}) < ${shellEscapePath(stdinPath)} > ${shellEscapePath(stdoutPath)} 2> ${shellEscapePath(stderrPath)}`;
|
|
10839
|
-
const { spawn: spawn5 } = await import("node:child_process");
|
|
10840
|
-
try {
|
|
10841
|
-
const exitCode = await new Promise((resolve, reject) => {
|
|
10842
|
-
const child = spawn5(wrappedCommand, {
|
|
10843
|
-
shell: true,
|
|
10844
|
-
cwd: options.cwd,
|
|
10845
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
10846
|
-
// Merge additional env vars with process.env
|
|
10847
|
-
env: options.env ? { ...process.env, ...options.env } : process.env
|
|
10848
|
-
});
|
|
10849
|
-
const timeout = options.timeoutMs ? setTimeout(() => {
|
|
10850
|
-
child.kill();
|
|
10851
|
-
reject(new Error(`Process timed out after ${options.timeoutMs}ms`));
|
|
10852
|
-
}, options.timeoutMs) : void 0;
|
|
10853
|
-
child.on("error", (error) => {
|
|
10854
|
-
if (timeout !== void 0) {
|
|
10855
|
-
clearTimeout(timeout);
|
|
10856
|
-
}
|
|
10857
|
-
reject(error);
|
|
10858
|
-
});
|
|
10859
|
-
child.on("exit", (code) => {
|
|
10860
|
-
if (timeout !== void 0) {
|
|
10861
|
-
clearTimeout(timeout);
|
|
10862
|
-
}
|
|
10863
|
-
resolve(code ?? 0);
|
|
10864
|
-
});
|
|
10865
|
-
});
|
|
10866
|
-
const stdout = (await readFile16(stdoutPath, "utf8")).replace(/\r\n/g, "\n");
|
|
10867
|
-
const stderr = (await readFile16(stderrPath, "utf8")).replace(/\r\n/g, "\n");
|
|
10868
|
-
return { stdout, stderr, exitCode };
|
|
10869
|
-
} finally {
|
|
10870
|
-
await rm6(dir, { recursive: true, force: true });
|
|
10871
|
-
}
|
|
10872
|
-
}
|
|
10873
|
-
|
|
10874
11108
|
// src/runtime/target-proxy.ts
|
|
10875
11109
|
import { randomBytes } from "node:crypto";
|
|
10876
11110
|
import { createServer } from "node:http";
|
|
@@ -11380,7 +11614,7 @@ import { generateText as generateText3 } from "ai";
|
|
|
11380
11614
|
|
|
11381
11615
|
// src/evaluation/evaluators/llm-grader.ts
|
|
11382
11616
|
import fs2 from "node:fs/promises";
|
|
11383
|
-
import
|
|
11617
|
+
import path36 from "node:path";
|
|
11384
11618
|
import { generateText as generateText2, stepCountIs, tool } from "ai";
|
|
11385
11619
|
import { z as z3 } from "zod";
|
|
11386
11620
|
var DEFAULT_MAX_STEPS = 10;
|
|
@@ -11464,6 +11698,15 @@ var scoreRangeEvaluationSchema = z3.object({
|
|
|
11464
11698
|
checks: z3.array(scoreRangeCheckResultSchema).describe("Scores for each rubric criterion"),
|
|
11465
11699
|
overall_reasoning: z3.string().describe("Overall assessment summary (1-2 sentences)").optional()
|
|
11466
11700
|
});
|
|
11701
|
+
function resolveContentBasePath(context) {
|
|
11702
|
+
if (context.workspacePath) {
|
|
11703
|
+
return context.workspacePath;
|
|
11704
|
+
}
|
|
11705
|
+
if ("config" in context.target && context.target.config && typeof context.target.config === "object" && "cwd" in context.target.config && typeof context.target.config.cwd === "string") {
|
|
11706
|
+
return context.target.config.cwd;
|
|
11707
|
+
}
|
|
11708
|
+
return void 0;
|
|
11709
|
+
}
|
|
11467
11710
|
var LlmGraderEvaluator = class {
|
|
11468
11711
|
kind = "llm-grader";
|
|
11469
11712
|
resolveGraderProvider;
|
|
@@ -11481,24 +11724,46 @@ var LlmGraderEvaluator = class {
|
|
|
11481
11724
|
this.graderTargetProvider = options.graderTargetProvider ?? options.judgeTargetProvider;
|
|
11482
11725
|
}
|
|
11483
11726
|
async evaluate(context) {
|
|
11727
|
+
const preparedContext = await this.prepareContext(context);
|
|
11484
11728
|
if (this.graderTargetProvider) {
|
|
11485
|
-
return this.evaluateWithGraderTarget(
|
|
11729
|
+
return this.evaluateWithGraderTarget(preparedContext);
|
|
11486
11730
|
}
|
|
11487
|
-
const graderProvider = await this.resolveGraderProvider(
|
|
11731
|
+
const graderProvider = await this.resolveGraderProvider(preparedContext);
|
|
11488
11732
|
if (!graderProvider) {
|
|
11489
11733
|
throw new Error("No grader provider available for LLM grading");
|
|
11490
11734
|
}
|
|
11491
11735
|
if (graderProvider.kind === "agentv") {
|
|
11492
|
-
return this.evaluateBuiltIn(
|
|
11736
|
+
return this.evaluateBuiltIn(preparedContext, graderProvider);
|
|
11493
11737
|
}
|
|
11494
11738
|
if (isAgentProvider(graderProvider)) {
|
|
11495
|
-
return this.evaluateWithDelegatedAgent(
|
|
11739
|
+
return this.evaluateWithDelegatedAgent(preparedContext, graderProvider);
|
|
11496
11740
|
}
|
|
11497
|
-
const config =
|
|
11741
|
+
const config = preparedContext.evaluator;
|
|
11498
11742
|
if (config?.type === "llm-grader" && config.rubrics && config.rubrics.length > 0) {
|
|
11499
|
-
return this.evaluateWithRubrics(
|
|
11743
|
+
return this.evaluateWithRubrics(preparedContext, graderProvider, config.rubrics);
|
|
11744
|
+
}
|
|
11745
|
+
return this.evaluateFreeform(preparedContext, graderProvider);
|
|
11746
|
+
}
|
|
11747
|
+
async prepareContext(context) {
|
|
11748
|
+
const config = context.evaluator;
|
|
11749
|
+
if (config?.type !== "llm-grader" || !context.output) {
|
|
11750
|
+
return context;
|
|
11751
|
+
}
|
|
11752
|
+
const lastAssistant = [...context.output].reverse().find((message) => message.role === "assistant" && message.content !== void 0);
|
|
11753
|
+
if (!lastAssistant || typeof lastAssistant.content === "string") {
|
|
11754
|
+
return context;
|
|
11500
11755
|
}
|
|
11501
|
-
|
|
11756
|
+
const extracted = await extractTextWithPreprocessors(
|
|
11757
|
+
lastAssistant.content,
|
|
11758
|
+
config.preprocessors,
|
|
11759
|
+
{
|
|
11760
|
+
basePath: resolveContentBasePath(context)
|
|
11761
|
+
}
|
|
11762
|
+
);
|
|
11763
|
+
return {
|
|
11764
|
+
...context,
|
|
11765
|
+
candidate: appendPreprocessingWarnings(extracted.text, extracted.warnings)
|
|
11766
|
+
};
|
|
11502
11767
|
}
|
|
11503
11768
|
// ---------------------------------------------------------------------------
|
|
11504
11769
|
// LLM mode (existing)
|
|
@@ -12383,8 +12648,8 @@ function toAiSdkImageParts(images) {
|
|
|
12383
12648
|
}));
|
|
12384
12649
|
}
|
|
12385
12650
|
function resolveSandboxed(basePath, relativePath) {
|
|
12386
|
-
const resolved =
|
|
12387
|
-
if (!resolved.startsWith(basePath +
|
|
12651
|
+
const resolved = path36.resolve(basePath, relativePath);
|
|
12652
|
+
if (!resolved.startsWith(basePath + path36.sep) && resolved !== basePath) {
|
|
12388
12653
|
throw new Error(`Path '${relativePath}' is outside the workspace`);
|
|
12389
12654
|
}
|
|
12390
12655
|
return resolved;
|
|
@@ -12474,11 +12739,11 @@ async function searchDirectory(dirPath, workspacePath, regex, matches) {
|
|
|
12474
12739
|
for (const entry of entries) {
|
|
12475
12740
|
if (matches.length >= MAX_SEARCH_MATCHES) return;
|
|
12476
12741
|
if (SEARCH_SKIP_DIRS.has(entry.name)) continue;
|
|
12477
|
-
const fullPath =
|
|
12742
|
+
const fullPath = path36.join(dirPath, entry.name);
|
|
12478
12743
|
if (entry.isDirectory()) {
|
|
12479
12744
|
await searchDirectory(fullPath, workspacePath, regex, matches);
|
|
12480
12745
|
} else if (entry.isFile()) {
|
|
12481
|
-
const ext =
|
|
12746
|
+
const ext = path36.extname(entry.name).toLowerCase();
|
|
12482
12747
|
if (BINARY_EXTENSIONS.has(ext)) continue;
|
|
12483
12748
|
try {
|
|
12484
12749
|
const stat11 = await fs2.stat(fullPath);
|
|
@@ -12490,7 +12755,7 @@ async function searchDirectory(dirPath, workspacePath, regex, matches) {
|
|
|
12490
12755
|
regex.lastIndex = 0;
|
|
12491
12756
|
if (regex.test(lines[i])) {
|
|
12492
12757
|
matches.push({
|
|
12493
|
-
file:
|
|
12758
|
+
file: path36.relative(workspacePath, fullPath),
|
|
12494
12759
|
line: i + 1,
|
|
12495
12760
|
text: lines[i].substring(0, 200)
|
|
12496
12761
|
});
|
|
@@ -13123,115 +13388,115 @@ var FieldAccuracyEvaluator = class {
|
|
|
13123
13388
|
* Evaluate a single field against the expected value.
|
|
13124
13389
|
*/
|
|
13125
13390
|
evaluateField(fieldConfig, candidateData, expectedData) {
|
|
13126
|
-
const { path:
|
|
13127
|
-
const candidateValue = resolvePath(candidateData,
|
|
13128
|
-
const expectedValue = resolvePath(expectedData,
|
|
13391
|
+
const { path: path52, match, required = true, weight = 1 } = fieldConfig;
|
|
13392
|
+
const candidateValue = resolvePath(candidateData, path52);
|
|
13393
|
+
const expectedValue = resolvePath(expectedData, path52);
|
|
13129
13394
|
if (expectedValue === void 0) {
|
|
13130
13395
|
return {
|
|
13131
|
-
path:
|
|
13396
|
+
path: path52,
|
|
13132
13397
|
score: 1,
|
|
13133
13398
|
// No expected value means no comparison needed
|
|
13134
13399
|
weight,
|
|
13135
13400
|
hit: true,
|
|
13136
|
-
message: `${
|
|
13401
|
+
message: `${path52}: no expected value`
|
|
13137
13402
|
};
|
|
13138
13403
|
}
|
|
13139
13404
|
if (candidateValue === void 0) {
|
|
13140
13405
|
if (required) {
|
|
13141
13406
|
return {
|
|
13142
|
-
path:
|
|
13407
|
+
path: path52,
|
|
13143
13408
|
score: 0,
|
|
13144
13409
|
weight,
|
|
13145
13410
|
hit: false,
|
|
13146
|
-
message: `${
|
|
13411
|
+
message: `${path52} (required, missing)`
|
|
13147
13412
|
};
|
|
13148
13413
|
}
|
|
13149
13414
|
return {
|
|
13150
|
-
path:
|
|
13415
|
+
path: path52,
|
|
13151
13416
|
score: 1,
|
|
13152
13417
|
// Don't penalize missing optional fields
|
|
13153
13418
|
weight: 0,
|
|
13154
13419
|
// Zero weight means it won't affect the score
|
|
13155
13420
|
hit: true,
|
|
13156
|
-
message: `${
|
|
13421
|
+
message: `${path52}: optional field missing`
|
|
13157
13422
|
};
|
|
13158
13423
|
}
|
|
13159
13424
|
switch (match) {
|
|
13160
13425
|
case "exact":
|
|
13161
|
-
return this.compareExact(
|
|
13426
|
+
return this.compareExact(path52, candidateValue, expectedValue, weight);
|
|
13162
13427
|
case "numeric_tolerance":
|
|
13163
13428
|
return this.compareNumericTolerance(
|
|
13164
|
-
|
|
13429
|
+
path52,
|
|
13165
13430
|
candidateValue,
|
|
13166
13431
|
expectedValue,
|
|
13167
13432
|
fieldConfig,
|
|
13168
13433
|
weight
|
|
13169
13434
|
);
|
|
13170
13435
|
case "date":
|
|
13171
|
-
return this.compareDate(
|
|
13436
|
+
return this.compareDate(path52, candidateValue, expectedValue, fieldConfig, weight);
|
|
13172
13437
|
default:
|
|
13173
13438
|
return {
|
|
13174
|
-
path:
|
|
13439
|
+
path: path52,
|
|
13175
13440
|
score: 0,
|
|
13176
13441
|
weight,
|
|
13177
13442
|
hit: false,
|
|
13178
|
-
message: `${
|
|
13443
|
+
message: `${path52}: unknown match type "${match}"`
|
|
13179
13444
|
};
|
|
13180
13445
|
}
|
|
13181
13446
|
}
|
|
13182
13447
|
/**
|
|
13183
13448
|
* Exact equality comparison.
|
|
13184
13449
|
*/
|
|
13185
|
-
compareExact(
|
|
13450
|
+
compareExact(path52, candidateValue, expectedValue, weight) {
|
|
13186
13451
|
if (deepEqual(candidateValue, expectedValue)) {
|
|
13187
13452
|
return {
|
|
13188
|
-
path:
|
|
13453
|
+
path: path52,
|
|
13189
13454
|
score: 1,
|
|
13190
13455
|
weight,
|
|
13191
13456
|
hit: true,
|
|
13192
|
-
message:
|
|
13457
|
+
message: path52
|
|
13193
13458
|
};
|
|
13194
13459
|
}
|
|
13195
13460
|
if (typeof candidateValue !== typeof expectedValue) {
|
|
13196
13461
|
return {
|
|
13197
|
-
path:
|
|
13462
|
+
path: path52,
|
|
13198
13463
|
score: 0,
|
|
13199
13464
|
weight,
|
|
13200
13465
|
hit: false,
|
|
13201
|
-
message: `${
|
|
13466
|
+
message: `${path52} (type mismatch: got ${typeof candidateValue}, expected ${typeof expectedValue})`
|
|
13202
13467
|
};
|
|
13203
13468
|
}
|
|
13204
13469
|
return {
|
|
13205
|
-
path:
|
|
13470
|
+
path: path52,
|
|
13206
13471
|
score: 0,
|
|
13207
13472
|
weight,
|
|
13208
13473
|
hit: false,
|
|
13209
|
-
message: `${
|
|
13474
|
+
message: `${path52} (value mismatch)`
|
|
13210
13475
|
};
|
|
13211
13476
|
}
|
|
13212
13477
|
/**
|
|
13213
13478
|
* Numeric comparison with absolute or relative tolerance.
|
|
13214
13479
|
*/
|
|
13215
|
-
compareNumericTolerance(
|
|
13480
|
+
compareNumericTolerance(path52, candidateValue, expectedValue, fieldConfig, weight) {
|
|
13216
13481
|
const { tolerance = 0, relative = false } = fieldConfig;
|
|
13217
13482
|
const candidateNum = toNumber(candidateValue);
|
|
13218
13483
|
const expectedNum = toNumber(expectedValue);
|
|
13219
13484
|
if (candidateNum === null || expectedNum === null) {
|
|
13220
13485
|
return {
|
|
13221
|
-
path:
|
|
13486
|
+
path: path52,
|
|
13222
13487
|
score: 0,
|
|
13223
13488
|
weight,
|
|
13224
13489
|
hit: false,
|
|
13225
|
-
message: `${
|
|
13490
|
+
message: `${path52} (non-numeric value)`
|
|
13226
13491
|
};
|
|
13227
13492
|
}
|
|
13228
13493
|
if (!Number.isFinite(candidateNum) || !Number.isFinite(expectedNum)) {
|
|
13229
13494
|
return {
|
|
13230
|
-
path:
|
|
13495
|
+
path: path52,
|
|
13231
13496
|
score: 0,
|
|
13232
13497
|
weight,
|
|
13233
13498
|
hit: false,
|
|
13234
|
-
message: `${
|
|
13499
|
+
message: `${path52} (invalid numeric value)`
|
|
13235
13500
|
};
|
|
13236
13501
|
}
|
|
13237
13502
|
const diff = Math.abs(candidateNum - expectedNum);
|
|
@@ -13244,61 +13509,61 @@ var FieldAccuracyEvaluator = class {
|
|
|
13244
13509
|
}
|
|
13245
13510
|
if (withinTolerance) {
|
|
13246
13511
|
return {
|
|
13247
|
-
path:
|
|
13512
|
+
path: path52,
|
|
13248
13513
|
score: 1,
|
|
13249
13514
|
weight,
|
|
13250
13515
|
hit: true,
|
|
13251
|
-
message: `${
|
|
13516
|
+
message: `${path52} (within tolerance: diff=${diff.toFixed(2)})`
|
|
13252
13517
|
};
|
|
13253
13518
|
}
|
|
13254
13519
|
return {
|
|
13255
|
-
path:
|
|
13520
|
+
path: path52,
|
|
13256
13521
|
score: 0,
|
|
13257
13522
|
weight,
|
|
13258
13523
|
hit: false,
|
|
13259
|
-
message: `${
|
|
13524
|
+
message: `${path52} (outside tolerance: diff=${diff.toFixed(2)}, tolerance=${tolerance})`
|
|
13260
13525
|
};
|
|
13261
13526
|
}
|
|
13262
13527
|
/**
|
|
13263
13528
|
* Date comparison with format normalization.
|
|
13264
13529
|
*/
|
|
13265
|
-
compareDate(
|
|
13530
|
+
compareDate(path52, candidateValue, expectedValue, fieldConfig, weight) {
|
|
13266
13531
|
const formats = fieldConfig.formats ?? DEFAULT_DATE_FORMATS;
|
|
13267
13532
|
const candidateDate = parseDate(String(candidateValue), formats);
|
|
13268
13533
|
const expectedDate = parseDate(String(expectedValue), formats);
|
|
13269
13534
|
if (candidateDate === null) {
|
|
13270
13535
|
return {
|
|
13271
|
-
path:
|
|
13536
|
+
path: path52,
|
|
13272
13537
|
score: 0,
|
|
13273
13538
|
weight,
|
|
13274
13539
|
hit: false,
|
|
13275
|
-
message: `${
|
|
13540
|
+
message: `${path52} (unparseable candidate date)`
|
|
13276
13541
|
};
|
|
13277
13542
|
}
|
|
13278
13543
|
if (expectedDate === null) {
|
|
13279
13544
|
return {
|
|
13280
|
-
path:
|
|
13545
|
+
path: path52,
|
|
13281
13546
|
score: 0,
|
|
13282
13547
|
weight,
|
|
13283
13548
|
hit: false,
|
|
13284
|
-
message: `${
|
|
13549
|
+
message: `${path52} (unparseable expected date)`
|
|
13285
13550
|
};
|
|
13286
13551
|
}
|
|
13287
13552
|
if (candidateDate.getFullYear() === expectedDate.getFullYear() && candidateDate.getMonth() === expectedDate.getMonth() && candidateDate.getDate() === expectedDate.getDate()) {
|
|
13288
13553
|
return {
|
|
13289
|
-
path:
|
|
13554
|
+
path: path52,
|
|
13290
13555
|
score: 1,
|
|
13291
13556
|
weight,
|
|
13292
13557
|
hit: true,
|
|
13293
|
-
message:
|
|
13558
|
+
message: path52
|
|
13294
13559
|
};
|
|
13295
13560
|
}
|
|
13296
13561
|
return {
|
|
13297
|
-
path:
|
|
13562
|
+
path: path52,
|
|
13298
13563
|
score: 0,
|
|
13299
13564
|
weight,
|
|
13300
13565
|
hit: false,
|
|
13301
|
-
message: `${
|
|
13566
|
+
message: `${path52} (date mismatch: got ${formatDateISO(candidateDate)}, expected ${formatDateISO(expectedDate)})`
|
|
13302
13567
|
};
|
|
13303
13568
|
}
|
|
13304
13569
|
/**
|
|
@@ -13331,11 +13596,11 @@ var FieldAccuracyEvaluator = class {
|
|
|
13331
13596
|
};
|
|
13332
13597
|
}
|
|
13333
13598
|
};
|
|
13334
|
-
function resolvePath(obj,
|
|
13335
|
-
if (!
|
|
13599
|
+
function resolvePath(obj, path52) {
|
|
13600
|
+
if (!path52 || !obj) {
|
|
13336
13601
|
return void 0;
|
|
13337
13602
|
}
|
|
13338
|
-
const parts =
|
|
13603
|
+
const parts = path52.split(/\.|\[|\]/).filter((p) => p.length > 0);
|
|
13339
13604
|
let current = obj;
|
|
13340
13605
|
for (const part of parts) {
|
|
13341
13606
|
if (current === null || current === void 0) {
|
|
@@ -13827,8 +14092,8 @@ var TokenUsageEvaluator = class {
|
|
|
13827
14092
|
};
|
|
13828
14093
|
|
|
13829
14094
|
// src/evaluation/evaluators/tool-trajectory.ts
|
|
13830
|
-
function getNestedValue(obj,
|
|
13831
|
-
const parts =
|
|
14095
|
+
function getNestedValue(obj, path52) {
|
|
14096
|
+
const parts = path52.split(".");
|
|
13832
14097
|
let current = obj;
|
|
13833
14098
|
for (const part of parts) {
|
|
13834
14099
|
if (current === null || current === void 0 || typeof current !== "object") {
|
|
@@ -14451,7 +14716,7 @@ function runEqualsAssertion(output, value) {
|
|
|
14451
14716
|
import { createHash as createHash2, randomUUID as randomUUID9 } from "node:crypto";
|
|
14452
14717
|
import { existsSync as existsSync5 } from "node:fs";
|
|
14453
14718
|
import { copyFile as copyFile2, mkdir as mkdir14, readdir as readdir7, stat as stat8 } from "node:fs/promises";
|
|
14454
|
-
import
|
|
14719
|
+
import path45 from "node:path";
|
|
14455
14720
|
import micromatch3 from "micromatch";
|
|
14456
14721
|
|
|
14457
14722
|
// ../../node_modules/.bun/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
|
|
@@ -14665,7 +14930,7 @@ var InlineAssertEvaluator = class {
|
|
|
14665
14930
|
};
|
|
14666
14931
|
|
|
14667
14932
|
// src/evaluation/evaluators/prompt-resolution.ts
|
|
14668
|
-
import
|
|
14933
|
+
import path37 from "node:path";
|
|
14669
14934
|
async function resolveCustomPrompt(promptConfig, context, timeoutMs) {
|
|
14670
14935
|
if (promptConfig.resolvedPromptScript && promptConfig.resolvedPromptScript.length > 0) {
|
|
14671
14936
|
if (!context) {
|
|
@@ -14708,7 +14973,7 @@ async function executePromptTemplate(script, context, config, timeoutMs) {
|
|
|
14708
14973
|
};
|
|
14709
14974
|
const inputJson = JSON.stringify(toSnakeCaseDeep(payload), null, 2);
|
|
14710
14975
|
const scriptPath = script[script.length - 1];
|
|
14711
|
-
const cwd =
|
|
14976
|
+
const cwd = path37.dirname(scriptPath);
|
|
14712
14977
|
try {
|
|
14713
14978
|
const stdout = await executeScript(script, inputJson, timeoutMs, cwd);
|
|
14714
14979
|
const prompt = stdout.trim();
|
|
@@ -14980,16 +15245,16 @@ function createBuiltinRegistry() {
|
|
|
14980
15245
|
}
|
|
14981
15246
|
|
|
14982
15247
|
// src/evaluation/registry/assertion-discovery.ts
|
|
14983
|
-
import
|
|
15248
|
+
import path38 from "node:path";
|
|
14984
15249
|
import fg2 from "fast-glob";
|
|
14985
15250
|
async function discoverAssertions(registry, baseDir) {
|
|
14986
15251
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
14987
15252
|
const candidateDirs = [];
|
|
14988
|
-
let dir =
|
|
14989
|
-
const root =
|
|
15253
|
+
let dir = path38.resolve(baseDir);
|
|
15254
|
+
const root = path38.parse(dir).root;
|
|
14990
15255
|
while (dir !== root) {
|
|
14991
|
-
candidateDirs.push(
|
|
14992
|
-
dir =
|
|
15256
|
+
candidateDirs.push(path38.join(dir, ".agentv", "assertions"));
|
|
15257
|
+
dir = path38.dirname(dir);
|
|
14993
15258
|
}
|
|
14994
15259
|
let files = [];
|
|
14995
15260
|
for (const assertionsDir of candidateDirs) {
|
|
@@ -15005,7 +15270,7 @@ async function discoverAssertions(registry, baseDir) {
|
|
|
15005
15270
|
}
|
|
15006
15271
|
const discoveredTypes = [];
|
|
15007
15272
|
for (const filePath of files) {
|
|
15008
|
-
const basename =
|
|
15273
|
+
const basename = path38.basename(filePath);
|
|
15009
15274
|
const typeName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
15010
15275
|
if (registry.has(typeName)) {
|
|
15011
15276
|
continue;
|
|
@@ -15023,17 +15288,17 @@ async function discoverAssertions(registry, baseDir) {
|
|
|
15023
15288
|
}
|
|
15024
15289
|
|
|
15025
15290
|
// src/evaluation/registry/grader-discovery.ts
|
|
15026
|
-
import
|
|
15291
|
+
import path39 from "node:path";
|
|
15027
15292
|
import fg3 from "fast-glob";
|
|
15028
15293
|
async function discoverGraders(registry, baseDir) {
|
|
15029
15294
|
const patterns = ["*.ts", "*.js", "*.mts", "*.mjs"];
|
|
15030
15295
|
const candidateDirs = [];
|
|
15031
|
-
let dir =
|
|
15032
|
-
const root =
|
|
15296
|
+
let dir = path39.resolve(baseDir);
|
|
15297
|
+
const root = path39.parse(dir).root;
|
|
15033
15298
|
while (dir !== root) {
|
|
15034
|
-
candidateDirs.push(
|
|
15035
|
-
candidateDirs.push(
|
|
15036
|
-
dir =
|
|
15299
|
+
candidateDirs.push(path39.join(dir, ".agentv", "graders"));
|
|
15300
|
+
candidateDirs.push(path39.join(dir, ".agentv", "judges"));
|
|
15301
|
+
dir = path39.dirname(dir);
|
|
15037
15302
|
}
|
|
15038
15303
|
let files = [];
|
|
15039
15304
|
for (const gradersDir of candidateDirs) {
|
|
@@ -15049,7 +15314,7 @@ async function discoverGraders(registry, baseDir) {
|
|
|
15049
15314
|
}
|
|
15050
15315
|
const discoveredTypes = [];
|
|
15051
15316
|
for (const filePath of files) {
|
|
15052
|
-
const basename =
|
|
15317
|
+
const basename = path39.basename(filePath);
|
|
15053
15318
|
const typeName = basename.replace(/\.(ts|js|mts|mjs)$/, "");
|
|
15054
15319
|
if (registry.has(typeName)) {
|
|
15055
15320
|
continue;
|
|
@@ -15209,7 +15474,7 @@ function getTCritical(df) {
|
|
|
15209
15474
|
// src/evaluation/workspace/file-changes.ts
|
|
15210
15475
|
import { exec as execCallback } from "node:child_process";
|
|
15211
15476
|
import { readdirSync as readdirSync2, statSync } from "node:fs";
|
|
15212
|
-
import
|
|
15477
|
+
import path40 from "node:path";
|
|
15213
15478
|
import { promisify as promisify4 } from "node:util";
|
|
15214
15479
|
var execAsync4 = promisify4(execCallback);
|
|
15215
15480
|
function gitExecOpts(workspacePath) {
|
|
@@ -15243,10 +15508,10 @@ async function stageNestedRepoChanges(workspacePath) {
|
|
|
15243
15508
|
}
|
|
15244
15509
|
for (const entry of entries) {
|
|
15245
15510
|
if (entry === ".git" || entry === "node_modules") continue;
|
|
15246
|
-
const childPath =
|
|
15511
|
+
const childPath = path40.join(workspacePath, entry);
|
|
15247
15512
|
try {
|
|
15248
15513
|
if (!statSync(childPath).isDirectory()) continue;
|
|
15249
|
-
if (!statSync(
|
|
15514
|
+
if (!statSync(path40.join(childPath, ".git")).isDirectory()) continue;
|
|
15250
15515
|
} catch {
|
|
15251
15516
|
continue;
|
|
15252
15517
|
}
|
|
@@ -15257,7 +15522,7 @@ async function stageNestedRepoChanges(workspacePath) {
|
|
|
15257
15522
|
|
|
15258
15523
|
// src/evaluation/workspace/manager.ts
|
|
15259
15524
|
import { cp, mkdir as mkdir12, readdir as readdir4, rm as rm4, stat as stat6 } from "node:fs/promises";
|
|
15260
|
-
import
|
|
15525
|
+
import path41 from "node:path";
|
|
15261
15526
|
var TemplateNotFoundError = class extends Error {
|
|
15262
15527
|
constructor(templatePath) {
|
|
15263
15528
|
super(`Workspace template not found: ${templatePath}`);
|
|
@@ -15287,14 +15552,14 @@ async function isDirectory(filePath) {
|
|
|
15287
15552
|
}
|
|
15288
15553
|
function getWorkspacePath(evalRunId, caseId, workspaceRoot) {
|
|
15289
15554
|
const root = workspaceRoot ?? getWorkspacesRoot();
|
|
15290
|
-
return
|
|
15555
|
+
return path41.join(root, evalRunId, caseId);
|
|
15291
15556
|
}
|
|
15292
15557
|
async function copyDirectoryRecursive(src, dest) {
|
|
15293
15558
|
await mkdir12(dest, { recursive: true });
|
|
15294
15559
|
const entries = await readdir4(src, { withFileTypes: true });
|
|
15295
15560
|
for (const entry of entries) {
|
|
15296
|
-
const srcPath =
|
|
15297
|
-
const destPath =
|
|
15561
|
+
const srcPath = path41.join(src, entry.name);
|
|
15562
|
+
const destPath = path41.join(dest, entry.name);
|
|
15298
15563
|
if (entry.name === ".git") {
|
|
15299
15564
|
continue;
|
|
15300
15565
|
}
|
|
@@ -15306,7 +15571,7 @@ async function copyDirectoryRecursive(src, dest) {
|
|
|
15306
15571
|
}
|
|
15307
15572
|
}
|
|
15308
15573
|
async function createTempWorkspace(templatePath, evalRunId, caseId, workspaceRoot) {
|
|
15309
|
-
const resolvedTemplatePath =
|
|
15574
|
+
const resolvedTemplatePath = path41.resolve(templatePath);
|
|
15310
15575
|
if (!await fileExists(resolvedTemplatePath)) {
|
|
15311
15576
|
throw new TemplateNotFoundError(resolvedTemplatePath);
|
|
15312
15577
|
}
|
|
@@ -15355,7 +15620,7 @@ async function cleanupWorkspace(workspacePath) {
|
|
|
15355
15620
|
}
|
|
15356
15621
|
async function cleanupEvalWorkspaces(evalRunId, workspaceRoot) {
|
|
15357
15622
|
const root = workspaceRoot ?? getWorkspacesRoot();
|
|
15358
|
-
const evalDir =
|
|
15623
|
+
const evalDir = path41.join(root, evalRunId);
|
|
15359
15624
|
if (await fileExists(evalDir)) {
|
|
15360
15625
|
await rm4(evalDir, { recursive: true, force: true });
|
|
15361
15626
|
}
|
|
@@ -15365,8 +15630,8 @@ async function cleanupEvalWorkspaces(evalRunId, workspaceRoot) {
|
|
|
15365
15630
|
import { execFile } from "node:child_process";
|
|
15366
15631
|
import { createHash } from "node:crypto";
|
|
15367
15632
|
import { existsSync as existsSync3 } from "node:fs";
|
|
15368
|
-
import { cp as cp2, mkdir as mkdir13, readFile as
|
|
15369
|
-
import
|
|
15633
|
+
import { cp as cp2, mkdir as mkdir13, readFile as readFile13, readdir as readdir5, rm as rm5, unlink, writeFile as writeFile7 } from "node:fs/promises";
|
|
15634
|
+
import path42 from "node:path";
|
|
15370
15635
|
import { promisify as promisify5 } from "node:util";
|
|
15371
15636
|
var execFileAsync = promisify5(execFile);
|
|
15372
15637
|
function gitEnv() {
|
|
@@ -15420,8 +15685,8 @@ async function copyDirectoryRecursive2(src, dest, skipDirs) {
|
|
|
15420
15685
|
await mkdir13(dest, { recursive: true });
|
|
15421
15686
|
const entries = await readdir5(src, { withFileTypes: true });
|
|
15422
15687
|
for (const entry of entries) {
|
|
15423
|
-
const srcPath =
|
|
15424
|
-
const destPath =
|
|
15688
|
+
const srcPath = path42.join(src, entry.name);
|
|
15689
|
+
const destPath = path42.join(dest, entry.name);
|
|
15425
15690
|
if (entry.name === ".git") {
|
|
15426
15691
|
continue;
|
|
15427
15692
|
}
|
|
@@ -15454,7 +15719,7 @@ var WorkspacePoolManager = class {
|
|
|
15454
15719
|
async acquireWorkspace(options) {
|
|
15455
15720
|
const { templatePath, repos, maxSlots, repoManager, poolReset } = options;
|
|
15456
15721
|
const fingerprint = computeWorkspaceFingerprint(repos);
|
|
15457
|
-
const poolDir =
|
|
15722
|
+
const poolDir = path42.join(this.poolRoot, fingerprint);
|
|
15458
15723
|
await mkdir13(poolDir, { recursive: true });
|
|
15459
15724
|
const drifted = await this.checkDrift(poolDir, fingerprint);
|
|
15460
15725
|
if (drifted) {
|
|
@@ -15464,7 +15729,7 @@ var WorkspacePoolManager = class {
|
|
|
15464
15729
|
await this.removeAllSlots(poolDir);
|
|
15465
15730
|
}
|
|
15466
15731
|
for (let i = 0; i < maxSlots; i++) {
|
|
15467
|
-
const slotPath =
|
|
15732
|
+
const slotPath = path42.join(poolDir, `slot-${i}`);
|
|
15468
15733
|
const lockPath = `${slotPath}.lock`;
|
|
15469
15734
|
const locked = await this.tryLock(lockPath);
|
|
15470
15735
|
if (!locked) {
|
|
@@ -15526,7 +15791,7 @@ var WorkspacePoolManager = class {
|
|
|
15526
15791
|
throw err;
|
|
15527
15792
|
}
|
|
15528
15793
|
try {
|
|
15529
|
-
const pidStr = await
|
|
15794
|
+
const pidStr = await readFile13(lockPath, "utf-8");
|
|
15530
15795
|
const pid = Number.parseInt(pidStr.trim(), 10);
|
|
15531
15796
|
if (!Number.isNaN(pid)) {
|
|
15532
15797
|
try {
|
|
@@ -15551,9 +15816,9 @@ var WorkspacePoolManager = class {
|
|
|
15551
15816
|
* Returns false (no drift) if metadata.json doesn't exist (first use).
|
|
15552
15817
|
*/
|
|
15553
15818
|
async checkDrift(poolDir, fingerprint) {
|
|
15554
|
-
const metadataPath =
|
|
15819
|
+
const metadataPath = path42.join(poolDir, "metadata.json");
|
|
15555
15820
|
try {
|
|
15556
|
-
const raw = await
|
|
15821
|
+
const raw = await readFile13(metadataPath, "utf-8");
|
|
15557
15822
|
const metadata = JSON.parse(raw);
|
|
15558
15823
|
return metadata.fingerprint !== fingerprint;
|
|
15559
15824
|
} catch {
|
|
@@ -15568,17 +15833,17 @@ var WorkspacePoolManager = class {
|
|
|
15568
15833
|
repos,
|
|
15569
15834
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15570
15835
|
};
|
|
15571
|
-
await writeFile7(
|
|
15836
|
+
await writeFile7(path42.join(poolDir, "metadata.json"), JSON.stringify(metadata, null, 2));
|
|
15572
15837
|
}
|
|
15573
15838
|
/** Remove all slot directories and their lock files from a pool directory. */
|
|
15574
15839
|
async removeAllSlots(poolDir) {
|
|
15575
15840
|
const entries = await readdir5(poolDir);
|
|
15576
15841
|
for (const entry of entries) {
|
|
15577
15842
|
if (entry.startsWith("slot-") && !entry.endsWith(".lock")) {
|
|
15578
|
-
const lockPath =
|
|
15843
|
+
const lockPath = path42.join(poolDir, `${entry}.lock`);
|
|
15579
15844
|
if (existsSync3(lockPath)) {
|
|
15580
15845
|
try {
|
|
15581
|
-
const pidStr = await
|
|
15846
|
+
const pidStr = await readFile13(lockPath, "utf-8");
|
|
15582
15847
|
const pid = Number.parseInt(pidStr.trim(), 10);
|
|
15583
15848
|
if (!Number.isNaN(pid)) {
|
|
15584
15849
|
try {
|
|
@@ -15591,12 +15856,12 @@ var WorkspacePoolManager = class {
|
|
|
15591
15856
|
} catch {
|
|
15592
15857
|
}
|
|
15593
15858
|
}
|
|
15594
|
-
await rm5(
|
|
15859
|
+
await rm5(path42.join(poolDir, entry), { recursive: true, force: true });
|
|
15595
15860
|
await rm5(lockPath, { force: true }).catch(() => {
|
|
15596
15861
|
});
|
|
15597
15862
|
}
|
|
15598
15863
|
}
|
|
15599
|
-
await rm5(
|
|
15864
|
+
await rm5(path42.join(poolDir, "metadata.json"), { force: true }).catch(() => {
|
|
15600
15865
|
});
|
|
15601
15866
|
}
|
|
15602
15867
|
/**
|
|
@@ -15606,7 +15871,7 @@ var WorkspacePoolManager = class {
|
|
|
15606
15871
|
*/
|
|
15607
15872
|
async resetSlot(slotPath, templatePath, repos, poolReset = "fast") {
|
|
15608
15873
|
for (const repo of repos) {
|
|
15609
|
-
const repoDir =
|
|
15874
|
+
const repoDir = path42.join(slotPath, repo.path);
|
|
15610
15875
|
if (!existsSync3(repoDir)) {
|
|
15611
15876
|
continue;
|
|
15612
15877
|
}
|
|
@@ -15643,7 +15908,7 @@ var WorkspacePoolManager = class {
|
|
|
15643
15908
|
// src/evaluation/workspace/repo-manager.ts
|
|
15644
15909
|
import { execFile as execFile2 } from "node:child_process";
|
|
15645
15910
|
import { existsSync as existsSync4 } from "node:fs";
|
|
15646
|
-
import
|
|
15911
|
+
import path43 from "node:path";
|
|
15647
15912
|
import { promisify as promisify6 } from "node:util";
|
|
15648
15913
|
var execFileAsync2 = promisify6(execFile2);
|
|
15649
15914
|
var DEFAULT_TIMEOUT_MS2 = 3e5;
|
|
@@ -15743,7 +16008,7 @@ ${lines.join("\n")}`;
|
|
|
15743
16008
|
* Handles checkout, ref resolution, ancestor walking, shallow clone, sparse checkout.
|
|
15744
16009
|
*/
|
|
15745
16010
|
async materialize(repo, workspacePath) {
|
|
15746
|
-
const targetDir =
|
|
16011
|
+
const targetDir = path43.join(workspacePath, repo.path);
|
|
15747
16012
|
const sourceUrl = getSourceUrl(repo.source);
|
|
15748
16013
|
const startedAt = Date.now();
|
|
15749
16014
|
if (this.verbose) {
|
|
@@ -15834,7 +16099,7 @@ ${lines.join("\n")}`;
|
|
|
15834
16099
|
async reset(repos, workspacePath, reset) {
|
|
15835
16100
|
const cleanFlag = reset === "strict" ? "-fdx" : "-fd";
|
|
15836
16101
|
for (const repo of repos) {
|
|
15837
|
-
const targetDir =
|
|
16102
|
+
const targetDir = path43.join(workspacePath, repo.path);
|
|
15838
16103
|
await this.runGit(["reset", "--hard", "HEAD"], { cwd: targetDir });
|
|
15839
16104
|
await this.runGit(["clean", cleanFlag], { cwd: targetDir });
|
|
15840
16105
|
}
|
|
@@ -15843,16 +16108,16 @@ ${lines.join("\n")}`;
|
|
|
15843
16108
|
|
|
15844
16109
|
// src/evaluation/workspace/resolve.ts
|
|
15845
16110
|
import { readdir as readdir6, stat as stat7 } from "node:fs/promises";
|
|
15846
|
-
import
|
|
16111
|
+
import path44 from "node:path";
|
|
15847
16112
|
async function resolveWorkspaceTemplate(templatePath) {
|
|
15848
16113
|
if (!templatePath) {
|
|
15849
16114
|
return void 0;
|
|
15850
16115
|
}
|
|
15851
|
-
const resolved =
|
|
16116
|
+
const resolved = path44.resolve(templatePath);
|
|
15852
16117
|
const stats = await stat7(resolved);
|
|
15853
16118
|
if (stats.isFile()) {
|
|
15854
16119
|
return {
|
|
15855
|
-
dir:
|
|
16120
|
+
dir: path44.dirname(resolved),
|
|
15856
16121
|
workspaceFile: resolved
|
|
15857
16122
|
};
|
|
15858
16123
|
}
|
|
@@ -15864,14 +16129,14 @@ async function resolveWorkspaceTemplate(templatePath) {
|
|
|
15864
16129
|
if (workspaceFiles.length === 1) {
|
|
15865
16130
|
return {
|
|
15866
16131
|
dir: resolved,
|
|
15867
|
-
workspaceFile:
|
|
16132
|
+
workspaceFile: path44.join(resolved, workspaceFiles[0])
|
|
15868
16133
|
};
|
|
15869
16134
|
}
|
|
15870
16135
|
if (workspaceFiles.length > 1) {
|
|
15871
16136
|
const conventionFile = workspaceFiles.find((f) => f === "template.code-workspace");
|
|
15872
16137
|
return {
|
|
15873
16138
|
dir: resolved,
|
|
15874
|
-
workspaceFile: conventionFile ?
|
|
16139
|
+
workspaceFile: conventionFile ? path44.join(resolved, conventionFile) : void 0
|
|
15875
16140
|
};
|
|
15876
16141
|
}
|
|
15877
16142
|
return { dir: resolved };
|
|
@@ -16090,7 +16355,7 @@ async function runEvaluation(options) {
|
|
|
16090
16355
|
];
|
|
16091
16356
|
const evaluatorRegistry = buildEvaluatorRegistry(evaluators, resolveGraderProvider);
|
|
16092
16357
|
const typeRegistry = createBuiltinRegistry();
|
|
16093
|
-
const discoveryBaseDir = evalFilePath ?
|
|
16358
|
+
const discoveryBaseDir = evalFilePath ? path45.dirname(path45.resolve(evalFilePath)) : process.cwd();
|
|
16094
16359
|
const evalDir = discoveryBaseDir;
|
|
16095
16360
|
await discoverAssertions(typeRegistry, discoveryBaseDir);
|
|
16096
16361
|
await discoverGraders(typeRegistry, discoveryBaseDir);
|
|
@@ -16288,7 +16553,7 @@ async function runEvaluation(options) {
|
|
|
16288
16553
|
}
|
|
16289
16554
|
try {
|
|
16290
16555
|
if (suiteWorkspaceFile && sharedWorkspacePath) {
|
|
16291
|
-
const copiedWorkspaceFile =
|
|
16556
|
+
const copiedWorkspaceFile = path45.join(sharedWorkspacePath, path45.basename(suiteWorkspaceFile));
|
|
16292
16557
|
try {
|
|
16293
16558
|
await stat8(copiedWorkspaceFile);
|
|
16294
16559
|
suiteWorkspaceFile = copiedWorkspaceFile;
|
|
@@ -16303,7 +16568,7 @@ async function runEvaluation(options) {
|
|
|
16303
16568
|
try {
|
|
16304
16569
|
if (needsPerRepoCheck) {
|
|
16305
16570
|
for (const repo of suiteWorkspace.repos) {
|
|
16306
|
-
const targetDir =
|
|
16571
|
+
const targetDir = path45.join(sharedWorkspacePath, repo.path);
|
|
16307
16572
|
if (existsSync5(targetDir)) {
|
|
16308
16573
|
setupLog(`reusing existing repo at: ${targetDir}`);
|
|
16309
16574
|
continue;
|
|
@@ -16890,7 +17155,7 @@ async function runEvalCase(options) {
|
|
|
16890
17155
|
);
|
|
16891
17156
|
}
|
|
16892
17157
|
if (caseWorkspaceFile && workspacePath) {
|
|
16893
|
-
const copiedFile =
|
|
17158
|
+
const copiedFile = path45.join(workspacePath, path45.basename(caseWorkspaceFile));
|
|
16894
17159
|
try {
|
|
16895
17160
|
await stat8(copiedFile);
|
|
16896
17161
|
caseWorkspaceFile = copiedFile;
|
|
@@ -16952,10 +17217,10 @@ async function runEvalCase(options) {
|
|
|
16952
17217
|
const files = evalCase.metadata.agent_skills_files;
|
|
16953
17218
|
if (baseDir && files.length > 0) {
|
|
16954
17219
|
for (const relPath of files) {
|
|
16955
|
-
const srcPath =
|
|
16956
|
-
const destPath =
|
|
17220
|
+
const srcPath = path45.resolve(baseDir, relPath);
|
|
17221
|
+
const destPath = path45.resolve(workspacePath, relPath);
|
|
16957
17222
|
try {
|
|
16958
|
-
await mkdir14(
|
|
17223
|
+
await mkdir14(path45.dirname(destPath), { recursive: true });
|
|
16959
17224
|
await copyFile2(srcPath, destPath);
|
|
16960
17225
|
} catch (error) {
|
|
16961
17226
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -17551,6 +17816,7 @@ async function runEvaluatorsForCase(options) {
|
|
|
17551
17816
|
if (!activeEvaluator) {
|
|
17552
17817
|
throw new Error(`No evaluator registered for kind '${evaluatorKind}'`);
|
|
17553
17818
|
}
|
|
17819
|
+
const implicitEvaluator = evaluatorKind === "llm-grader" && !evalCase.assertions ? buildImplicitLlmGraderConfig(evalCase) : void 0;
|
|
17554
17820
|
const score = await activeEvaluator.evaluate({
|
|
17555
17821
|
evalCase,
|
|
17556
17822
|
candidate,
|
|
@@ -17570,10 +17836,21 @@ async function runEvaluatorsForCase(options) {
|
|
|
17570
17836
|
targetResolver,
|
|
17571
17837
|
availableTargets,
|
|
17572
17838
|
fileChanges,
|
|
17573
|
-
workspacePath
|
|
17839
|
+
workspacePath,
|
|
17840
|
+
...implicitEvaluator ? { evaluator: implicitEvaluator } : {}
|
|
17574
17841
|
});
|
|
17575
17842
|
return { score };
|
|
17576
17843
|
}
|
|
17844
|
+
function buildImplicitLlmGraderConfig(evalCase) {
|
|
17845
|
+
if (!evalCase.preprocessors || evalCase.preprocessors.length === 0) {
|
|
17846
|
+
return void 0;
|
|
17847
|
+
}
|
|
17848
|
+
return {
|
|
17849
|
+
name: "llm-grader",
|
|
17850
|
+
type: "llm-grader",
|
|
17851
|
+
preprocessors: evalCase.preprocessors
|
|
17852
|
+
};
|
|
17853
|
+
}
|
|
17577
17854
|
async function runEvaluatorList(options) {
|
|
17578
17855
|
const {
|
|
17579
17856
|
evalCase,
|
|
@@ -17623,7 +17900,7 @@ async function runEvaluatorList(options) {
|
|
|
17623
17900
|
fileChanges,
|
|
17624
17901
|
workspacePath
|
|
17625
17902
|
};
|
|
17626
|
-
const evalFileDir = evalCase.file_paths[0] ?
|
|
17903
|
+
const evalFileDir = evalCase.file_paths[0] ? path45.dirname(evalCase.file_paths[0]) : process.cwd();
|
|
17627
17904
|
const dispatchContext = {
|
|
17628
17905
|
graderProvider,
|
|
17629
17906
|
targetResolver,
|
|
@@ -17991,7 +18268,7 @@ function computeWeightedMean(entries) {
|
|
|
17991
18268
|
|
|
17992
18269
|
// src/evaluation/evaluate.ts
|
|
17993
18270
|
import { existsSync as existsSync6 } from "node:fs";
|
|
17994
|
-
import
|
|
18271
|
+
import path46 from "node:path";
|
|
17995
18272
|
|
|
17996
18273
|
// src/evaluation/providers/function-provider.ts
|
|
17997
18274
|
function createFunctionProvider(taskFn) {
|
|
@@ -18028,7 +18305,7 @@ async function evaluate(config) {
|
|
|
18028
18305
|
}
|
|
18029
18306
|
const gitRoot = await findGitRoot(process.cwd());
|
|
18030
18307
|
const repoRoot = gitRoot ?? process.cwd();
|
|
18031
|
-
const testFilePath = config.specFile ?
|
|
18308
|
+
const testFilePath = config.specFile ? path46.resolve(config.specFile) : path46.join(process.cwd(), "__programmatic__.yaml");
|
|
18032
18309
|
await loadEnvHierarchy(repoRoot, testFilePath);
|
|
18033
18310
|
let resolvedTarget;
|
|
18034
18311
|
let taskProvider;
|
|
@@ -18143,10 +18420,10 @@ function computeSummary(results, durationMs, threshold = DEFAULT_THRESHOLD) {
|
|
|
18143
18420
|
var TARGET_FILE_CANDIDATES = [".agentv/targets.yaml", ".agentv/targets.yml"];
|
|
18144
18421
|
async function discoverDefaultTarget(repoRoot) {
|
|
18145
18422
|
const cwd = process.cwd();
|
|
18146
|
-
const chain = buildDirectoryChain(
|
|
18423
|
+
const chain = buildDirectoryChain(path46.join(cwd, "_placeholder"), repoRoot);
|
|
18147
18424
|
for (const dir of chain) {
|
|
18148
18425
|
for (const candidate of TARGET_FILE_CANDIDATES) {
|
|
18149
|
-
const targetsPath =
|
|
18426
|
+
const targetsPath = path46.join(dir, candidate);
|
|
18150
18427
|
if (!existsSync6(targetsPath)) continue;
|
|
18151
18428
|
try {
|
|
18152
18429
|
const definitions = await readTargetDefinitions(targetsPath);
|
|
@@ -18163,7 +18440,7 @@ async function loadEnvHierarchy(repoRoot, startPath) {
|
|
|
18163
18440
|
const chain = buildDirectoryChain(startPath, repoRoot);
|
|
18164
18441
|
const envFiles = [];
|
|
18165
18442
|
for (const dir of chain) {
|
|
18166
|
-
const envPath =
|
|
18443
|
+
const envPath = path46.join(dir, ".env");
|
|
18167
18444
|
if (existsSync6(envPath)) envFiles.push(envPath);
|
|
18168
18445
|
}
|
|
18169
18446
|
for (let i = 0; i < envFiles.length; i++) {
|
|
@@ -18342,8 +18619,8 @@ function buildPrompt(criteria, question, referenceAnswer) {
|
|
|
18342
18619
|
}
|
|
18343
18620
|
|
|
18344
18621
|
// src/evaluation/workspace/deps-scanner.ts
|
|
18345
|
-
import { readFile as
|
|
18346
|
-
import
|
|
18622
|
+
import { readFile as readFile14 } from "node:fs/promises";
|
|
18623
|
+
import path47 from "node:path";
|
|
18347
18624
|
import { parse as parse5 } from "yaml";
|
|
18348
18625
|
function normalizeGitUrl(url) {
|
|
18349
18626
|
let normalized = url.replace(/\.git$/, "");
|
|
@@ -18390,11 +18667,11 @@ async function scanRepoDeps(evalFilePaths) {
|
|
|
18390
18667
|
return { repos: [...seen.values()], errors };
|
|
18391
18668
|
}
|
|
18392
18669
|
async function extractReposFromEvalFile(filePath) {
|
|
18393
|
-
const content = await
|
|
18670
|
+
const content = await readFile14(filePath, "utf8");
|
|
18394
18671
|
const parsed = interpolateEnv(parse5(content), process.env);
|
|
18395
18672
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
|
|
18396
18673
|
const obj = parsed;
|
|
18397
|
-
const evalFileDir =
|
|
18674
|
+
const evalFileDir = path47.dirname(path47.resolve(filePath));
|
|
18398
18675
|
const repos = [];
|
|
18399
18676
|
const suiteRepos = await extractReposFromWorkspaceRaw(obj.workspace, evalFileDir);
|
|
18400
18677
|
repos.push(...suiteRepos);
|
|
@@ -18410,8 +18687,8 @@ async function extractReposFromEvalFile(filePath) {
|
|
|
18410
18687
|
}
|
|
18411
18688
|
async function extractReposFromWorkspaceRaw(raw, evalFileDir) {
|
|
18412
18689
|
if (typeof raw === "string") {
|
|
18413
|
-
const workspaceFilePath =
|
|
18414
|
-
const content = await
|
|
18690
|
+
const workspaceFilePath = path47.resolve(evalFileDir, raw);
|
|
18691
|
+
const content = await readFile14(workspaceFilePath, "utf8");
|
|
18415
18692
|
const parsed = interpolateEnv(parse5(content), process.env);
|
|
18416
18693
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
|
|
18417
18694
|
return extractReposFromObject(parsed);
|
|
@@ -18439,8 +18716,8 @@ function extractReposFromObject(obj) {
|
|
|
18439
18716
|
}
|
|
18440
18717
|
|
|
18441
18718
|
// src/evaluation/cache/response-cache.ts
|
|
18442
|
-
import { mkdir as mkdir15, readFile as
|
|
18443
|
-
import
|
|
18719
|
+
import { mkdir as mkdir15, readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
|
|
18720
|
+
import path48 from "node:path";
|
|
18444
18721
|
var DEFAULT_CACHE_PATH = ".agentv/cache";
|
|
18445
18722
|
var ResponseCache = class {
|
|
18446
18723
|
cachePath;
|
|
@@ -18450,7 +18727,7 @@ var ResponseCache = class {
|
|
|
18450
18727
|
async get(key) {
|
|
18451
18728
|
const filePath = this.keyToPath(key);
|
|
18452
18729
|
try {
|
|
18453
|
-
const data = await
|
|
18730
|
+
const data = await readFile15(filePath, "utf8");
|
|
18454
18731
|
return JSON.parse(data);
|
|
18455
18732
|
} catch {
|
|
18456
18733
|
return void 0;
|
|
@@ -18458,13 +18735,13 @@ var ResponseCache = class {
|
|
|
18458
18735
|
}
|
|
18459
18736
|
async set(key, value) {
|
|
18460
18737
|
const filePath = this.keyToPath(key);
|
|
18461
|
-
const dir =
|
|
18738
|
+
const dir = path48.dirname(filePath);
|
|
18462
18739
|
await mkdir15(dir, { recursive: true });
|
|
18463
18740
|
await writeFile8(filePath, JSON.stringify(value, null, 2), "utf8");
|
|
18464
18741
|
}
|
|
18465
18742
|
keyToPath(key) {
|
|
18466
18743
|
const prefix = key.slice(0, 2);
|
|
18467
|
-
return
|
|
18744
|
+
return path48.join(this.cachePath, prefix, `${key}.json`);
|
|
18468
18745
|
}
|
|
18469
18746
|
};
|
|
18470
18747
|
function shouldEnableCache(params) {
|
|
@@ -18481,10 +18758,10 @@ function shouldSkipCacheForTemperature(targetConfig) {
|
|
|
18481
18758
|
|
|
18482
18759
|
// src/projects.ts
|
|
18483
18760
|
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2, writeFileSync } from "node:fs";
|
|
18484
|
-
import
|
|
18761
|
+
import path49 from "node:path";
|
|
18485
18762
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
18486
18763
|
function getProjectsRegistryPath() {
|
|
18487
|
-
return
|
|
18764
|
+
return path49.join(getAgentvHome(), "projects.yaml");
|
|
18488
18765
|
}
|
|
18489
18766
|
function loadProjectRegistry() {
|
|
18490
18767
|
const registryPath = getProjectsRegistryPath();
|
|
@@ -18504,14 +18781,14 @@ function loadProjectRegistry() {
|
|
|
18504
18781
|
}
|
|
18505
18782
|
function saveProjectRegistry(registry) {
|
|
18506
18783
|
const registryPath = getProjectsRegistryPath();
|
|
18507
|
-
const dir =
|
|
18784
|
+
const dir = path49.dirname(registryPath);
|
|
18508
18785
|
if (!existsSync7(dir)) {
|
|
18509
18786
|
mkdirSync2(dir, { recursive: true });
|
|
18510
18787
|
}
|
|
18511
18788
|
writeFileSync(registryPath, stringifyYaml(registry), "utf-8");
|
|
18512
18789
|
}
|
|
18513
18790
|
function deriveProjectId(dirPath, existingIds) {
|
|
18514
|
-
const base =
|
|
18791
|
+
const base = path49.basename(dirPath).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
18515
18792
|
let candidate = base || "project";
|
|
18516
18793
|
let suffix = 2;
|
|
18517
18794
|
while (existingIds.includes(candidate)) {
|
|
@@ -18521,11 +18798,11 @@ function deriveProjectId(dirPath, existingIds) {
|
|
|
18521
18798
|
return candidate;
|
|
18522
18799
|
}
|
|
18523
18800
|
function addProject(projectPath) {
|
|
18524
|
-
const absPath =
|
|
18801
|
+
const absPath = path49.resolve(projectPath);
|
|
18525
18802
|
if (!existsSync7(absPath)) {
|
|
18526
18803
|
throw new Error(`Directory not found: ${absPath}`);
|
|
18527
18804
|
}
|
|
18528
|
-
if (!existsSync7(
|
|
18805
|
+
if (!existsSync7(path49.join(absPath, ".agentv"))) {
|
|
18529
18806
|
throw new Error(`No .agentv/ directory found in ${absPath}. Run an evaluation first.`);
|
|
18530
18807
|
}
|
|
18531
18808
|
const registry = loadProjectRegistry();
|
|
@@ -18539,7 +18816,7 @@ function addProject(projectPath) {
|
|
|
18539
18816
|
absPath,
|
|
18540
18817
|
registry.projects.map((p) => p.id)
|
|
18541
18818
|
),
|
|
18542
|
-
name:
|
|
18819
|
+
name: path49.basename(absPath),
|
|
18543
18820
|
path: absPath,
|
|
18544
18821
|
addedAt: now,
|
|
18545
18822
|
lastOpenedAt: now
|
|
@@ -18568,14 +18845,14 @@ function touchProject(projectId) {
|
|
|
18568
18845
|
}
|
|
18569
18846
|
}
|
|
18570
18847
|
function discoverProjects(rootDir, maxDepth = 2) {
|
|
18571
|
-
const absRoot =
|
|
18848
|
+
const absRoot = path49.resolve(rootDir);
|
|
18572
18849
|
if (!existsSync7(absRoot) || !statSync2(absRoot).isDirectory()) {
|
|
18573
18850
|
return [];
|
|
18574
18851
|
}
|
|
18575
18852
|
const results = [];
|
|
18576
18853
|
function scan(dir, depth) {
|
|
18577
18854
|
if (depth > maxDepth) return;
|
|
18578
|
-
if (existsSync7(
|
|
18855
|
+
if (existsSync7(path49.join(dir, ".agentv"))) {
|
|
18579
18856
|
results.push(dir);
|
|
18580
18857
|
return;
|
|
18581
18858
|
}
|
|
@@ -18585,7 +18862,7 @@ function discoverProjects(rootDir, maxDepth = 2) {
|
|
|
18585
18862
|
for (const entry of entries) {
|
|
18586
18863
|
if (!entry.isDirectory()) continue;
|
|
18587
18864
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
18588
|
-
scan(
|
|
18865
|
+
scan(path49.join(dir, entry.name), depth + 1);
|
|
18589
18866
|
}
|
|
18590
18867
|
} catch {
|
|
18591
18868
|
}
|
|
@@ -19498,8 +19775,8 @@ function extractResponseItemContent(content) {
|
|
|
19498
19775
|
// src/import/codex-session-discovery.ts
|
|
19499
19776
|
import { readdir as readdir8, stat as stat9 } from "node:fs/promises";
|
|
19500
19777
|
import { homedir as homedir3 } from "node:os";
|
|
19501
|
-
import
|
|
19502
|
-
var DEFAULT_SESSIONS_DIR = () =>
|
|
19778
|
+
import path50 from "node:path";
|
|
19779
|
+
var DEFAULT_SESSIONS_DIR = () => path50.join(homedir3(), ".codex", "sessions");
|
|
19503
19780
|
async function discoverCodexSessions(opts) {
|
|
19504
19781
|
const sessionsDir = opts?.sessionsDir ?? DEFAULT_SESSIONS_DIR();
|
|
19505
19782
|
const limit = opts?.latest ? 1 : opts?.limit ?? 10;
|
|
@@ -19511,7 +19788,7 @@ async function discoverCodexSessions(opts) {
|
|
|
19511
19788
|
return [];
|
|
19512
19789
|
}
|
|
19513
19790
|
for (const year of yearDirs) {
|
|
19514
|
-
const yearPath =
|
|
19791
|
+
const yearPath = path50.join(sessionsDir, year);
|
|
19515
19792
|
let monthDirs;
|
|
19516
19793
|
try {
|
|
19517
19794
|
monthDirs = await readdir8(yearPath);
|
|
@@ -19519,7 +19796,7 @@ async function discoverCodexSessions(opts) {
|
|
|
19519
19796
|
continue;
|
|
19520
19797
|
}
|
|
19521
19798
|
for (const month of monthDirs) {
|
|
19522
|
-
const monthPath =
|
|
19799
|
+
const monthPath = path50.join(yearPath, month);
|
|
19523
19800
|
let dayDirs;
|
|
19524
19801
|
try {
|
|
19525
19802
|
dayDirs = await readdir8(monthPath);
|
|
@@ -19531,7 +19808,7 @@ async function discoverCodexSessions(opts) {
|
|
|
19531
19808
|
const dirDate = `${year}-${month}-${day}`;
|
|
19532
19809
|
if (dirDate !== opts.date) continue;
|
|
19533
19810
|
}
|
|
19534
|
-
const dayPath =
|
|
19811
|
+
const dayPath = path50.join(monthPath, day);
|
|
19535
19812
|
let files;
|
|
19536
19813
|
try {
|
|
19537
19814
|
files = await readdir8(dayPath);
|
|
@@ -19540,7 +19817,7 @@ async function discoverCodexSessions(opts) {
|
|
|
19540
19817
|
}
|
|
19541
19818
|
for (const file of files) {
|
|
19542
19819
|
if (!file.startsWith("rollout-") || !file.endsWith(".jsonl")) continue;
|
|
19543
|
-
const filePath =
|
|
19820
|
+
const filePath = path50.join(dayPath, file);
|
|
19544
19821
|
const nameWithoutExt = file.replace(/\.jsonl$/, "");
|
|
19545
19822
|
const parts = nameWithoutExt.split("-");
|
|
19546
19823
|
const sessionId = parts.length >= 6 ? parts.slice(-5).join("-") : nameWithoutExt;
|
|
@@ -19563,8 +19840,8 @@ async function discoverCodexSessions(opts) {
|
|
|
19563
19840
|
// src/import/session-discovery.ts
|
|
19564
19841
|
import { readdir as readdir9, stat as stat10 } from "node:fs/promises";
|
|
19565
19842
|
import { homedir as homedir4 } from "node:os";
|
|
19566
|
-
import
|
|
19567
|
-
var DEFAULT_PROJECTS_DIR = () =>
|
|
19843
|
+
import path51 from "node:path";
|
|
19844
|
+
var DEFAULT_PROJECTS_DIR = () => path51.join(homedir4(), ".claude", "projects");
|
|
19568
19845
|
function encodeProjectPath(projectPath) {
|
|
19569
19846
|
return projectPath.replace(/\//g, "-");
|
|
19570
19847
|
}
|
|
@@ -19583,7 +19860,7 @@ async function discoverClaudeSessions(opts) {
|
|
|
19583
19860
|
}
|
|
19584
19861
|
const sessions = [];
|
|
19585
19862
|
for (const projectDir of projectDirs) {
|
|
19586
|
-
const dirPath =
|
|
19863
|
+
const dirPath = path51.join(projectsDir, projectDir);
|
|
19587
19864
|
let entries;
|
|
19588
19865
|
try {
|
|
19589
19866
|
entries = await readdir9(dirPath);
|
|
@@ -19594,7 +19871,7 @@ async function discoverClaudeSessions(opts) {
|
|
|
19594
19871
|
if (!entry.endsWith(".jsonl")) continue;
|
|
19595
19872
|
const sessionId = entry.replace(/\.jsonl$/, "");
|
|
19596
19873
|
if (opts?.sessionId && sessionId !== opts.sessionId) continue;
|
|
19597
|
-
const filePath =
|
|
19874
|
+
const filePath = path51.join(dirPath, entry);
|
|
19598
19875
|
let updatedAt;
|
|
19599
19876
|
try {
|
|
19600
19877
|
const fileStat = await stat10(filePath);
|
|
@@ -19615,7 +19892,7 @@ async function discoverClaudeSessions(opts) {
|
|
|
19615
19892
|
}
|
|
19616
19893
|
|
|
19617
19894
|
// src/import/types.ts
|
|
19618
|
-
import { readFile as
|
|
19895
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
19619
19896
|
function toTranscriptJsonLine(entry) {
|
|
19620
19897
|
const firstUserMessage = entry.messages.find((m) => m.role === "user");
|
|
19621
19898
|
const input = typeof firstUserMessage?.content === "string" ? firstUserMessage.content : "";
|
|
@@ -19641,11 +19918,11 @@ function toTranscriptJsonLine(entry) {
|
|
|
19641
19918
|
};
|
|
19642
19919
|
}
|
|
19643
19920
|
async function readTranscriptJsonl(filePath) {
|
|
19644
|
-
const text = await
|
|
19921
|
+
const text = await readFile16(filePath, "utf8");
|
|
19645
19922
|
return text.split("\n").filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
|
|
19646
19923
|
}
|
|
19647
19924
|
async function readTranscriptFile(filePath) {
|
|
19648
|
-
return
|
|
19925
|
+
return readFile16(filePath, "utf8");
|
|
19649
19926
|
}
|
|
19650
19927
|
|
|
19651
19928
|
// src/import/transcript-provider.ts
|