agentv 0.5.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -142
- package/dist/{chunk-THVRLL37.js → chunk-5WBKOCCW.js} +1493 -1169
- package/dist/chunk-5WBKOCCW.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/.env.template +35 -0
- package/dist/templates/agentv/.env.template +23 -0
- package/dist/templates/agentv/config.yaml +15 -0
- package/dist/templates/agentv/targets.yaml +74 -0
- package/dist/templates/{eval-build.prompt.md → github/prompts/eval-build.prompt.md} +1 -0
- package/package.json +4 -3
- package/dist/chunk-THVRLL37.js.map +0 -1
- /package/dist/templates/{config-schema.json → github/contexts/config-schema.json} +0 -0
- /package/dist/templates/{eval-schema.json → github/contexts/eval-schema.json} +0 -0
|
@@ -5039,6 +5039,14 @@ var ba = new Error("Agent definition is the prompt you give to the LLM for the a
|
|
|
5039
5039
|
import { exec as execWithCallback } from "node:child_process";
|
|
5040
5040
|
import path22 from "node:path";
|
|
5041
5041
|
import { promisify as promisify2 } from "node:util";
|
|
5042
|
+
import { exec as execCallback, spawn as spawn2 } from "node:child_process";
|
|
5043
|
+
import { randomUUID } from "node:crypto";
|
|
5044
|
+
import { constants as constants22, createWriteStream } from "node:fs";
|
|
5045
|
+
import { access as access22, copyFile as copyFile2, mkdtemp, mkdir as mkdir3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
5046
|
+
import { tmpdir } from "node:os";
|
|
5047
|
+
import path42 from "node:path";
|
|
5048
|
+
import { promisify as promisify22 } from "node:util";
|
|
5049
|
+
import path32 from "node:path";
|
|
5042
5050
|
|
|
5043
5051
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
5044
5052
|
var external_exports = {};
|
|
@@ -9083,7 +9091,7 @@ var NEVER = INVALID;
|
|
|
9083
9091
|
|
|
9084
9092
|
// ../../packages/core/dist/index.js
|
|
9085
9093
|
import { readFile as readFile22 } from "node:fs/promises";
|
|
9086
|
-
import
|
|
9094
|
+
import path52 from "node:path";
|
|
9087
9095
|
|
|
9088
9096
|
// ../../node_modules/.pnpm/subagent@0.4.6/node_modules/subagent/dist/vscode/agentDispatch.js
|
|
9089
9097
|
import { exec, spawn } from "child_process";
|
|
@@ -11021,19 +11029,12 @@ async function provisionSubagents(options) {
|
|
|
11021
11029
|
}
|
|
11022
11030
|
|
|
11023
11031
|
// ../../packages/core/dist/index.js
|
|
11024
|
-
import { exec as execCallback, spawn as spawn2 } from "node:child_process";
|
|
11025
|
-
import { constants as constants22 } from "node:fs";
|
|
11026
|
-
import { access as access22, copyFile as copyFile2, mkdtemp, mkdir as mkdir3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
11027
|
-
import { tmpdir } from "node:os";
|
|
11028
|
-
import path52 from "node:path";
|
|
11029
|
-
import { promisify as promisify22 } from "node:util";
|
|
11030
|
-
import path42 from "node:path";
|
|
11031
11032
|
import { constants as constants32 } from "node:fs";
|
|
11032
11033
|
import { access as access32, readFile as readFile3 } from "node:fs/promises";
|
|
11033
11034
|
import path62 from "node:path";
|
|
11034
11035
|
import { parse as parse22 } from "yaml";
|
|
11035
|
-
import { randomUUID } from "node:crypto";
|
|
11036
|
-
import { createHash, randomUUID as
|
|
11036
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11037
|
+
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
11037
11038
|
import { mkdir as mkdir22, readFile as readFile4, writeFile as writeFile22 } from "node:fs/promises";
|
|
11038
11039
|
import path72 from "node:path";
|
|
11039
11040
|
var TEST_MESSAGE_ROLE_VALUES = ["system", "user", "assistant", "tool"];
|
|
@@ -11960,1301 +11961,1558 @@ function formatTimeoutSuffix(timeoutMs) {
|
|
|
11960
11961
|
const seconds = Math.ceil(timeoutMs / 1e3);
|
|
11961
11962
|
return ` after ${seconds}s`;
|
|
11962
11963
|
}
|
|
11963
|
-
|
|
11964
|
-
|
|
11964
|
+
function buildPromptDocument(request, inputFiles, options) {
|
|
11965
|
+
const parts = [];
|
|
11966
|
+
const guidelineFiles = collectGuidelineFiles(
|
|
11967
|
+
inputFiles,
|
|
11968
|
+
options?.guidelinePatterns ?? request.guideline_patterns,
|
|
11969
|
+
options?.guidelineOverrides
|
|
11970
|
+
);
|
|
11971
|
+
const inputFilesList = collectInputFiles(inputFiles);
|
|
11972
|
+
const nonGuidelineInputFiles = inputFilesList.filter(
|
|
11973
|
+
(file) => !guidelineFiles.includes(file)
|
|
11974
|
+
);
|
|
11975
|
+
const prereadBlock = buildMandatoryPrereadBlock(guidelineFiles, nonGuidelineInputFiles);
|
|
11976
|
+
if (prereadBlock.length > 0) {
|
|
11977
|
+
parts.push("\n", prereadBlock);
|
|
11978
|
+
}
|
|
11979
|
+
parts.push("\n[[ ## user_query ## ]]\n", request.prompt.trim());
|
|
11980
|
+
return parts.join("\n").trim();
|
|
11981
|
+
}
|
|
11982
|
+
function normalizeInputFiles2(inputFiles) {
|
|
11983
|
+
if (!inputFiles || inputFiles.length === 0) {
|
|
11984
|
+
return void 0;
|
|
11985
|
+
}
|
|
11986
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
11987
|
+
for (const inputFile of inputFiles) {
|
|
11988
|
+
const absolutePath = path32.resolve(inputFile);
|
|
11989
|
+
if (!deduped.has(absolutePath)) {
|
|
11990
|
+
deduped.set(absolutePath, absolutePath);
|
|
11991
|
+
}
|
|
11992
|
+
}
|
|
11993
|
+
return Array.from(deduped.values());
|
|
11994
|
+
}
|
|
11995
|
+
function collectGuidelineFiles(inputFiles, guidelinePatterns, overrides) {
|
|
11996
|
+
if (!inputFiles || inputFiles.length === 0) {
|
|
11997
|
+
return [];
|
|
11998
|
+
}
|
|
11999
|
+
const unique = /* @__PURE__ */ new Map();
|
|
12000
|
+
for (const inputFile of inputFiles) {
|
|
12001
|
+
const absolutePath = path32.resolve(inputFile);
|
|
12002
|
+
if (overrides?.has(absolutePath)) {
|
|
12003
|
+
if (!unique.has(absolutePath)) {
|
|
12004
|
+
unique.set(absolutePath, absolutePath);
|
|
12005
|
+
}
|
|
12006
|
+
continue;
|
|
12007
|
+
}
|
|
12008
|
+
const normalized = absolutePath.split(path32.sep).join("/");
|
|
12009
|
+
if (isGuidelineFile(normalized, guidelinePatterns)) {
|
|
12010
|
+
if (!unique.has(absolutePath)) {
|
|
12011
|
+
unique.set(absolutePath, absolutePath);
|
|
12012
|
+
}
|
|
12013
|
+
}
|
|
12014
|
+
}
|
|
12015
|
+
return Array.from(unique.values());
|
|
12016
|
+
}
|
|
12017
|
+
function collectInputFiles(inputFiles) {
|
|
12018
|
+
if (!inputFiles || inputFiles.length === 0) {
|
|
12019
|
+
return [];
|
|
12020
|
+
}
|
|
12021
|
+
const unique = /* @__PURE__ */ new Map();
|
|
12022
|
+
for (const inputFile of inputFiles) {
|
|
12023
|
+
const absolutePath = path32.resolve(inputFile);
|
|
12024
|
+
if (!unique.has(absolutePath)) {
|
|
12025
|
+
unique.set(absolutePath, absolutePath);
|
|
12026
|
+
}
|
|
12027
|
+
}
|
|
12028
|
+
return Array.from(unique.values());
|
|
12029
|
+
}
|
|
12030
|
+
function buildMandatoryPrereadBlock(guidelineFiles, inputFiles) {
|
|
12031
|
+
if (guidelineFiles.length === 0 && inputFiles.length === 0) {
|
|
12032
|
+
return "";
|
|
12033
|
+
}
|
|
12034
|
+
const buildList = (files) => files.map((absolutePath) => {
|
|
12035
|
+
const fileName = path32.basename(absolutePath);
|
|
12036
|
+
const fileUri = pathToFileUri2(absolutePath);
|
|
12037
|
+
return `* [${fileName}](${fileUri})`;
|
|
12038
|
+
});
|
|
12039
|
+
const sections = [];
|
|
12040
|
+
if (guidelineFiles.length > 0) {
|
|
12041
|
+
sections.push(`Read all guideline files:
|
|
12042
|
+
${buildList(guidelineFiles).join("\n")}.`);
|
|
12043
|
+
}
|
|
12044
|
+
if (inputFiles.length > 0) {
|
|
12045
|
+
sections.push(`Read all input files:
|
|
12046
|
+
${buildList(inputFiles).join("\n")}.`);
|
|
12047
|
+
}
|
|
12048
|
+
sections.push(
|
|
12049
|
+
"If any file is missing, fail with ERROR: missing-file <filename> and stop.",
|
|
12050
|
+
"Then apply system_instructions on the user query below."
|
|
12051
|
+
);
|
|
12052
|
+
return sections.join("\n");
|
|
12053
|
+
}
|
|
12054
|
+
function pathToFileUri2(filePath) {
|
|
12055
|
+
const absolutePath = path32.isAbsolute(filePath) ? filePath : path32.resolve(filePath);
|
|
12056
|
+
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
12057
|
+
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
12058
|
+
return `file:///${normalizedPath}`;
|
|
12059
|
+
}
|
|
12060
|
+
return `file://${normalizedPath}`;
|
|
12061
|
+
}
|
|
12062
|
+
var execAsync22 = promisify22(execCallback);
|
|
12063
|
+
var WORKSPACE_PREFIX = "agentv-codex-";
|
|
12064
|
+
var PROMPT_FILENAME = "prompt.md";
|
|
12065
|
+
var FILES_DIR = "files";
|
|
12066
|
+
var JSONL_TYPE_ITEM_COMPLETED = "item.completed";
|
|
12067
|
+
var CodexProvider = class {
|
|
11965
12068
|
id;
|
|
11966
|
-
kind = "
|
|
12069
|
+
kind = "codex";
|
|
11967
12070
|
targetName;
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
12071
|
+
supportsBatch = false;
|
|
12072
|
+
config;
|
|
12073
|
+
runCodex;
|
|
12074
|
+
environmentCheck;
|
|
12075
|
+
resolvedExecutable;
|
|
12076
|
+
constructor(targetName, config, runner = defaultCodexRunner) {
|
|
12077
|
+
this.id = `codex:${targetName}`;
|
|
11974
12078
|
this.targetName = targetName;
|
|
11975
|
-
this.
|
|
11976
|
-
this.
|
|
11977
|
-
this.delayMinMs = config.delayMinMs ?? 0;
|
|
11978
|
-
this.delayMaxMs = config.delayMaxMs ?? 0;
|
|
12079
|
+
this.config = config;
|
|
12080
|
+
this.runCodex = runner;
|
|
11979
12081
|
}
|
|
11980
12082
|
async invoke(request) {
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
12083
|
+
if (request.signal?.aborted) {
|
|
12084
|
+
throw new Error("Codex provider request was aborted before execution");
|
|
11984
12085
|
}
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
|
|
11989
|
-
|
|
12086
|
+
await this.ensureEnvironmentReady();
|
|
12087
|
+
const inputFiles = normalizeInputFiles2(request.inputFiles);
|
|
12088
|
+
const originalGuidelines = new Set(
|
|
12089
|
+
collectGuidelineFiles(inputFiles, request.guideline_patterns).map((file) => path42.resolve(file))
|
|
12090
|
+
);
|
|
12091
|
+
const workspaceRoot = await this.createWorkspace();
|
|
12092
|
+
const logger = await this.createStreamLogger(request).catch(() => void 0);
|
|
12093
|
+
try {
|
|
12094
|
+
const { mirroredInputFiles, guidelineMirrors } = await this.mirrorInputFiles(
|
|
12095
|
+
inputFiles,
|
|
12096
|
+
workspaceRoot,
|
|
12097
|
+
originalGuidelines
|
|
12098
|
+
);
|
|
12099
|
+
const promptContent = buildPromptDocument(request, mirroredInputFiles, {
|
|
12100
|
+
guidelinePatterns: request.guideline_patterns,
|
|
12101
|
+
guidelineOverrides: guidelineMirrors
|
|
12102
|
+
});
|
|
12103
|
+
const promptFile = path42.join(workspaceRoot, PROMPT_FILENAME);
|
|
12104
|
+
await writeFile3(promptFile, promptContent, "utf8");
|
|
12105
|
+
const args = this.buildCodexArgs();
|
|
12106
|
+
const cwd = this.resolveCwd(workspaceRoot);
|
|
12107
|
+
const result = await this.executeCodex(args, cwd, promptContent, request.signal, logger);
|
|
12108
|
+
if (result.timedOut) {
|
|
12109
|
+
throw new Error(
|
|
12110
|
+
`Codex CLI timed out${formatTimeoutSuffix2(this.config.timeoutMs ?? void 0)}`
|
|
12111
|
+
);
|
|
11990
12112
|
}
|
|
11991
|
-
|
|
12113
|
+
if (result.exitCode !== 0) {
|
|
12114
|
+
const detail = pickDetail(result.stderr, result.stdout);
|
|
12115
|
+
const prefix = `Codex CLI exited with code ${result.exitCode}`;
|
|
12116
|
+
throw new Error(detail ? `${prefix}: ${detail}` : prefix);
|
|
12117
|
+
}
|
|
12118
|
+
const parsed = parseCodexJson(result.stdout);
|
|
12119
|
+
const assistantText = extractAssistantText(parsed);
|
|
12120
|
+
return {
|
|
12121
|
+
text: assistantText,
|
|
12122
|
+
raw: {
|
|
12123
|
+
response: parsed,
|
|
12124
|
+
stdout: result.stdout,
|
|
12125
|
+
stderr: result.stderr,
|
|
12126
|
+
exitCode: result.exitCode,
|
|
12127
|
+
args,
|
|
12128
|
+
executable: this.resolvedExecutable ?? this.config.executable,
|
|
12129
|
+
promptFile,
|
|
12130
|
+
workspace: workspaceRoot,
|
|
12131
|
+
inputFiles: mirroredInputFiles,
|
|
12132
|
+
logFile: logger?.filePath
|
|
12133
|
+
}
|
|
12134
|
+
};
|
|
12135
|
+
} finally {
|
|
12136
|
+
await logger?.close();
|
|
12137
|
+
await this.cleanupWorkspace(workspaceRoot);
|
|
12138
|
+
}
|
|
11992
12139
|
}
|
|
11993
|
-
|
|
11994
|
-
if (this.
|
|
11995
|
-
|
|
11996
|
-
const max = Math.max(min, this.delayMaxMs);
|
|
11997
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
12140
|
+
async ensureEnvironmentReady() {
|
|
12141
|
+
if (!this.environmentCheck) {
|
|
12142
|
+
this.environmentCheck = this.validateEnvironment();
|
|
11998
12143
|
}
|
|
11999
|
-
|
|
12144
|
+
await this.environmentCheck;
|
|
12000
12145
|
}
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
var BASE_TARGET_SCHEMA = external_exports.object({
|
|
12004
|
-
name: external_exports.string().min(1, "target name is required"),
|
|
12005
|
-
provider: external_exports.string().min(1, "provider is required"),
|
|
12006
|
-
settings: external_exports.record(external_exports.unknown()).optional(),
|
|
12007
|
-
judge_target: external_exports.string().optional(),
|
|
12008
|
-
workers: external_exports.number().int().min(1).optional()
|
|
12009
|
-
});
|
|
12010
|
-
var DEFAULT_AZURE_API_VERSION = "2024-10-01-preview";
|
|
12011
|
-
function normalizeAzureApiVersion(value) {
|
|
12012
|
-
if (!value) {
|
|
12013
|
-
return DEFAULT_AZURE_API_VERSION;
|
|
12146
|
+
async validateEnvironment() {
|
|
12147
|
+
this.resolvedExecutable = await locateExecutable(this.config.executable);
|
|
12014
12148
|
}
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12149
|
+
resolveCwd(workspaceRoot) {
|
|
12150
|
+
if (!this.config.cwd) {
|
|
12151
|
+
return workspaceRoot;
|
|
12152
|
+
}
|
|
12153
|
+
return path42.resolve(this.config.cwd);
|
|
12018
12154
|
}
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
)
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
kind: "gemini",
|
|
12053
|
-
name: parsed.name,
|
|
12054
|
-
judgeTarget: parsed.judge_target,
|
|
12055
|
-
workers: parsed.workers,
|
|
12056
|
-
providerBatching,
|
|
12057
|
-
config: resolveGeminiConfig(parsed, env)
|
|
12058
|
-
};
|
|
12059
|
-
case "codex":
|
|
12060
|
-
case "codex-cli":
|
|
12061
|
-
return {
|
|
12062
|
-
kind: "codex",
|
|
12063
|
-
name: parsed.name,
|
|
12064
|
-
judgeTarget: parsed.judge_target,
|
|
12065
|
-
workers: parsed.workers,
|
|
12066
|
-
providerBatching,
|
|
12067
|
-
config: resolveCodexConfig(parsed, env)
|
|
12068
|
-
};
|
|
12069
|
-
case "mock":
|
|
12070
|
-
return {
|
|
12071
|
-
kind: "mock",
|
|
12072
|
-
name: parsed.name,
|
|
12073
|
-
judgeTarget: parsed.judge_target,
|
|
12074
|
-
workers: parsed.workers,
|
|
12075
|
-
providerBatching,
|
|
12076
|
-
config: resolveMockConfig(parsed)
|
|
12077
|
-
};
|
|
12078
|
-
case "vscode":
|
|
12079
|
-
case "vscode-insiders":
|
|
12080
|
-
return {
|
|
12081
|
-
kind: provider,
|
|
12082
|
-
name: parsed.name,
|
|
12083
|
-
judgeTarget: parsed.judge_target,
|
|
12084
|
-
workers: parsed.workers,
|
|
12085
|
-
providerBatching,
|
|
12086
|
-
config: resolveVSCodeConfig(parsed, env, provider === "vscode-insiders")
|
|
12087
|
-
};
|
|
12088
|
-
case "cli":
|
|
12155
|
+
buildCodexArgs() {
|
|
12156
|
+
const args = ["--ask-for-approval", "never", "exec", "--json", "--color", "never", "--skip-git-repo-check"];
|
|
12157
|
+
if (this.config.args && this.config.args.length > 0) {
|
|
12158
|
+
args.push(...this.config.args);
|
|
12159
|
+
}
|
|
12160
|
+
args.push("-");
|
|
12161
|
+
return args;
|
|
12162
|
+
}
|
|
12163
|
+
async executeCodex(args, cwd, promptContent, signal, logger) {
|
|
12164
|
+
try {
|
|
12165
|
+
return await this.runCodex({
|
|
12166
|
+
executable: this.resolvedExecutable ?? this.config.executable,
|
|
12167
|
+
args,
|
|
12168
|
+
cwd,
|
|
12169
|
+
prompt: promptContent,
|
|
12170
|
+
timeoutMs: this.config.timeoutMs,
|
|
12171
|
+
env: process.env,
|
|
12172
|
+
signal,
|
|
12173
|
+
onStdoutChunk: logger ? (chunk) => logger.handleStdoutChunk(chunk) : void 0,
|
|
12174
|
+
onStderrChunk: logger ? (chunk) => logger.handleStderrChunk(chunk) : void 0
|
|
12175
|
+
});
|
|
12176
|
+
} catch (error) {
|
|
12177
|
+
const err = error;
|
|
12178
|
+
if (err.code === "ENOENT") {
|
|
12179
|
+
throw new Error(
|
|
12180
|
+
`Codex executable '${this.config.executable}' was not found. Update the target settings.executable or add it to PATH.`
|
|
12181
|
+
);
|
|
12182
|
+
}
|
|
12183
|
+
throw error;
|
|
12184
|
+
}
|
|
12185
|
+
}
|
|
12186
|
+
async mirrorInputFiles(inputFiles, workspaceRoot, guidelineOriginals) {
|
|
12187
|
+
if (!inputFiles || inputFiles.length === 0) {
|
|
12089
12188
|
return {
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
judgeTarget: parsed.judge_target,
|
|
12093
|
-
workers: parsed.workers,
|
|
12094
|
-
providerBatching,
|
|
12095
|
-
config: resolveCliConfig(parsed, env)
|
|
12189
|
+
mirroredInputFiles: void 0,
|
|
12190
|
+
guidelineMirrors: /* @__PURE__ */ new Set()
|
|
12096
12191
|
};
|
|
12097
|
-
|
|
12098
|
-
|
|
12192
|
+
}
|
|
12193
|
+
const filesRoot = path42.join(workspaceRoot, FILES_DIR);
|
|
12194
|
+
await mkdir3(filesRoot, { recursive: true });
|
|
12195
|
+
const mirrored = [];
|
|
12196
|
+
const guidelineMirrors = /* @__PURE__ */ new Set();
|
|
12197
|
+
const nameCounts = /* @__PURE__ */ new Map();
|
|
12198
|
+
for (const inputFile of inputFiles) {
|
|
12199
|
+
const absoluteSource = path42.resolve(inputFile);
|
|
12200
|
+
const baseName = path42.basename(absoluteSource);
|
|
12201
|
+
const count = nameCounts.get(baseName) ?? 0;
|
|
12202
|
+
nameCounts.set(baseName, count + 1);
|
|
12203
|
+
const finalName = count === 0 ? baseName : `${baseName}.${count}`;
|
|
12204
|
+
const destination = path42.join(filesRoot, finalName);
|
|
12205
|
+
await copyFile2(absoluteSource, destination);
|
|
12206
|
+
const resolvedDestination = path42.resolve(destination);
|
|
12207
|
+
mirrored.push(resolvedDestination);
|
|
12208
|
+
if (guidelineOriginals.has(absoluteSource)) {
|
|
12209
|
+
guidelineMirrors.add(resolvedDestination);
|
|
12210
|
+
}
|
|
12211
|
+
}
|
|
12212
|
+
return {
|
|
12213
|
+
mirroredInputFiles: mirrored,
|
|
12214
|
+
guidelineMirrors
|
|
12215
|
+
};
|
|
12099
12216
|
}
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
const settings = target.settings ?? {};
|
|
12103
|
-
const endpointSource = settings.endpoint ?? settings.resource ?? settings.resourceName;
|
|
12104
|
-
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12105
|
-
const deploymentSource = settings.deployment ?? settings.deploymentName ?? settings.model;
|
|
12106
|
-
const versionSource = settings.version ?? settings.api_version;
|
|
12107
|
-
const temperatureSource = settings.temperature;
|
|
12108
|
-
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12109
|
-
const resourceName = resolveString(endpointSource, env, `${target.name} endpoint`);
|
|
12110
|
-
const apiKey = resolveString(apiKeySource, env, `${target.name} api key`);
|
|
12111
|
-
const deploymentName = resolveString(deploymentSource, env, `${target.name} deployment`);
|
|
12112
|
-
const version = normalizeAzureApiVersion(
|
|
12113
|
-
resolveOptionalString(versionSource, env, `${target.name} api version`)
|
|
12114
|
-
);
|
|
12115
|
-
const temperature = resolveOptionalNumber(temperatureSource, `${target.name} temperature`);
|
|
12116
|
-
const maxOutputTokens = resolveOptionalNumber(
|
|
12117
|
-
maxTokensSource,
|
|
12118
|
-
`${target.name} max output tokens`
|
|
12119
|
-
);
|
|
12120
|
-
return {
|
|
12121
|
-
resourceName,
|
|
12122
|
-
deploymentName,
|
|
12123
|
-
apiKey,
|
|
12124
|
-
version,
|
|
12125
|
-
temperature,
|
|
12126
|
-
maxOutputTokens
|
|
12127
|
-
};
|
|
12128
|
-
}
|
|
12129
|
-
function resolveAnthropicConfig(target, env) {
|
|
12130
|
-
const settings = target.settings ?? {};
|
|
12131
|
-
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12132
|
-
const modelSource = settings.model ?? settings.deployment ?? settings.variant;
|
|
12133
|
-
const temperatureSource = settings.temperature;
|
|
12134
|
-
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12135
|
-
const thinkingBudgetSource = settings.thinking_budget ?? settings.thinkingBudget;
|
|
12136
|
-
const apiKey = resolveString(apiKeySource, env, `${target.name} Anthropic api key`);
|
|
12137
|
-
const model = resolveString(modelSource, env, `${target.name} Anthropic model`);
|
|
12138
|
-
return {
|
|
12139
|
-
apiKey,
|
|
12140
|
-
model,
|
|
12141
|
-
temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),
|
|
12142
|
-
maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),
|
|
12143
|
-
thinkingBudget: resolveOptionalNumber(thinkingBudgetSource, `${target.name} thinking budget`)
|
|
12144
|
-
};
|
|
12145
|
-
}
|
|
12146
|
-
function resolveGeminiConfig(target, env) {
|
|
12147
|
-
const settings = target.settings ?? {};
|
|
12148
|
-
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12149
|
-
const modelSource = settings.model ?? settings.deployment ?? settings.variant;
|
|
12150
|
-
const temperatureSource = settings.temperature;
|
|
12151
|
-
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12152
|
-
const apiKey = resolveString(apiKeySource, env, `${target.name} Google API key`);
|
|
12153
|
-
const model = resolveOptionalString(modelSource, env, `${target.name} Gemini model`, {
|
|
12154
|
-
allowLiteral: true,
|
|
12155
|
-
optionalEnv: true
|
|
12156
|
-
}) ?? "gemini-2.5-flash";
|
|
12157
|
-
return {
|
|
12158
|
-
apiKey,
|
|
12159
|
-
model,
|
|
12160
|
-
temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),
|
|
12161
|
-
maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`)
|
|
12162
|
-
};
|
|
12163
|
-
}
|
|
12164
|
-
function resolveCodexConfig(target, env) {
|
|
12165
|
-
const settings = target.settings ?? {};
|
|
12166
|
-
const executableSource = settings.executable ?? settings.command ?? settings.binary;
|
|
12167
|
-
const argsSource = settings.args ?? settings.arguments;
|
|
12168
|
-
const cwdSource = settings.cwd;
|
|
12169
|
-
const timeoutSource = settings.timeout_seconds ?? settings.timeoutSeconds;
|
|
12170
|
-
const executable = resolveOptionalString(executableSource, env, `${target.name} codex executable`, {
|
|
12171
|
-
allowLiteral: true,
|
|
12172
|
-
optionalEnv: true
|
|
12173
|
-
}) ?? "codex";
|
|
12174
|
-
const args = resolveOptionalStringArray(argsSource, env, `${target.name} codex args`);
|
|
12175
|
-
const cwd = resolveOptionalString(cwdSource, env, `${target.name} codex cwd`, {
|
|
12176
|
-
allowLiteral: true,
|
|
12177
|
-
optionalEnv: true
|
|
12178
|
-
});
|
|
12179
|
-
const timeoutMs = resolveTimeoutMs(timeoutSource, `${target.name} codex timeout`);
|
|
12180
|
-
return {
|
|
12181
|
-
executable,
|
|
12182
|
-
args,
|
|
12183
|
-
cwd,
|
|
12184
|
-
timeoutMs
|
|
12185
|
-
};
|
|
12186
|
-
}
|
|
12187
|
-
function resolveMockConfig(target) {
|
|
12188
|
-
const settings = target.settings ?? {};
|
|
12189
|
-
const response = typeof settings.response === "string" ? settings.response : void 0;
|
|
12190
|
-
return { response };
|
|
12191
|
-
}
|
|
12192
|
-
function resolveVSCodeConfig(target, env, insiders) {
|
|
12193
|
-
const settings = target.settings ?? {};
|
|
12194
|
-
const workspaceTemplateEnvVar = resolveOptionalLiteralString(settings.workspace_template ?? settings.workspaceTemplate);
|
|
12195
|
-
const workspaceTemplate = workspaceTemplateEnvVar ? resolveOptionalString(workspaceTemplateEnvVar, env, `${target.name} workspace template path`, {
|
|
12196
|
-
allowLiteral: false,
|
|
12197
|
-
optionalEnv: true
|
|
12198
|
-
}) : void 0;
|
|
12199
|
-
const commandSource = settings.vscode_cmd ?? settings.command;
|
|
12200
|
-
const waitSource = settings.wait;
|
|
12201
|
-
const dryRunSource = settings.dry_run ?? settings.dryRun;
|
|
12202
|
-
const subagentRootSource = settings.subagent_root ?? settings.subagentRoot;
|
|
12203
|
-
const defaultCommand = insiders ? "code-insiders" : "code";
|
|
12204
|
-
const command = resolveOptionalLiteralString(commandSource) ?? defaultCommand;
|
|
12205
|
-
return {
|
|
12206
|
-
command,
|
|
12207
|
-
waitForResponse: resolveOptionalBoolean(waitSource) ?? true,
|
|
12208
|
-
dryRun: resolveOptionalBoolean(dryRunSource) ?? false,
|
|
12209
|
-
subagentRoot: resolveOptionalString(subagentRootSource, env, `${target.name} subagent root`, {
|
|
12210
|
-
allowLiteral: true,
|
|
12211
|
-
optionalEnv: true
|
|
12212
|
-
}),
|
|
12213
|
-
workspaceTemplate
|
|
12214
|
-
};
|
|
12215
|
-
}
|
|
12216
|
-
function resolveCliConfig(target, env) {
|
|
12217
|
-
const settings = target.settings ?? {};
|
|
12218
|
-
const commandTemplateSource = settings.command_template ?? settings.commandTemplate;
|
|
12219
|
-
const filesFormat = resolveOptionalLiteralString(
|
|
12220
|
-
settings.files_format ?? settings.filesFormat ?? settings.attachments_format ?? settings.attachmentsFormat
|
|
12221
|
-
);
|
|
12222
|
-
const cwd = resolveOptionalString(settings.cwd, env, `${target.name} working directory`, {
|
|
12223
|
-
allowLiteral: true,
|
|
12224
|
-
optionalEnv: true
|
|
12225
|
-
});
|
|
12226
|
-
const envOverrides = resolveEnvOverrides(settings.env, env, target.name);
|
|
12227
|
-
const timeoutMs = resolveTimeoutMs(settings.timeout_seconds ?? settings.timeoutSeconds, `${target.name} timeout`);
|
|
12228
|
-
const healthcheck = resolveCliHealthcheck(settings.healthcheck, env, target.name);
|
|
12229
|
-
const commandTemplate = resolveString(
|
|
12230
|
-
commandTemplateSource,
|
|
12231
|
-
env,
|
|
12232
|
-
`${target.name} CLI command template`,
|
|
12233
|
-
true
|
|
12234
|
-
);
|
|
12235
|
-
assertSupportedCliPlaceholders(commandTemplate, `${target.name} CLI command template`);
|
|
12236
|
-
return {
|
|
12237
|
-
commandTemplate,
|
|
12238
|
-
filesFormat,
|
|
12239
|
-
cwd,
|
|
12240
|
-
env: envOverrides,
|
|
12241
|
-
timeoutMs,
|
|
12242
|
-
healthcheck
|
|
12243
|
-
};
|
|
12244
|
-
}
|
|
12245
|
-
function resolveEnvOverrides(source2, env, targetName) {
|
|
12246
|
-
if (source2 === void 0 || source2 === null) {
|
|
12247
|
-
return void 0;
|
|
12217
|
+
async createWorkspace() {
|
|
12218
|
+
return await mkdtemp(path42.join(tmpdir(), WORKSPACE_PREFIX));
|
|
12248
12219
|
}
|
|
12249
|
-
|
|
12250
|
-
|
|
12220
|
+
async cleanupWorkspace(workspaceRoot) {
|
|
12221
|
+
try {
|
|
12222
|
+
await rm2(workspaceRoot, { recursive: true, force: true });
|
|
12223
|
+
} catch {
|
|
12224
|
+
}
|
|
12251
12225
|
}
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12226
|
+
resolveLogDirectory() {
|
|
12227
|
+
const disabled = isCodexLogStreamingDisabled();
|
|
12228
|
+
if (disabled) {
|
|
12229
|
+
return void 0;
|
|
12230
|
+
}
|
|
12231
|
+
if (this.config.logDir) {
|
|
12232
|
+
return path42.resolve(this.config.logDir);
|
|
12233
|
+
}
|
|
12234
|
+
return path42.join(process.cwd(), ".agentv", "logs", "codex");
|
|
12235
|
+
}
|
|
12236
|
+
async createStreamLogger(request) {
|
|
12237
|
+
const logDir = this.resolveLogDirectory();
|
|
12238
|
+
if (!logDir) {
|
|
12239
|
+
return void 0;
|
|
12240
|
+
}
|
|
12241
|
+
try {
|
|
12242
|
+
await mkdir3(logDir, { recursive: true });
|
|
12243
|
+
} catch (error) {
|
|
12244
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12245
|
+
console.warn(`Skipping Codex stream logging (could not create ${logDir}): ${message}`);
|
|
12246
|
+
return void 0;
|
|
12247
|
+
}
|
|
12248
|
+
const filePath = path42.join(logDir, buildLogFilename(request, this.targetName));
|
|
12249
|
+
try {
|
|
12250
|
+
const logger = await CodexStreamLogger.create({
|
|
12251
|
+
filePath,
|
|
12252
|
+
targetName: this.targetName,
|
|
12253
|
+
evalCaseId: request.evalCaseId,
|
|
12254
|
+
attempt: request.attempt,
|
|
12255
|
+
format: this.config.logFormat ?? "summary"
|
|
12256
|
+
});
|
|
12257
|
+
console.log(`Streaming Codex CLI output to ${filePath}`);
|
|
12258
|
+
return logger;
|
|
12259
|
+
} catch (error) {
|
|
12260
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12261
|
+
console.warn(`Skipping Codex stream logging for ${filePath}: ${message}`);
|
|
12262
|
+
return void 0;
|
|
12257
12263
|
}
|
|
12258
|
-
const resolvedValue = resolveString(value, env, `${targetName} env override '${key2}'`);
|
|
12259
|
-
resolved[key2] = resolvedValue;
|
|
12260
12264
|
}
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12265
|
+
};
|
|
12266
|
+
var CodexStreamLogger = class _CodexStreamLogger {
|
|
12267
|
+
filePath;
|
|
12268
|
+
stream;
|
|
12269
|
+
startedAt = Date.now();
|
|
12270
|
+
stdoutBuffer = "";
|
|
12271
|
+
stderrBuffer = "";
|
|
12272
|
+
format;
|
|
12273
|
+
constructor(filePath, format) {
|
|
12274
|
+
this.filePath = filePath;
|
|
12275
|
+
this.format = format;
|
|
12276
|
+
this.stream = createWriteStream(filePath, { flags: "a" });
|
|
12277
|
+
}
|
|
12278
|
+
static async create(options) {
|
|
12279
|
+
const logger = new _CodexStreamLogger(options.filePath, options.format);
|
|
12280
|
+
const header = [
|
|
12281
|
+
"# Codex CLI stream log",
|
|
12282
|
+
`# target: ${options.targetName}`,
|
|
12283
|
+
options.evalCaseId ? `# eval: ${options.evalCaseId}` : void 0,
|
|
12284
|
+
options.attempt !== void 0 ? `# attempt: ${options.attempt + 1}` : void 0,
|
|
12285
|
+
`# started: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
12286
|
+
""
|
|
12287
|
+
].filter((line2) => Boolean(line2));
|
|
12288
|
+
logger.writeLines(header);
|
|
12289
|
+
return logger;
|
|
12290
|
+
}
|
|
12291
|
+
handleStdoutChunk(chunk) {
|
|
12292
|
+
this.stdoutBuffer += chunk;
|
|
12293
|
+
this.flushBuffer("stdout");
|
|
12294
|
+
}
|
|
12295
|
+
handleStderrChunk(chunk) {
|
|
12296
|
+
this.stderrBuffer += chunk;
|
|
12297
|
+
this.flushBuffer("stderr");
|
|
12267
12298
|
}
|
|
12268
|
-
|
|
12269
|
-
|
|
12299
|
+
async close() {
|
|
12300
|
+
this.flushBuffer("stdout");
|
|
12301
|
+
this.flushBuffer("stderr");
|
|
12302
|
+
this.flushRemainder();
|
|
12303
|
+
await new Promise((resolve, reject) => {
|
|
12304
|
+
this.stream.once("error", reject);
|
|
12305
|
+
this.stream.end(() => resolve());
|
|
12306
|
+
});
|
|
12270
12307
|
}
|
|
12271
|
-
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12308
|
+
writeLines(lines) {
|
|
12309
|
+
for (const line2 of lines) {
|
|
12310
|
+
this.stream.write(`${line2}
|
|
12311
|
+
`);
|
|
12312
|
+
}
|
|
12276
12313
|
}
|
|
12277
|
-
|
|
12278
|
-
|
|
12314
|
+
flushBuffer(source2) {
|
|
12315
|
+
const buffer2 = source2 === "stdout" ? this.stdoutBuffer : this.stderrBuffer;
|
|
12316
|
+
const lines = buffer2.split(/\r?\n/);
|
|
12317
|
+
const remainder = lines.pop() ?? "";
|
|
12318
|
+
if (source2 === "stdout") {
|
|
12319
|
+
this.stdoutBuffer = remainder;
|
|
12320
|
+
} else {
|
|
12321
|
+
this.stderrBuffer = remainder;
|
|
12322
|
+
}
|
|
12323
|
+
for (const line2 of lines) {
|
|
12324
|
+
const formatted = this.formatLine(line2, source2);
|
|
12325
|
+
if (formatted) {
|
|
12326
|
+
this.stream.write(formatted);
|
|
12327
|
+
this.stream.write("\n");
|
|
12328
|
+
}
|
|
12329
|
+
}
|
|
12279
12330
|
}
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
const url = resolveString(candidate.url, env, `${targetName} healthcheck URL`);
|
|
12288
|
-
return {
|
|
12289
|
-
type: "http",
|
|
12290
|
-
url,
|
|
12291
|
-
timeoutMs
|
|
12292
|
-
};
|
|
12331
|
+
formatLine(rawLine, source2) {
|
|
12332
|
+
const trimmed = rawLine.trim();
|
|
12333
|
+
if (trimmed.length === 0) {
|
|
12334
|
+
return void 0;
|
|
12335
|
+
}
|
|
12336
|
+
const message = this.format === "json" ? formatCodexJsonLog(trimmed) : formatCodexLogMessage(trimmed, source2);
|
|
12337
|
+
return `[+${formatElapsed(this.startedAt)}] [${source2}] ${message}`;
|
|
12293
12338
|
}
|
|
12294
|
-
|
|
12295
|
-
const
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12309
|
-
|
|
12310
|
-
|
|
12311
|
-
|
|
12339
|
+
flushRemainder() {
|
|
12340
|
+
const stdoutRemainder = this.stdoutBuffer.trim();
|
|
12341
|
+
if (stdoutRemainder.length > 0) {
|
|
12342
|
+
const formatted = this.formatLine(stdoutRemainder, "stdout");
|
|
12343
|
+
if (formatted) {
|
|
12344
|
+
this.stream.write(formatted);
|
|
12345
|
+
this.stream.write("\n");
|
|
12346
|
+
}
|
|
12347
|
+
}
|
|
12348
|
+
const stderrRemainder = this.stderrBuffer.trim();
|
|
12349
|
+
if (stderrRemainder.length > 0) {
|
|
12350
|
+
const formatted = this.formatLine(stderrRemainder, "stderr");
|
|
12351
|
+
if (formatted) {
|
|
12352
|
+
this.stream.write(formatted);
|
|
12353
|
+
this.stream.write("\n");
|
|
12354
|
+
}
|
|
12355
|
+
}
|
|
12356
|
+
this.stdoutBuffer = "";
|
|
12357
|
+
this.stderrBuffer = "";
|
|
12312
12358
|
}
|
|
12313
|
-
|
|
12359
|
+
};
|
|
12360
|
+
function isCodexLogStreamingDisabled() {
|
|
12361
|
+
const envValue = process.env.AGENTV_CODEX_STREAM_LOGS;
|
|
12362
|
+
if (!envValue) {
|
|
12363
|
+
return false;
|
|
12364
|
+
}
|
|
12365
|
+
const normalized = envValue.trim().toLowerCase();
|
|
12366
|
+
return normalized === "false" || normalized === "0" || normalized === "off";
|
|
12314
12367
|
}
|
|
12315
|
-
function
|
|
12316
|
-
const
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12368
|
+
function buildLogFilename(request, targetName) {
|
|
12369
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
12370
|
+
const evalId = sanitizeForFilename(request.evalCaseId ?? "codex");
|
|
12371
|
+
const attemptSuffix = request.attempt !== void 0 ? `_attempt-${request.attempt + 1}` : "";
|
|
12372
|
+
const target = sanitizeForFilename(targetName);
|
|
12373
|
+
return `${timestamp}_${target}_${evalId}${attemptSuffix}_${randomUUID().slice(0, 8)}.log`;
|
|
12374
|
+
}
|
|
12375
|
+
function sanitizeForFilename(value) {
|
|
12376
|
+
const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
12377
|
+
return sanitized.length > 0 ? sanitized : "codex";
|
|
12378
|
+
}
|
|
12379
|
+
function formatElapsed(startedAt) {
|
|
12380
|
+
const elapsedSeconds = Math.floor((Date.now() - startedAt) / 1e3);
|
|
12381
|
+
const hours = Math.floor(elapsedSeconds / 3600);
|
|
12382
|
+
const minutes = Math.floor(elapsedSeconds % 3600 / 60);
|
|
12383
|
+
const seconds = elapsedSeconds % 60;
|
|
12384
|
+
if (hours > 0) {
|
|
12385
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
12323
12386
|
}
|
|
12387
|
+
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
12324
12388
|
}
|
|
12325
|
-
function
|
|
12326
|
-
const
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
if (
|
|
12330
|
-
|
|
12389
|
+
function formatCodexLogMessage(rawLine, source2) {
|
|
12390
|
+
const parsed = tryParseJsonValue(rawLine);
|
|
12391
|
+
if (parsed) {
|
|
12392
|
+
const summary = summarizeCodexEvent(parsed);
|
|
12393
|
+
if (summary) {
|
|
12394
|
+
return summary;
|
|
12331
12395
|
}
|
|
12332
12396
|
}
|
|
12333
|
-
|
|
12334
|
-
}
|
|
12335
|
-
function resolveString(source2, env, description, allowLiteral = false) {
|
|
12336
|
-
const value = resolveOptionalString(source2, env, description, {
|
|
12337
|
-
allowLiteral,
|
|
12338
|
-
optionalEnv: false
|
|
12339
|
-
});
|
|
12340
|
-
if (value === void 0) {
|
|
12341
|
-
throw new Error(`${description} is required`);
|
|
12397
|
+
if (source2 === "stderr") {
|
|
12398
|
+
return `stderr: ${rawLine}`;
|
|
12342
12399
|
}
|
|
12343
|
-
return
|
|
12400
|
+
return rawLine;
|
|
12344
12401
|
}
|
|
12345
|
-
function
|
|
12346
|
-
|
|
12347
|
-
|
|
12402
|
+
function formatCodexJsonLog(rawLine) {
|
|
12403
|
+
const parsed = tryParseJsonValue(rawLine);
|
|
12404
|
+
if (!parsed) {
|
|
12405
|
+
return rawLine;
|
|
12348
12406
|
}
|
|
12349
|
-
|
|
12350
|
-
|
|
12407
|
+
try {
|
|
12408
|
+
return JSON.stringify(parsed, null, 2);
|
|
12409
|
+
} catch {
|
|
12410
|
+
return rawLine;
|
|
12351
12411
|
}
|
|
12352
|
-
|
|
12353
|
-
|
|
12412
|
+
}
|
|
12413
|
+
function summarizeCodexEvent(event) {
|
|
12414
|
+
if (!event || typeof event !== "object") {
|
|
12354
12415
|
return void 0;
|
|
12355
12416
|
}
|
|
12356
|
-
const
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12417
|
+
const record = event;
|
|
12418
|
+
const type = typeof record.type === "string" ? record.type : void 0;
|
|
12419
|
+
let message = extractFromEvent(event) ?? extractFromItem(record.item) ?? flattenContent(record.output ?? record.content);
|
|
12420
|
+
if (!message && type === JSONL_TYPE_ITEM_COMPLETED) {
|
|
12421
|
+
const item = record.item;
|
|
12422
|
+
if (item && typeof item === "object") {
|
|
12423
|
+
const candidate = flattenContent(
|
|
12424
|
+
item.text ?? item.content ?? item.output
|
|
12425
|
+
);
|
|
12426
|
+
if (candidate) {
|
|
12427
|
+
message = candidate;
|
|
12428
|
+
}
|
|
12360
12429
|
}
|
|
12361
|
-
return envValue;
|
|
12362
12430
|
}
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
if (optionalEnv) {
|
|
12368
|
-
return void 0;
|
|
12431
|
+
if (!message) {
|
|
12432
|
+
const itemType = typeof record.item?.type === "string" ? record.item.type : void 0;
|
|
12433
|
+
if (type && itemType) {
|
|
12434
|
+
return `${type}:${itemType}`;
|
|
12369
12435
|
}
|
|
12370
|
-
if (
|
|
12371
|
-
|
|
12436
|
+
if (type) {
|
|
12437
|
+
return type;
|
|
12372
12438
|
}
|
|
12373
12439
|
}
|
|
12374
|
-
|
|
12375
|
-
}
|
|
12376
|
-
function resolveOptionalLiteralString(source2) {
|
|
12377
|
-
if (source2 === void 0 || source2 === null) {
|
|
12378
|
-
return void 0;
|
|
12440
|
+
if (type && message) {
|
|
12441
|
+
return `${type}: ${message}`;
|
|
12379
12442
|
}
|
|
12380
|
-
if (
|
|
12381
|
-
|
|
12443
|
+
if (message) {
|
|
12444
|
+
return message;
|
|
12382
12445
|
}
|
|
12383
|
-
|
|
12384
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
12446
|
+
return type;
|
|
12385
12447
|
}
|
|
12386
|
-
function
|
|
12387
|
-
|
|
12448
|
+
function tryParseJsonValue(rawLine) {
|
|
12449
|
+
try {
|
|
12450
|
+
return JSON.parse(rawLine);
|
|
12451
|
+
} catch {
|
|
12388
12452
|
return void 0;
|
|
12389
12453
|
}
|
|
12390
|
-
|
|
12391
|
-
|
|
12454
|
+
}
|
|
12455
|
+
async function locateExecutable(candidate) {
|
|
12456
|
+
const includesPathSeparator = candidate.includes("/") || candidate.includes("\\");
|
|
12457
|
+
if (includesPathSeparator) {
|
|
12458
|
+
const resolved = path42.isAbsolute(candidate) ? candidate : path42.resolve(candidate);
|
|
12459
|
+
const executablePath = await ensureWindowsExecutableVariant(resolved);
|
|
12460
|
+
await access22(executablePath, constants22.F_OK);
|
|
12461
|
+
return executablePath;
|
|
12392
12462
|
}
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12463
|
+
const locator = process.platform === "win32" ? "where" : "which";
|
|
12464
|
+
try {
|
|
12465
|
+
const { stdout } = await execAsync22(`${locator} ${candidate}`);
|
|
12466
|
+
const lines = stdout.split(/\r?\n/).map((line2) => line2.trim()).filter((line2) => line2.length > 0);
|
|
12467
|
+
const preferred = selectExecutableCandidate(lines);
|
|
12468
|
+
if (preferred) {
|
|
12469
|
+
const executablePath = await ensureWindowsExecutableVariant(preferred);
|
|
12470
|
+
await access22(executablePath, constants22.F_OK);
|
|
12471
|
+
return executablePath;
|
|
12397
12472
|
}
|
|
12473
|
+
} catch {
|
|
12398
12474
|
}
|
|
12399
|
-
throw new Error(
|
|
12475
|
+
throw new Error(`Codex executable '${candidate}' was not found on PATH`);
|
|
12400
12476
|
}
|
|
12401
|
-
function
|
|
12402
|
-
if (
|
|
12477
|
+
function selectExecutableCandidate(candidates) {
|
|
12478
|
+
if (candidates.length === 0) {
|
|
12403
12479
|
return void 0;
|
|
12404
12480
|
}
|
|
12405
|
-
if (
|
|
12406
|
-
return
|
|
12481
|
+
if (process.platform !== "win32") {
|
|
12482
|
+
return candidates[0];
|
|
12407
12483
|
}
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12484
|
+
const extensions = getWindowsExecutableExtensions();
|
|
12485
|
+
for (const ext of extensions) {
|
|
12486
|
+
const match = candidates.find((candidate) => candidate.toLowerCase().endsWith(ext));
|
|
12487
|
+
if (match) {
|
|
12488
|
+
return match;
|
|
12412
12489
|
}
|
|
12413
|
-
|
|
12414
|
-
|
|
12490
|
+
}
|
|
12491
|
+
return candidates[0];
|
|
12492
|
+
}
|
|
12493
|
+
async function ensureWindowsExecutableVariant(candidate) {
|
|
12494
|
+
if (process.platform !== "win32") {
|
|
12495
|
+
return candidate;
|
|
12496
|
+
}
|
|
12497
|
+
if (hasExecutableExtension(candidate)) {
|
|
12498
|
+
return candidate;
|
|
12499
|
+
}
|
|
12500
|
+
const extensions = getWindowsExecutableExtensions();
|
|
12501
|
+
for (const ext of extensions) {
|
|
12502
|
+
const withExtension = `${candidate}${ext}`;
|
|
12503
|
+
try {
|
|
12504
|
+
await access22(withExtension, constants22.F_OK);
|
|
12505
|
+
return withExtension;
|
|
12506
|
+
} catch {
|
|
12415
12507
|
}
|
|
12416
12508
|
}
|
|
12417
|
-
|
|
12509
|
+
return candidate;
|
|
12418
12510
|
}
|
|
12419
|
-
function
|
|
12420
|
-
|
|
12511
|
+
function hasExecutableExtension(candidate) {
|
|
12512
|
+
const lower = candidate.toLowerCase();
|
|
12513
|
+
return getWindowsExecutableExtensions().some((ext) => lower.endsWith(ext));
|
|
12421
12514
|
}
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
if (!Array.isArray(source2)) {
|
|
12427
|
-
throw new Error(`${description} must be an array of strings`);
|
|
12515
|
+
var DEFAULT_WINDOWS_EXTENSIONS = [".com", ".exe", ".bat", ".cmd", ".ps1"];
|
|
12516
|
+
function getWindowsExecutableExtensions() {
|
|
12517
|
+
if (process.platform !== "win32") {
|
|
12518
|
+
return [];
|
|
12428
12519
|
}
|
|
12429
|
-
|
|
12430
|
-
|
|
12520
|
+
const fromEnv = process.env.PATHEXT?.split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.length > 0);
|
|
12521
|
+
return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_WINDOWS_EXTENSIONS;
|
|
12522
|
+
}
|
|
12523
|
+
function parseCodexJson(output) {
|
|
12524
|
+
const trimmed = output.trim();
|
|
12525
|
+
if (trimmed.length === 0) {
|
|
12526
|
+
throw new Error("Codex CLI produced no output in --json mode");
|
|
12431
12527
|
}
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
throw new Error(`Environment variable '${trimmed}' for ${description}[${i6}] is empty`);
|
|
12528
|
+
try {
|
|
12529
|
+
return JSON.parse(trimmed);
|
|
12530
|
+
} catch {
|
|
12531
|
+
const lineObjects = parseJsonLines(trimmed);
|
|
12532
|
+
if (lineObjects) {
|
|
12533
|
+
return lineObjects;
|
|
12534
|
+
}
|
|
12535
|
+
const lastBrace = trimmed.lastIndexOf("{");
|
|
12536
|
+
if (lastBrace >= 0) {
|
|
12537
|
+
const candidate = trimmed.slice(lastBrace);
|
|
12538
|
+
try {
|
|
12539
|
+
return JSON.parse(candidate);
|
|
12540
|
+
} catch {
|
|
12446
12541
|
}
|
|
12447
|
-
resolved.push(envValue);
|
|
12448
|
-
} else {
|
|
12449
|
-
resolved.push(trimmed);
|
|
12450
12542
|
}
|
|
12543
|
+
const preview = trimmed.slice(0, 200);
|
|
12544
|
+
throw new Error(`Codex CLI emitted invalid JSON: ${preview}${trimmed.length > 200 ? "\u2026" : ""}`);
|
|
12451
12545
|
}
|
|
12452
|
-
return resolved.length > 0 ? resolved : void 0;
|
|
12453
12546
|
}
|
|
12454
|
-
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
config;
|
|
12460
|
-
constructor(targetName, config, kind) {
|
|
12461
|
-
this.id = `${kind}:${targetName}`;
|
|
12462
|
-
this.kind = kind;
|
|
12463
|
-
this.targetName = targetName;
|
|
12464
|
-
this.config = config;
|
|
12465
|
-
}
|
|
12466
|
-
async invoke(request) {
|
|
12467
|
-
if (request.signal?.aborted) {
|
|
12468
|
-
throw new Error("VS Code provider request was aborted before dispatch");
|
|
12469
|
-
}
|
|
12470
|
-
const inputFiles = normalizeAttachments(request.inputFiles);
|
|
12471
|
-
const promptContent = buildPromptDocument(request, inputFiles, request.guideline_patterns);
|
|
12472
|
-
const session = await dispatchAgentSession({
|
|
12473
|
-
userQuery: promptContent,
|
|
12474
|
-
extraAttachments: inputFiles,
|
|
12475
|
-
wait: this.config.waitForResponse,
|
|
12476
|
-
dryRun: this.config.dryRun,
|
|
12477
|
-
vscodeCmd: this.config.command,
|
|
12478
|
-
subagentRoot: this.config.subagentRoot,
|
|
12479
|
-
workspaceTemplate: this.config.workspaceTemplate,
|
|
12480
|
-
silent: true
|
|
12481
|
-
});
|
|
12482
|
-
if (session.exitCode !== 0 || !session.responseFile) {
|
|
12483
|
-
const failure = session.error ?? "VS Code subagent did not produce a response";
|
|
12484
|
-
throw new Error(failure);
|
|
12485
|
-
}
|
|
12486
|
-
if (this.config.dryRun) {
|
|
12487
|
-
return {
|
|
12488
|
-
text: "",
|
|
12489
|
-
raw: {
|
|
12490
|
-
session,
|
|
12491
|
-
inputFiles
|
|
12492
|
-
}
|
|
12493
|
-
};
|
|
12547
|
+
function extractAssistantText(parsed) {
|
|
12548
|
+
if (Array.isArray(parsed)) {
|
|
12549
|
+
const text = extractFromEventStream(parsed);
|
|
12550
|
+
if (text) {
|
|
12551
|
+
return text;
|
|
12494
12552
|
}
|
|
12495
|
-
const responseText = await readFile22(session.responseFile, "utf8");
|
|
12496
|
-
return {
|
|
12497
|
-
text: responseText,
|
|
12498
|
-
raw: {
|
|
12499
|
-
session,
|
|
12500
|
-
inputFiles
|
|
12501
|
-
}
|
|
12502
|
-
};
|
|
12503
12553
|
}
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
)
|
|
12515
|
-
|
|
12516
|
-
(
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
if (session.exitCode !== 0 || !session.responseFiles) {
|
|
12529
|
-
const failure = session.error ?? "VS Code subagent did not produce batch responses";
|
|
12530
|
-
throw new Error(failure);
|
|
12554
|
+
if (!parsed || typeof parsed !== "object") {
|
|
12555
|
+
throw new Error("Codex CLI JSON response did not include an assistant message");
|
|
12556
|
+
}
|
|
12557
|
+
const record = parsed;
|
|
12558
|
+
const eventText = extractFromEvent(record);
|
|
12559
|
+
if (eventText) {
|
|
12560
|
+
return eventText;
|
|
12561
|
+
}
|
|
12562
|
+
const messages = Array.isArray(record.messages) ? record.messages : void 0;
|
|
12563
|
+
if (messages) {
|
|
12564
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
12565
|
+
const entry = messages[index];
|
|
12566
|
+
if (!entry || typeof entry !== "object") {
|
|
12567
|
+
continue;
|
|
12568
|
+
}
|
|
12569
|
+
const role = entry.role;
|
|
12570
|
+
if (role !== "assistant") {
|
|
12571
|
+
continue;
|
|
12572
|
+
}
|
|
12573
|
+
const content = entry.content;
|
|
12574
|
+
const flattened = flattenContent(content);
|
|
12575
|
+
if (flattened) {
|
|
12576
|
+
return flattened;
|
|
12577
|
+
}
|
|
12531
12578
|
}
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
}
|
|
12540
|
-
}));
|
|
12579
|
+
}
|
|
12580
|
+
const response = record.response;
|
|
12581
|
+
if (response && typeof response === "object") {
|
|
12582
|
+
const content = response.content;
|
|
12583
|
+
const flattened = flattenContent(content);
|
|
12584
|
+
if (flattened) {
|
|
12585
|
+
return flattened;
|
|
12541
12586
|
}
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12587
|
+
}
|
|
12588
|
+
const output = record.output;
|
|
12589
|
+
const flattenedOutput = flattenContent(output);
|
|
12590
|
+
if (flattenedOutput) {
|
|
12591
|
+
return flattenedOutput;
|
|
12592
|
+
}
|
|
12593
|
+
throw new Error("Codex CLI JSON response did not include an assistant message");
|
|
12594
|
+
}
|
|
12595
|
+
function extractFromEventStream(events) {
|
|
12596
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
12597
|
+
const candidate = events[index];
|
|
12598
|
+
const text = extractFromEvent(candidate);
|
|
12599
|
+
if (text) {
|
|
12600
|
+
return text;
|
|
12546
12601
|
}
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12557
|
-
|
|
12558
|
-
|
|
12602
|
+
}
|
|
12603
|
+
return void 0;
|
|
12604
|
+
}
|
|
12605
|
+
function extractFromEvent(event) {
|
|
12606
|
+
if (!event || typeof event !== "object") {
|
|
12607
|
+
return void 0;
|
|
12608
|
+
}
|
|
12609
|
+
const record = event;
|
|
12610
|
+
const type = typeof record.type === "string" ? record.type : void 0;
|
|
12611
|
+
if (type === JSONL_TYPE_ITEM_COMPLETED) {
|
|
12612
|
+
const item = record.item;
|
|
12613
|
+
const text = extractFromItem(item);
|
|
12614
|
+
if (text) {
|
|
12615
|
+
return text;
|
|
12559
12616
|
}
|
|
12560
|
-
return responses;
|
|
12561
12617
|
}
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
const attachmentFiles = collectAttachmentFiles(attachments);
|
|
12567
|
-
const nonGuidelineAttachments = attachmentFiles.filter(
|
|
12568
|
-
(file) => !guidelineFiles.includes(file)
|
|
12569
|
-
);
|
|
12570
|
-
const prereadBlock = buildMandatoryPrereadBlock(guidelineFiles, nonGuidelineAttachments);
|
|
12571
|
-
if (prereadBlock.length > 0) {
|
|
12572
|
-
parts.push("\n", prereadBlock);
|
|
12618
|
+
const output = record.output ?? record.content;
|
|
12619
|
+
const flattened = flattenContent(output);
|
|
12620
|
+
if (flattened) {
|
|
12621
|
+
return flattened;
|
|
12573
12622
|
}
|
|
12574
|
-
|
|
12575
|
-
return parts.join("\n").trim();
|
|
12623
|
+
return void 0;
|
|
12576
12624
|
}
|
|
12577
|
-
function
|
|
12578
|
-
if (
|
|
12579
|
-
return
|
|
12580
|
-
}
|
|
12581
|
-
const buildList = (files) => files.map((absolutePath) => {
|
|
12582
|
-
const fileName = path32.basename(absolutePath);
|
|
12583
|
-
const fileUri = pathToFileUri2(absolutePath);
|
|
12584
|
-
return `* [${fileName}](${fileUri})`;
|
|
12585
|
-
});
|
|
12586
|
-
const sections = [];
|
|
12587
|
-
if (guidelineFiles.length > 0) {
|
|
12588
|
-
sections.push(`Read all guideline files:
|
|
12589
|
-
${buildList(guidelineFiles).join("\n")}.`);
|
|
12625
|
+
function extractFromItem(item) {
|
|
12626
|
+
if (!item || typeof item !== "object") {
|
|
12627
|
+
return void 0;
|
|
12590
12628
|
}
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12629
|
+
const record = item;
|
|
12630
|
+
const itemType = typeof record.type === "string" ? record.type : void 0;
|
|
12631
|
+
if (itemType === "agent_message" || itemType === "response" || itemType === "output") {
|
|
12632
|
+
const text = flattenContent(record.text ?? record.content ?? record.output);
|
|
12633
|
+
if (text) {
|
|
12634
|
+
return text;
|
|
12635
|
+
}
|
|
12594
12636
|
}
|
|
12595
|
-
|
|
12596
|
-
"If any file is missing, fail with ERROR: missing-file <filename> and stop.",
|
|
12597
|
-
"Then apply system_instructions on the user query below."
|
|
12598
|
-
);
|
|
12599
|
-
return sections.join("\n");
|
|
12637
|
+
return void 0;
|
|
12600
12638
|
}
|
|
12601
|
-
function
|
|
12602
|
-
if (
|
|
12603
|
-
return
|
|
12639
|
+
function flattenContent(value) {
|
|
12640
|
+
if (typeof value === "string") {
|
|
12641
|
+
return value;
|
|
12604
12642
|
}
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
if (isGuidelineFile(normalized, guidelinePatterns)) {
|
|
12610
|
-
if (!unique.has(absolutePath)) {
|
|
12611
|
-
unique.set(absolutePath, absolutePath);
|
|
12643
|
+
if (Array.isArray(value)) {
|
|
12644
|
+
const parts = value.map((segment) => {
|
|
12645
|
+
if (typeof segment === "string") {
|
|
12646
|
+
return segment;
|
|
12612
12647
|
}
|
|
12613
|
-
|
|
12648
|
+
if (segment && typeof segment === "object" && "text" in segment) {
|
|
12649
|
+
const text = segment.text;
|
|
12650
|
+
return typeof text === "string" ? text : void 0;
|
|
12651
|
+
}
|
|
12652
|
+
return void 0;
|
|
12653
|
+
}).filter((part) => typeof part === "string" && part.length > 0);
|
|
12654
|
+
return parts.length > 0 ? parts.join(" \n") : void 0;
|
|
12614
12655
|
}
|
|
12615
|
-
|
|
12656
|
+
if (value && typeof value === "object" && "text" in value) {
|
|
12657
|
+
const text = value.text;
|
|
12658
|
+
return typeof text === "string" ? text : void 0;
|
|
12659
|
+
}
|
|
12660
|
+
return void 0;
|
|
12616
12661
|
}
|
|
12617
|
-
function
|
|
12618
|
-
|
|
12619
|
-
|
|
12662
|
+
function parseJsonLines(output) {
|
|
12663
|
+
const lines = output.split(/\r?\n/).map((line2) => line2.trim()).filter((line2) => line2.length > 0);
|
|
12664
|
+
if (lines.length <= 1) {
|
|
12665
|
+
return void 0;
|
|
12620
12666
|
}
|
|
12621
|
-
const
|
|
12622
|
-
for (const
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
|
|
12667
|
+
const parsed = [];
|
|
12668
|
+
for (const line2 of lines) {
|
|
12669
|
+
try {
|
|
12670
|
+
parsed.push(JSON.parse(line2));
|
|
12671
|
+
} catch {
|
|
12672
|
+
return void 0;
|
|
12626
12673
|
}
|
|
12627
12674
|
}
|
|
12628
|
-
return
|
|
12675
|
+
return parsed;
|
|
12629
12676
|
}
|
|
12630
|
-
function
|
|
12631
|
-
const
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
return `file:///${normalizedPath}`;
|
|
12677
|
+
function pickDetail(stderr, stdout) {
|
|
12678
|
+
const errorText = stderr.trim();
|
|
12679
|
+
if (errorText.length > 0) {
|
|
12680
|
+
return errorText;
|
|
12635
12681
|
}
|
|
12636
|
-
|
|
12682
|
+
const stdoutText = stdout.trim();
|
|
12683
|
+
return stdoutText.length > 0 ? stdoutText : void 0;
|
|
12637
12684
|
}
|
|
12638
|
-
function
|
|
12639
|
-
if (!
|
|
12640
|
-
return
|
|
12641
|
-
}
|
|
12642
|
-
const deduped = /* @__PURE__ */ new Set();
|
|
12643
|
-
for (const attachment of attachments) {
|
|
12644
|
-
deduped.add(path32.resolve(attachment));
|
|
12685
|
+
function formatTimeoutSuffix2(timeoutMs) {
|
|
12686
|
+
if (!timeoutMs || timeoutMs <= 0) {
|
|
12687
|
+
return "";
|
|
12645
12688
|
}
|
|
12646
|
-
|
|
12689
|
+
const seconds = Math.ceil(timeoutMs / 1e3);
|
|
12690
|
+
return ` after ${seconds}s`;
|
|
12647
12691
|
}
|
|
12648
|
-
function
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12692
|
+
async function defaultCodexRunner(options) {
|
|
12693
|
+
return await new Promise((resolve, reject) => {
|
|
12694
|
+
const child = spawn2(options.executable, options.args, {
|
|
12695
|
+
cwd: options.cwd,
|
|
12696
|
+
env: options.env,
|
|
12697
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
12698
|
+
shell: shouldShellExecute(options.executable)
|
|
12699
|
+
});
|
|
12700
|
+
let stdout = "";
|
|
12701
|
+
let stderr = "";
|
|
12702
|
+
let timedOut = false;
|
|
12703
|
+
const onAbort = () => {
|
|
12704
|
+
child.kill("SIGTERM");
|
|
12705
|
+
};
|
|
12706
|
+
if (options.signal) {
|
|
12707
|
+
if (options.signal.aborted) {
|
|
12708
|
+
onAbort();
|
|
12709
|
+
} else {
|
|
12710
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
12711
|
+
}
|
|
12654
12712
|
}
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
try {
|
|
12663
|
-
if (verbose) {
|
|
12664
|
-
console.log(`Provisioning ${count} subagent(s) via: subagent ${vscodeCmd} provision`);
|
|
12713
|
+
let timeoutHandle;
|
|
12714
|
+
if (options.timeoutMs && options.timeoutMs > 0) {
|
|
12715
|
+
timeoutHandle = setTimeout(() => {
|
|
12716
|
+
timedOut = true;
|
|
12717
|
+
child.kill("SIGTERM");
|
|
12718
|
+
}, options.timeoutMs);
|
|
12719
|
+
timeoutHandle.unref?.();
|
|
12665
12720
|
}
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12721
|
+
child.stdout.setEncoding("utf8");
|
|
12722
|
+
child.stdout.on("data", (chunk) => {
|
|
12723
|
+
stdout += chunk;
|
|
12724
|
+
options.onStdoutChunk?.(chunk);
|
|
12670
12725
|
});
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12726
|
+
child.stderr.setEncoding("utf8");
|
|
12727
|
+
child.stderr.on("data", (chunk) => {
|
|
12728
|
+
stderr += chunk;
|
|
12729
|
+
options.onStderrChunk?.(chunk);
|
|
12730
|
+
});
|
|
12731
|
+
child.stdin.end(options.prompt);
|
|
12732
|
+
const cleanup = () => {
|
|
12733
|
+
if (timeoutHandle) {
|
|
12734
|
+
clearTimeout(timeoutHandle);
|
|
12674
12735
|
}
|
|
12675
|
-
if (
|
|
12676
|
-
|
|
12736
|
+
if (options.signal) {
|
|
12737
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
12677
12738
|
}
|
|
12678
|
-
console.log(`
|
|
12679
|
-
total unlocked subagents available: ${result.created.length + result.skippedExisting.length}`);
|
|
12680
|
-
}
|
|
12681
|
-
return {
|
|
12682
|
-
provisioned: true,
|
|
12683
|
-
message: `Provisioned ${count} subagent(s): ${result.created.length} created, ${result.skippedExisting.length} reused`
|
|
12684
12739
|
};
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
|
|
12688
|
-
|
|
12740
|
+
child.on("error", (error) => {
|
|
12741
|
+
cleanup();
|
|
12742
|
+
reject(error);
|
|
12743
|
+
});
|
|
12744
|
+
child.on("close", (code) => {
|
|
12745
|
+
cleanup();
|
|
12746
|
+
resolve({
|
|
12747
|
+
stdout,
|
|
12748
|
+
stderr,
|
|
12749
|
+
exitCode: typeof code === "number" ? code : -1,
|
|
12750
|
+
timedOut
|
|
12751
|
+
});
|
|
12752
|
+
});
|
|
12753
|
+
});
|
|
12754
|
+
}
|
|
12755
|
+
function shouldShellExecute(executable) {
|
|
12756
|
+
if (process.platform !== "win32") {
|
|
12757
|
+
return false;
|
|
12758
|
+
}
|
|
12759
|
+
const lower = executable.toLowerCase();
|
|
12760
|
+
return lower.endsWith(".cmd") || lower.endsWith(".bat") || lower.endsWith(".ps1");
|
|
12761
|
+
}
|
|
12762
|
+
var DEFAULT_MOCK_RESPONSE = '{"answer":"Mock provider response. Configure targets.yaml to supply a custom value."}';
|
|
12763
|
+
var MockProvider = class {
|
|
12764
|
+
id;
|
|
12765
|
+
kind = "mock";
|
|
12766
|
+
targetName;
|
|
12767
|
+
cannedResponse;
|
|
12768
|
+
delayMs;
|
|
12769
|
+
delayMinMs;
|
|
12770
|
+
delayMaxMs;
|
|
12771
|
+
constructor(targetName, config) {
|
|
12772
|
+
this.id = `mock:${targetName}`;
|
|
12773
|
+
this.targetName = targetName;
|
|
12774
|
+
this.cannedResponse = config.response ?? DEFAULT_MOCK_RESPONSE;
|
|
12775
|
+
this.delayMs = config.delayMs ?? 0;
|
|
12776
|
+
this.delayMinMs = config.delayMinMs ?? 0;
|
|
12777
|
+
this.delayMaxMs = config.delayMaxMs ?? 0;
|
|
12778
|
+
}
|
|
12779
|
+
async invoke(request) {
|
|
12780
|
+
const delay = this.calculateDelay();
|
|
12781
|
+
if (delay > 0) {
|
|
12782
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
12689
12783
|
}
|
|
12690
12784
|
return {
|
|
12691
|
-
|
|
12692
|
-
|
|
12785
|
+
text: this.cannedResponse,
|
|
12786
|
+
raw: {
|
|
12787
|
+
prompt: request.prompt,
|
|
12788
|
+
guidelines: request.guidelines
|
|
12789
|
+
}
|
|
12693
12790
|
};
|
|
12694
12791
|
}
|
|
12792
|
+
calculateDelay() {
|
|
12793
|
+
if (this.delayMinMs > 0 || this.delayMaxMs > 0) {
|
|
12794
|
+
const min = Math.max(0, this.delayMinMs);
|
|
12795
|
+
const max = Math.max(min, this.delayMaxMs);
|
|
12796
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
12797
|
+
}
|
|
12798
|
+
return this.delayMs;
|
|
12799
|
+
}
|
|
12800
|
+
};
|
|
12801
|
+
var CLI_PLACEHOLDERS = /* @__PURE__ */ new Set(["PROMPT", "GUIDELINES", "EVAL_ID", "ATTEMPT", "FILES"]);
|
|
12802
|
+
var BASE_TARGET_SCHEMA = external_exports.object({
|
|
12803
|
+
name: external_exports.string().min(1, "target name is required"),
|
|
12804
|
+
provider: external_exports.string().min(1, "provider is required"),
|
|
12805
|
+
settings: external_exports.record(external_exports.unknown()).optional(),
|
|
12806
|
+
judge_target: external_exports.string().optional(),
|
|
12807
|
+
workers: external_exports.number().int().min(1).optional()
|
|
12808
|
+
});
|
|
12809
|
+
var DEFAULT_AZURE_API_VERSION = "2024-10-01-preview";
|
|
12810
|
+
function normalizeAzureApiVersion(value) {
|
|
12811
|
+
if (!value) {
|
|
12812
|
+
return DEFAULT_AZURE_API_VERSION;
|
|
12813
|
+
}
|
|
12814
|
+
const trimmed = value.trim();
|
|
12815
|
+
if (trimmed.length === 0) {
|
|
12816
|
+
return DEFAULT_AZURE_API_VERSION;
|
|
12817
|
+
}
|
|
12818
|
+
const withoutPrefix = trimmed.replace(/^api[-_]?version\s*=\s*/i, "").trim();
|
|
12819
|
+
return withoutPrefix.length > 0 ? withoutPrefix : DEFAULT_AZURE_API_VERSION;
|
|
12820
|
+
}
|
|
12821
|
+
function resolveTargetDefinition(definition, env = process.env) {
|
|
12822
|
+
const parsed = BASE_TARGET_SCHEMA.parse(definition);
|
|
12823
|
+
const provider = parsed.provider.toLowerCase();
|
|
12824
|
+
const providerBatching = resolveOptionalBoolean(
|
|
12825
|
+
parsed.settings?.provider_batching ?? parsed.settings?.providerBatching
|
|
12826
|
+
);
|
|
12827
|
+
switch (provider) {
|
|
12828
|
+
case "azure":
|
|
12829
|
+
case "azure-openai":
|
|
12830
|
+
return {
|
|
12831
|
+
kind: "azure",
|
|
12832
|
+
name: parsed.name,
|
|
12833
|
+
judgeTarget: parsed.judge_target,
|
|
12834
|
+
workers: parsed.workers,
|
|
12835
|
+
providerBatching,
|
|
12836
|
+
config: resolveAzureConfig(parsed, env)
|
|
12837
|
+
};
|
|
12838
|
+
case "anthropic":
|
|
12839
|
+
return {
|
|
12840
|
+
kind: "anthropic",
|
|
12841
|
+
name: parsed.name,
|
|
12842
|
+
judgeTarget: parsed.judge_target,
|
|
12843
|
+
workers: parsed.workers,
|
|
12844
|
+
providerBatching,
|
|
12845
|
+
config: resolveAnthropicConfig(parsed, env)
|
|
12846
|
+
};
|
|
12847
|
+
case "gemini":
|
|
12848
|
+
case "google":
|
|
12849
|
+
case "google-gemini":
|
|
12850
|
+
return {
|
|
12851
|
+
kind: "gemini",
|
|
12852
|
+
name: parsed.name,
|
|
12853
|
+
judgeTarget: parsed.judge_target,
|
|
12854
|
+
workers: parsed.workers,
|
|
12855
|
+
providerBatching,
|
|
12856
|
+
config: resolveGeminiConfig(parsed, env)
|
|
12857
|
+
};
|
|
12858
|
+
case "codex":
|
|
12859
|
+
case "codex-cli":
|
|
12860
|
+
return {
|
|
12861
|
+
kind: "codex",
|
|
12862
|
+
name: parsed.name,
|
|
12863
|
+
judgeTarget: parsed.judge_target,
|
|
12864
|
+
workers: parsed.workers,
|
|
12865
|
+
providerBatching,
|
|
12866
|
+
config: resolveCodexConfig(parsed, env)
|
|
12867
|
+
};
|
|
12868
|
+
case "mock":
|
|
12869
|
+
return {
|
|
12870
|
+
kind: "mock",
|
|
12871
|
+
name: parsed.name,
|
|
12872
|
+
judgeTarget: parsed.judge_target,
|
|
12873
|
+
workers: parsed.workers,
|
|
12874
|
+
providerBatching,
|
|
12875
|
+
config: resolveMockConfig(parsed)
|
|
12876
|
+
};
|
|
12877
|
+
case "vscode":
|
|
12878
|
+
case "vscode-insiders":
|
|
12879
|
+
return {
|
|
12880
|
+
kind: provider,
|
|
12881
|
+
name: parsed.name,
|
|
12882
|
+
judgeTarget: parsed.judge_target,
|
|
12883
|
+
workers: parsed.workers,
|
|
12884
|
+
providerBatching,
|
|
12885
|
+
config: resolveVSCodeConfig(parsed, env, provider === "vscode-insiders")
|
|
12886
|
+
};
|
|
12887
|
+
case "cli":
|
|
12888
|
+
return {
|
|
12889
|
+
kind: "cli",
|
|
12890
|
+
name: parsed.name,
|
|
12891
|
+
judgeTarget: parsed.judge_target,
|
|
12892
|
+
workers: parsed.workers,
|
|
12893
|
+
providerBatching,
|
|
12894
|
+
config: resolveCliConfig(parsed, env)
|
|
12895
|
+
};
|
|
12896
|
+
default:
|
|
12897
|
+
throw new Error(`Unsupported provider '${parsed.provider}' in target '${parsed.name}'`);
|
|
12898
|
+
}
|
|
12695
12899
|
}
|
|
12696
|
-
function
|
|
12697
|
-
const
|
|
12698
|
-
const
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12900
|
+
function resolveAzureConfig(target, env) {
|
|
12901
|
+
const settings = target.settings ?? {};
|
|
12902
|
+
const endpointSource = settings.endpoint ?? settings.resource ?? settings.resourceName;
|
|
12903
|
+
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12904
|
+
const deploymentSource = settings.deployment ?? settings.deploymentName ?? settings.model;
|
|
12905
|
+
const versionSource = settings.version ?? settings.api_version;
|
|
12906
|
+
const temperatureSource = settings.temperature;
|
|
12907
|
+
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12908
|
+
const resourceName = resolveString(endpointSource, env, `${target.name} endpoint`);
|
|
12909
|
+
const apiKey = resolveString(apiKeySource, env, `${target.name} api key`);
|
|
12910
|
+
const deploymentName = resolveString(deploymentSource, env, `${target.name} deployment`);
|
|
12911
|
+
const version = normalizeAzureApiVersion(
|
|
12912
|
+
resolveOptionalString(versionSource, env, `${target.name} api version`)
|
|
12702
12913
|
);
|
|
12703
|
-
const
|
|
12704
|
-
const
|
|
12705
|
-
|
|
12914
|
+
const temperature = resolveOptionalNumber(temperatureSource, `${target.name} temperature`);
|
|
12915
|
+
const maxOutputTokens = resolveOptionalNumber(
|
|
12916
|
+
maxTokensSource,
|
|
12917
|
+
`${target.name} max output tokens`
|
|
12706
12918
|
);
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12919
|
+
return {
|
|
12920
|
+
resourceName,
|
|
12921
|
+
deploymentName,
|
|
12922
|
+
apiKey,
|
|
12923
|
+
version,
|
|
12924
|
+
temperature,
|
|
12925
|
+
maxOutputTokens
|
|
12926
|
+
};
|
|
12713
12927
|
}
|
|
12714
|
-
function
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
const
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12928
|
+
function resolveAnthropicConfig(target, env) {
|
|
12929
|
+
const settings = target.settings ?? {};
|
|
12930
|
+
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12931
|
+
const modelSource = settings.model ?? settings.deployment ?? settings.variant;
|
|
12932
|
+
const temperatureSource = settings.temperature;
|
|
12933
|
+
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12934
|
+
const thinkingBudgetSource = settings.thinking_budget ?? settings.thinkingBudget;
|
|
12935
|
+
const apiKey = resolveString(apiKeySource, env, `${target.name} Anthropic api key`);
|
|
12936
|
+
const model = resolveString(modelSource, env, `${target.name} Anthropic model`);
|
|
12937
|
+
return {
|
|
12938
|
+
apiKey,
|
|
12939
|
+
model,
|
|
12940
|
+
temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),
|
|
12941
|
+
maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),
|
|
12942
|
+
thinkingBudget: resolveOptionalNumber(thinkingBudgetSource, `${target.name} thinking budget`)
|
|
12943
|
+
};
|
|
12726
12944
|
}
|
|
12727
|
-
function
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
const
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
}
|
|
12745
|
-
}
|
|
12746
|
-
}
|
|
12747
|
-
return Array.from(unique.values());
|
|
12945
|
+
function resolveGeminiConfig(target, env) {
|
|
12946
|
+
const settings = target.settings ?? {};
|
|
12947
|
+
const apiKeySource = settings.api_key ?? settings.apiKey;
|
|
12948
|
+
const modelSource = settings.model ?? settings.deployment ?? settings.variant;
|
|
12949
|
+
const temperatureSource = settings.temperature;
|
|
12950
|
+
const maxTokensSource = settings.max_output_tokens ?? settings.maxTokens;
|
|
12951
|
+
const apiKey = resolveString(apiKeySource, env, `${target.name} Google API key`);
|
|
12952
|
+
const model = resolveOptionalString(modelSource, env, `${target.name} Gemini model`, {
|
|
12953
|
+
allowLiteral: true,
|
|
12954
|
+
optionalEnv: true
|
|
12955
|
+
}) ?? "gemini-2.5-flash";
|
|
12956
|
+
return {
|
|
12957
|
+
apiKey,
|
|
12958
|
+
model,
|
|
12959
|
+
temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),
|
|
12960
|
+
maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`)
|
|
12961
|
+
};
|
|
12748
12962
|
}
|
|
12749
|
-
function
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
const
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12963
|
+
function resolveCodexConfig(target, env) {
|
|
12964
|
+
const settings = target.settings ?? {};
|
|
12965
|
+
const executableSource = settings.executable ?? settings.command ?? settings.binary;
|
|
12966
|
+
const argsSource = settings.args ?? settings.arguments;
|
|
12967
|
+
const cwdSource = settings.cwd;
|
|
12968
|
+
const timeoutSource = settings.timeout_seconds ?? settings.timeoutSeconds;
|
|
12969
|
+
const logDirSource = settings.log_dir ?? settings.logDir ?? settings.log_directory ?? settings.logDirectory;
|
|
12970
|
+
const logFormatSource = settings.log_format ?? settings.logFormat ?? settings.log_output_format ?? settings.logOutputFormat ?? env.AGENTV_CODEX_LOG_FORMAT;
|
|
12971
|
+
const executable = resolveOptionalString(executableSource, env, `${target.name} codex executable`, {
|
|
12972
|
+
allowLiteral: true,
|
|
12973
|
+
optionalEnv: true
|
|
12974
|
+
}) ?? "codex";
|
|
12975
|
+
const args = resolveOptionalStringArray(argsSource, env, `${target.name} codex args`);
|
|
12976
|
+
const cwd = resolveOptionalString(cwdSource, env, `${target.name} codex cwd`, {
|
|
12977
|
+
allowLiteral: true,
|
|
12978
|
+
optionalEnv: true
|
|
12979
|
+
});
|
|
12980
|
+
const timeoutMs = resolveTimeoutMs(timeoutSource, `${target.name} codex timeout`);
|
|
12981
|
+
const logDir = resolveOptionalString(logDirSource, env, `${target.name} codex log directory`, {
|
|
12982
|
+
allowLiteral: true,
|
|
12983
|
+
optionalEnv: true
|
|
12984
|
+
});
|
|
12985
|
+
const logFormat = normalizeCodexLogFormat(logFormatSource);
|
|
12986
|
+
return {
|
|
12987
|
+
executable,
|
|
12988
|
+
args,
|
|
12989
|
+
cwd,
|
|
12990
|
+
timeoutMs,
|
|
12991
|
+
logDir,
|
|
12992
|
+
logFormat
|
|
12993
|
+
};
|
|
12761
12994
|
}
|
|
12762
|
-
function
|
|
12763
|
-
if (
|
|
12764
|
-
return
|
|
12995
|
+
function normalizeCodexLogFormat(value) {
|
|
12996
|
+
if (value === void 0 || value === null) {
|
|
12997
|
+
return void 0;
|
|
12765
12998
|
}
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
const fileUri = pathToFileUri22(absolutePath);
|
|
12769
|
-
return `* [${fileName}](${fileUri})`;
|
|
12770
|
-
});
|
|
12771
|
-
const sections = [];
|
|
12772
|
-
if (guidelineFiles.length > 0) {
|
|
12773
|
-
sections.push(`Read all guideline files:
|
|
12774
|
-
${buildList(guidelineFiles).join("\n")}.`);
|
|
12999
|
+
if (typeof value !== "string") {
|
|
13000
|
+
throw new Error("codex log format must be 'summary' or 'json'");
|
|
12775
13001
|
}
|
|
12776
|
-
|
|
12777
|
-
|
|
12778
|
-
|
|
13002
|
+
const normalized = value.trim().toLowerCase();
|
|
13003
|
+
if (normalized === "json" || normalized === "summary") {
|
|
13004
|
+
return normalized;
|
|
12779
13005
|
}
|
|
12780
|
-
|
|
12781
|
-
"If any file is missing, fail with ERROR: missing-file <filename> and stop.",
|
|
12782
|
-
"Then apply system_instructions on the user query below."
|
|
12783
|
-
);
|
|
12784
|
-
return sections.join("\n");
|
|
13006
|
+
throw new Error("codex log format must be 'summary' or 'json'");
|
|
12785
13007
|
}
|
|
12786
|
-
function
|
|
12787
|
-
const
|
|
12788
|
-
const
|
|
12789
|
-
|
|
12790
|
-
return `file:///${normalizedPath}`;
|
|
12791
|
-
}
|
|
12792
|
-
return `file://${normalizedPath}`;
|
|
13008
|
+
function resolveMockConfig(target) {
|
|
13009
|
+
const settings = target.settings ?? {};
|
|
13010
|
+
const response = typeof settings.response === "string" ? settings.response : void 0;
|
|
13011
|
+
return { response };
|
|
12793
13012
|
}
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
|
|
12813
|
-
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
12840
|
-
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
12849
|
-
|
|
12850
|
-
const assistantText = extractAssistantText(parsed);
|
|
12851
|
-
return {
|
|
12852
|
-
text: assistantText,
|
|
12853
|
-
raw: {
|
|
12854
|
-
response: parsed,
|
|
12855
|
-
stdout: result.stdout,
|
|
12856
|
-
stderr: result.stderr,
|
|
12857
|
-
exitCode: result.exitCode,
|
|
12858
|
-
args,
|
|
12859
|
-
executable: this.resolvedExecutable ?? this.config.executable,
|
|
12860
|
-
promptFile,
|
|
12861
|
-
workspace: workspaceRoot,
|
|
12862
|
-
inputFiles: mirroredInputFiles
|
|
12863
|
-
}
|
|
12864
|
-
};
|
|
12865
|
-
} finally {
|
|
12866
|
-
await this.cleanupWorkspace(workspaceRoot);
|
|
12867
|
-
}
|
|
13013
|
+
function resolveVSCodeConfig(target, env, insiders) {
|
|
13014
|
+
const settings = target.settings ?? {};
|
|
13015
|
+
const workspaceTemplateEnvVar = resolveOptionalLiteralString(settings.workspace_template ?? settings.workspaceTemplate);
|
|
13016
|
+
const workspaceTemplate = workspaceTemplateEnvVar ? resolveOptionalString(workspaceTemplateEnvVar, env, `${target.name} workspace template path`, {
|
|
13017
|
+
allowLiteral: false,
|
|
13018
|
+
optionalEnv: true
|
|
13019
|
+
}) : void 0;
|
|
13020
|
+
const commandSource = settings.vscode_cmd ?? settings.command;
|
|
13021
|
+
const waitSource = settings.wait;
|
|
13022
|
+
const dryRunSource = settings.dry_run ?? settings.dryRun;
|
|
13023
|
+
const subagentRootSource = settings.subagent_root ?? settings.subagentRoot;
|
|
13024
|
+
const defaultCommand = insiders ? "code-insiders" : "code";
|
|
13025
|
+
const command = resolveOptionalLiteralString(commandSource) ?? defaultCommand;
|
|
13026
|
+
return {
|
|
13027
|
+
command,
|
|
13028
|
+
waitForResponse: resolveOptionalBoolean(waitSource) ?? true,
|
|
13029
|
+
dryRun: resolveOptionalBoolean(dryRunSource) ?? false,
|
|
13030
|
+
subagentRoot: resolveOptionalString(subagentRootSource, env, `${target.name} subagent root`, {
|
|
13031
|
+
allowLiteral: true,
|
|
13032
|
+
optionalEnv: true
|
|
13033
|
+
}),
|
|
13034
|
+
workspaceTemplate
|
|
13035
|
+
};
|
|
13036
|
+
}
|
|
13037
|
+
function resolveCliConfig(target, env) {
|
|
13038
|
+
const settings = target.settings ?? {};
|
|
13039
|
+
const commandTemplateSource = settings.command_template ?? settings.commandTemplate;
|
|
13040
|
+
const filesFormat = resolveOptionalLiteralString(
|
|
13041
|
+
settings.files_format ?? settings.filesFormat ?? settings.attachments_format ?? settings.attachmentsFormat
|
|
13042
|
+
);
|
|
13043
|
+
const cwd = resolveOptionalString(settings.cwd, env, `${target.name} working directory`, {
|
|
13044
|
+
allowLiteral: true,
|
|
13045
|
+
optionalEnv: true
|
|
13046
|
+
});
|
|
13047
|
+
const envOverrides = resolveEnvOverrides(settings.env, env, target.name);
|
|
13048
|
+
const timeoutMs = resolveTimeoutMs(settings.timeout_seconds ?? settings.timeoutSeconds, `${target.name} timeout`);
|
|
13049
|
+
const healthcheck = resolveCliHealthcheck(settings.healthcheck, env, target.name);
|
|
13050
|
+
const commandTemplate = resolveString(
|
|
13051
|
+
commandTemplateSource,
|
|
13052
|
+
env,
|
|
13053
|
+
`${target.name} CLI command template`,
|
|
13054
|
+
true
|
|
13055
|
+
);
|
|
13056
|
+
assertSupportedCliPlaceholders(commandTemplate, `${target.name} CLI command template`);
|
|
13057
|
+
return {
|
|
13058
|
+
commandTemplate,
|
|
13059
|
+
filesFormat,
|
|
13060
|
+
cwd,
|
|
13061
|
+
env: envOverrides,
|
|
13062
|
+
timeoutMs,
|
|
13063
|
+
healthcheck
|
|
13064
|
+
};
|
|
13065
|
+
}
|
|
13066
|
+
function resolveEnvOverrides(source2, env, targetName) {
|
|
13067
|
+
if (source2 === void 0 || source2 === null) {
|
|
13068
|
+
return void 0;
|
|
12868
13069
|
}
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
13070
|
+
if (typeof source2 !== "object" || Array.isArray(source2)) {
|
|
13071
|
+
throw new Error(`${targetName} env overrides must be an object map of strings`);
|
|
13072
|
+
}
|
|
13073
|
+
const entries = Object.entries(source2);
|
|
13074
|
+
const resolved = {};
|
|
13075
|
+
for (const [key2, value] of entries) {
|
|
13076
|
+
if (typeof value !== "string") {
|
|
13077
|
+
throw new Error(`${targetName} env override '${key2}' must be a string`);
|
|
12872
13078
|
}
|
|
12873
|
-
|
|
13079
|
+
const resolvedValue = resolveString(value, env, `${targetName} env override '${key2}'`);
|
|
13080
|
+
resolved[key2] = resolvedValue;
|
|
12874
13081
|
}
|
|
12875
|
-
|
|
12876
|
-
|
|
13082
|
+
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
13083
|
+
}
|
|
13084
|
+
function resolveTimeoutMs(source2, description) {
|
|
13085
|
+
const seconds = resolveOptionalNumber(source2, `${description} (seconds)`);
|
|
13086
|
+
if (seconds === void 0) {
|
|
13087
|
+
return void 0;
|
|
12877
13088
|
}
|
|
12878
|
-
|
|
12879
|
-
|
|
12880
|
-
return workspaceRoot;
|
|
12881
|
-
}
|
|
12882
|
-
return path52.resolve(this.config.cwd);
|
|
13089
|
+
if (seconds <= 0) {
|
|
13090
|
+
throw new Error(`${description} must be greater than zero seconds`);
|
|
12883
13091
|
}
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
args.push("-");
|
|
12890
|
-
return args;
|
|
13092
|
+
return Math.floor(seconds * 1e3);
|
|
13093
|
+
}
|
|
13094
|
+
function resolveCliHealthcheck(source2, env, targetName) {
|
|
13095
|
+
if (source2 === void 0 || source2 === null) {
|
|
13096
|
+
return void 0;
|
|
12891
13097
|
}
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
return await this.runCodex({
|
|
12895
|
-
executable: this.resolvedExecutable ?? this.config.executable,
|
|
12896
|
-
args,
|
|
12897
|
-
cwd,
|
|
12898
|
-
prompt: promptContent,
|
|
12899
|
-
timeoutMs: this.config.timeoutMs,
|
|
12900
|
-
env: process.env,
|
|
12901
|
-
signal
|
|
12902
|
-
});
|
|
12903
|
-
} catch (error) {
|
|
12904
|
-
const err = error;
|
|
12905
|
-
if (err.code === "ENOENT") {
|
|
12906
|
-
throw new Error(
|
|
12907
|
-
`Codex executable '${this.config.executable}' was not found. Update the target settings.executable or add it to PATH.`
|
|
12908
|
-
);
|
|
12909
|
-
}
|
|
12910
|
-
throw error;
|
|
12911
|
-
}
|
|
13098
|
+
if (typeof source2 !== "object" || Array.isArray(source2)) {
|
|
13099
|
+
throw new Error(`${targetName} healthcheck must be an object`);
|
|
12912
13100
|
}
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
const
|
|
12921
|
-
await mkdir3(filesRoot, { recursive: true });
|
|
12922
|
-
const mirrored = [];
|
|
12923
|
-
const guidelineMirrors = /* @__PURE__ */ new Set();
|
|
12924
|
-
const nameCounts = /* @__PURE__ */ new Map();
|
|
12925
|
-
for (const inputFile of inputFiles) {
|
|
12926
|
-
const absoluteSource = path52.resolve(inputFile);
|
|
12927
|
-
const baseName = path52.basename(absoluteSource);
|
|
12928
|
-
const count = nameCounts.get(baseName) ?? 0;
|
|
12929
|
-
nameCounts.set(baseName, count + 1);
|
|
12930
|
-
const finalName = count === 0 ? baseName : `${baseName}.${count}`;
|
|
12931
|
-
const destination = path52.join(filesRoot, finalName);
|
|
12932
|
-
await copyFile2(absoluteSource, destination);
|
|
12933
|
-
const resolvedDestination = path52.resolve(destination);
|
|
12934
|
-
mirrored.push(resolvedDestination);
|
|
12935
|
-
if (guidelineOriginals.has(absoluteSource)) {
|
|
12936
|
-
guidelineMirrors.add(resolvedDestination);
|
|
12937
|
-
}
|
|
12938
|
-
}
|
|
13101
|
+
const candidate = source2;
|
|
13102
|
+
const type = candidate.type;
|
|
13103
|
+
const timeoutMs = resolveTimeoutMs(
|
|
13104
|
+
candidate.timeout_seconds ?? candidate.timeoutSeconds,
|
|
13105
|
+
`${targetName} healthcheck timeout`
|
|
13106
|
+
);
|
|
13107
|
+
if (type === "http") {
|
|
13108
|
+
const url = resolveString(candidate.url, env, `${targetName} healthcheck URL`);
|
|
12939
13109
|
return {
|
|
12940
|
-
|
|
12941
|
-
|
|
13110
|
+
type: "http",
|
|
13111
|
+
url,
|
|
13112
|
+
timeoutMs
|
|
12942
13113
|
};
|
|
12943
13114
|
}
|
|
12944
|
-
|
|
12945
|
-
|
|
13115
|
+
if (type === "command") {
|
|
13116
|
+
const commandTemplate = resolveString(
|
|
13117
|
+
candidate.command_template ?? candidate.commandTemplate,
|
|
13118
|
+
env,
|
|
13119
|
+
`${targetName} healthcheck command template`,
|
|
13120
|
+
true
|
|
13121
|
+
);
|
|
13122
|
+
assertSupportedCliPlaceholders(commandTemplate, `${targetName} healthcheck command template`);
|
|
13123
|
+
const cwd = resolveOptionalString(candidate.cwd, env, `${targetName} healthcheck cwd`, {
|
|
13124
|
+
allowLiteral: true,
|
|
13125
|
+
optionalEnv: true
|
|
13126
|
+
});
|
|
13127
|
+
return {
|
|
13128
|
+
type: "command",
|
|
13129
|
+
commandTemplate,
|
|
13130
|
+
timeoutMs,
|
|
13131
|
+
cwd
|
|
13132
|
+
};
|
|
12946
13133
|
}
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
13134
|
+
throw new Error(`${targetName} healthcheck type must be 'http' or 'command'`);
|
|
13135
|
+
}
|
|
13136
|
+
function assertSupportedCliPlaceholders(template, description) {
|
|
13137
|
+
const placeholders = extractCliPlaceholders(template);
|
|
13138
|
+
for (const placeholder of placeholders) {
|
|
13139
|
+
if (!CLI_PLACEHOLDERS.has(placeholder)) {
|
|
13140
|
+
throw new Error(
|
|
13141
|
+
`${description} includes unsupported placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(", ")}`
|
|
13142
|
+
);
|
|
12951
13143
|
}
|
|
12952
13144
|
}
|
|
12953
|
-
}
|
|
12954
|
-
|
|
12955
|
-
const
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
return executablePath;
|
|
12961
|
-
}
|
|
12962
|
-
const locator = process.platform === "win32" ? "where" : "which";
|
|
12963
|
-
try {
|
|
12964
|
-
const { stdout } = await execAsync22(`${locator} ${candidate}`);
|
|
12965
|
-
const lines = stdout.split(/\r?\n/).map((line2) => line2.trim()).filter((line2) => line2.length > 0);
|
|
12966
|
-
const preferred = selectExecutableCandidate(lines);
|
|
12967
|
-
if (preferred) {
|
|
12968
|
-
const executablePath = await ensureWindowsExecutableVariant(preferred);
|
|
12969
|
-
await access22(executablePath, constants22.F_OK);
|
|
12970
|
-
return executablePath;
|
|
13145
|
+
}
|
|
13146
|
+
function extractCliPlaceholders(template) {
|
|
13147
|
+
const matches = template.matchAll(/\{([A-Z_]+)\}/g);
|
|
13148
|
+
const results = [];
|
|
13149
|
+
for (const match of matches) {
|
|
13150
|
+
if (match[1]) {
|
|
13151
|
+
results.push(match[1]);
|
|
12971
13152
|
}
|
|
12972
|
-
} catch {
|
|
12973
13153
|
}
|
|
12974
|
-
|
|
13154
|
+
return results;
|
|
12975
13155
|
}
|
|
12976
|
-
function
|
|
12977
|
-
|
|
13156
|
+
function resolveString(source2, env, description, allowLiteral = false) {
|
|
13157
|
+
const value = resolveOptionalString(source2, env, description, {
|
|
13158
|
+
allowLiteral,
|
|
13159
|
+
optionalEnv: false
|
|
13160
|
+
});
|
|
13161
|
+
if (value === void 0) {
|
|
13162
|
+
throw new Error(`${description} is required`);
|
|
13163
|
+
}
|
|
13164
|
+
return value;
|
|
13165
|
+
}
|
|
13166
|
+
function resolveOptionalString(source2, env, description, options) {
|
|
13167
|
+
if (source2 === void 0 || source2 === null) {
|
|
12978
13168
|
return void 0;
|
|
12979
13169
|
}
|
|
12980
|
-
if (
|
|
12981
|
-
|
|
13170
|
+
if (typeof source2 !== "string") {
|
|
13171
|
+
throw new Error(`${description} must be a string`);
|
|
12982
13172
|
}
|
|
12983
|
-
const
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
13173
|
+
const trimmed = source2.trim();
|
|
13174
|
+
if (trimmed.length === 0) {
|
|
13175
|
+
return void 0;
|
|
13176
|
+
}
|
|
13177
|
+
const envValue = env[trimmed];
|
|
13178
|
+
if (envValue !== void 0) {
|
|
13179
|
+
if (envValue.trim().length === 0) {
|
|
13180
|
+
throw new Error(`Environment variable '${trimmed}' for ${description} is empty`);
|
|
12988
13181
|
}
|
|
13182
|
+
return envValue;
|
|
12989
13183
|
}
|
|
12990
|
-
|
|
13184
|
+
const allowLiteral = options?.allowLiteral ?? false;
|
|
13185
|
+
const optionalEnv = options?.optionalEnv ?? false;
|
|
13186
|
+
const looksLikeEnv = isLikelyEnvReference(trimmed);
|
|
13187
|
+
if (looksLikeEnv) {
|
|
13188
|
+
if (optionalEnv) {
|
|
13189
|
+
return void 0;
|
|
13190
|
+
}
|
|
13191
|
+
if (!allowLiteral) {
|
|
13192
|
+
throw new Error(`Environment variable '${trimmed}' required for ${description} is not set`);
|
|
13193
|
+
}
|
|
13194
|
+
}
|
|
13195
|
+
return trimmed;
|
|
13196
|
+
}
|
|
13197
|
+
function resolveOptionalLiteralString(source2) {
|
|
13198
|
+
if (source2 === void 0 || source2 === null) {
|
|
13199
|
+
return void 0;
|
|
13200
|
+
}
|
|
13201
|
+
if (typeof source2 !== "string") {
|
|
13202
|
+
throw new Error("expected string value");
|
|
13203
|
+
}
|
|
13204
|
+
const trimmed = source2.trim();
|
|
13205
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
12991
13206
|
}
|
|
12992
|
-
|
|
12993
|
-
if (
|
|
12994
|
-
return
|
|
13207
|
+
function resolveOptionalNumber(source2, description) {
|
|
13208
|
+
if (source2 === void 0 || source2 === null || source2 === "") {
|
|
13209
|
+
return void 0;
|
|
12995
13210
|
}
|
|
12996
|
-
if (
|
|
12997
|
-
return
|
|
13211
|
+
if (typeof source2 === "number") {
|
|
13212
|
+
return Number.isFinite(source2) ? source2 : void 0;
|
|
12998
13213
|
}
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
await access22(withExtension, constants22.F_OK);
|
|
13004
|
-
return withExtension;
|
|
13005
|
-
} catch {
|
|
13214
|
+
if (typeof source2 === "string") {
|
|
13215
|
+
const numeric = Number(source2);
|
|
13216
|
+
if (Number.isFinite(numeric)) {
|
|
13217
|
+
return numeric;
|
|
13006
13218
|
}
|
|
13007
13219
|
}
|
|
13008
|
-
|
|
13009
|
-
}
|
|
13010
|
-
function hasExecutableExtension(candidate) {
|
|
13011
|
-
const lower = candidate.toLowerCase();
|
|
13012
|
-
return getWindowsExecutableExtensions().some((ext) => lower.endsWith(ext));
|
|
13220
|
+
throw new Error(`${description} must be a number`);
|
|
13013
13221
|
}
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
return [];
|
|
13222
|
+
function resolveOptionalBoolean(source2) {
|
|
13223
|
+
if (source2 === void 0 || source2 === null || source2 === "") {
|
|
13224
|
+
return void 0;
|
|
13018
13225
|
}
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
}
|
|
13022
|
-
function parseCodexJson(output) {
|
|
13023
|
-
const trimmed = output.trim();
|
|
13024
|
-
if (trimmed.length === 0) {
|
|
13025
|
-
throw new Error("Codex CLI produced no output in --json mode");
|
|
13226
|
+
if (typeof source2 === "boolean") {
|
|
13227
|
+
return source2;
|
|
13026
13228
|
}
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
if (lineObjects) {
|
|
13032
|
-
return lineObjects;
|
|
13229
|
+
if (typeof source2 === "string") {
|
|
13230
|
+
const lowered = source2.trim().toLowerCase();
|
|
13231
|
+
if (lowered === "true" || lowered === "1") {
|
|
13232
|
+
return true;
|
|
13033
13233
|
}
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
const candidate = trimmed.slice(lastBrace);
|
|
13037
|
-
try {
|
|
13038
|
-
return JSON.parse(candidate);
|
|
13039
|
-
} catch {
|
|
13040
|
-
}
|
|
13234
|
+
if (lowered === "false" || lowered === "0") {
|
|
13235
|
+
return false;
|
|
13041
13236
|
}
|
|
13042
|
-
const preview = trimmed.slice(0, 200);
|
|
13043
|
-
throw new Error(`Codex CLI emitted invalid JSON: ${preview}${trimmed.length > 200 ? "\u2026" : ""}`);
|
|
13044
13237
|
}
|
|
13238
|
+
throw new Error("expected boolean value");
|
|
13045
13239
|
}
|
|
13046
|
-
function
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13240
|
+
function isLikelyEnvReference(value) {
|
|
13241
|
+
return /^[A-Z0-9_]+$/.test(value);
|
|
13242
|
+
}
|
|
13243
|
+
function resolveOptionalStringArray(source2, env, description) {
|
|
13244
|
+
if (source2 === void 0 || source2 === null) {
|
|
13245
|
+
return void 0;
|
|
13052
13246
|
}
|
|
13053
|
-
if (!
|
|
13054
|
-
throw new Error(
|
|
13247
|
+
if (!Array.isArray(source2)) {
|
|
13248
|
+
throw new Error(`${description} must be an array of strings`);
|
|
13055
13249
|
}
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
if (eventText) {
|
|
13059
|
-
return eventText;
|
|
13250
|
+
if (source2.length === 0) {
|
|
13251
|
+
return void 0;
|
|
13060
13252
|
}
|
|
13061
|
-
const
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
continue;
|
|
13067
|
-
}
|
|
13068
|
-
const role = entry.role;
|
|
13069
|
-
if (role !== "assistant") {
|
|
13070
|
-
continue;
|
|
13071
|
-
}
|
|
13072
|
-
const content = entry.content;
|
|
13073
|
-
const flattened = flattenContent(content);
|
|
13074
|
-
if (flattened) {
|
|
13075
|
-
return flattened;
|
|
13076
|
-
}
|
|
13253
|
+
const resolved = [];
|
|
13254
|
+
for (let i6 = 0; i6 < source2.length; i6++) {
|
|
13255
|
+
const item = source2[i6];
|
|
13256
|
+
if (typeof item !== "string") {
|
|
13257
|
+
throw new Error(`${description}[${i6}] must be a string`);
|
|
13077
13258
|
}
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
const content = response.content;
|
|
13082
|
-
const flattened = flattenContent(content);
|
|
13083
|
-
if (flattened) {
|
|
13084
|
-
return flattened;
|
|
13259
|
+
const trimmed = item.trim();
|
|
13260
|
+
if (trimmed.length === 0) {
|
|
13261
|
+
throw new Error(`${description}[${i6}] cannot be empty`);
|
|
13085
13262
|
}
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
function extractFromEventStream(events) {
|
|
13095
|
-
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
13096
|
-
const candidate = events[index];
|
|
13097
|
-
const text = extractFromEvent(candidate);
|
|
13098
|
-
if (text) {
|
|
13099
|
-
return text;
|
|
13263
|
+
const envValue = env[trimmed];
|
|
13264
|
+
if (envValue !== void 0) {
|
|
13265
|
+
if (envValue.trim().length === 0) {
|
|
13266
|
+
throw new Error(`Environment variable '${trimmed}' for ${description}[${i6}] is empty`);
|
|
13267
|
+
}
|
|
13268
|
+
resolved.push(envValue);
|
|
13269
|
+
} else {
|
|
13270
|
+
resolved.push(trimmed);
|
|
13100
13271
|
}
|
|
13101
13272
|
}
|
|
13102
|
-
return void 0;
|
|
13273
|
+
return resolved.length > 0 ? resolved : void 0;
|
|
13103
13274
|
}
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13275
|
+
var VSCodeProvider = class {
|
|
13276
|
+
id;
|
|
13277
|
+
kind;
|
|
13278
|
+
targetName;
|
|
13279
|
+
supportsBatch = true;
|
|
13280
|
+
config;
|
|
13281
|
+
constructor(targetName, config, kind) {
|
|
13282
|
+
this.id = `${kind}:${targetName}`;
|
|
13283
|
+
this.kind = kind;
|
|
13284
|
+
this.targetName = targetName;
|
|
13285
|
+
this.config = config;
|
|
13107
13286
|
}
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
const
|
|
13113
|
-
|
|
13114
|
-
|
|
13287
|
+
async invoke(request) {
|
|
13288
|
+
if (request.signal?.aborted) {
|
|
13289
|
+
throw new Error("VS Code provider request was aborted before dispatch");
|
|
13290
|
+
}
|
|
13291
|
+
const inputFiles = normalizeAttachments(request.inputFiles);
|
|
13292
|
+
const promptContent = buildPromptDocument2(request, inputFiles, request.guideline_patterns);
|
|
13293
|
+
const session = await dispatchAgentSession({
|
|
13294
|
+
userQuery: promptContent,
|
|
13295
|
+
extraAttachments: inputFiles,
|
|
13296
|
+
wait: this.config.waitForResponse,
|
|
13297
|
+
dryRun: this.config.dryRun,
|
|
13298
|
+
vscodeCmd: this.config.command,
|
|
13299
|
+
subagentRoot: this.config.subagentRoot,
|
|
13300
|
+
workspaceTemplate: this.config.workspaceTemplate,
|
|
13301
|
+
silent: true
|
|
13302
|
+
});
|
|
13303
|
+
if (session.exitCode !== 0 || !session.responseFile) {
|
|
13304
|
+
const failure = session.error ?? "VS Code subagent did not produce a response";
|
|
13305
|
+
throw new Error(failure);
|
|
13306
|
+
}
|
|
13307
|
+
if (this.config.dryRun) {
|
|
13308
|
+
return {
|
|
13309
|
+
text: "",
|
|
13310
|
+
raw: {
|
|
13311
|
+
session,
|
|
13312
|
+
inputFiles
|
|
13313
|
+
}
|
|
13314
|
+
};
|
|
13115
13315
|
}
|
|
13316
|
+
const responseText = await readFile22(session.responseFile, "utf8");
|
|
13317
|
+
return {
|
|
13318
|
+
text: responseText,
|
|
13319
|
+
raw: {
|
|
13320
|
+
session,
|
|
13321
|
+
inputFiles
|
|
13322
|
+
}
|
|
13323
|
+
};
|
|
13116
13324
|
}
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13325
|
+
async invokeBatch(requests) {
|
|
13326
|
+
if (requests.length === 0) {
|
|
13327
|
+
return [];
|
|
13328
|
+
}
|
|
13329
|
+
const normalizedRequests = requests.map((req) => ({
|
|
13330
|
+
request: req,
|
|
13331
|
+
inputFiles: normalizeAttachments(req.inputFiles)
|
|
13332
|
+
}));
|
|
13333
|
+
const combinedInputFiles = mergeAttachments(
|
|
13334
|
+
normalizedRequests.map(({ inputFiles }) => inputFiles)
|
|
13335
|
+
);
|
|
13336
|
+
const userQueries = normalizedRequests.map(
|
|
13337
|
+
({ request, inputFiles }) => buildPromptDocument2(request, inputFiles, request.guideline_patterns)
|
|
13338
|
+
);
|
|
13339
|
+
const session = await dispatchBatchAgent({
|
|
13340
|
+
userQueries,
|
|
13341
|
+
extraAttachments: combinedInputFiles,
|
|
13342
|
+
wait: this.config.waitForResponse,
|
|
13343
|
+
dryRun: this.config.dryRun,
|
|
13344
|
+
vscodeCmd: this.config.command,
|
|
13345
|
+
subagentRoot: this.config.subagentRoot,
|
|
13346
|
+
workspaceTemplate: this.config.workspaceTemplate,
|
|
13347
|
+
silent: true
|
|
13348
|
+
});
|
|
13349
|
+
if (session.exitCode !== 0 || !session.responseFiles) {
|
|
13350
|
+
const failure = session.error ?? "VS Code subagent did not produce batch responses";
|
|
13351
|
+
throw new Error(failure);
|
|
13352
|
+
}
|
|
13353
|
+
if (this.config.dryRun) {
|
|
13354
|
+
return normalizedRequests.map(({ inputFiles }) => ({
|
|
13355
|
+
text: "",
|
|
13356
|
+
raw: {
|
|
13357
|
+
session,
|
|
13358
|
+
inputFiles,
|
|
13359
|
+
allInputFiles: combinedInputFiles
|
|
13360
|
+
}
|
|
13361
|
+
}));
|
|
13362
|
+
}
|
|
13363
|
+
if (session.responseFiles.length !== requests.length) {
|
|
13364
|
+
throw new Error(
|
|
13365
|
+
`VS Code batch returned ${session.responseFiles.length} responses for ${requests.length} requests`
|
|
13366
|
+
);
|
|
13367
|
+
}
|
|
13368
|
+
const responses = [];
|
|
13369
|
+
for (const [index, responseFile] of session.responseFiles.entries()) {
|
|
13370
|
+
const responseText = await readFile22(responseFile, "utf8");
|
|
13371
|
+
responses.push({
|
|
13372
|
+
text: responseText,
|
|
13373
|
+
raw: {
|
|
13374
|
+
session,
|
|
13375
|
+
inputFiles: normalizedRequests[index]?.inputFiles,
|
|
13376
|
+
allInputFiles: combinedInputFiles,
|
|
13377
|
+
responseFile
|
|
13378
|
+
}
|
|
13379
|
+
});
|
|
13380
|
+
}
|
|
13381
|
+
return responses;
|
|
13121
13382
|
}
|
|
13122
|
-
|
|
13383
|
+
};
|
|
13384
|
+
function buildPromptDocument2(request, attachments, guidelinePatterns) {
|
|
13385
|
+
const parts = [];
|
|
13386
|
+
const guidelineFiles = collectGuidelineFiles2(attachments, guidelinePatterns);
|
|
13387
|
+
const attachmentFiles = collectAttachmentFiles(attachments);
|
|
13388
|
+
const nonGuidelineAttachments = attachmentFiles.filter(
|
|
13389
|
+
(file) => !guidelineFiles.includes(file)
|
|
13390
|
+
);
|
|
13391
|
+
const prereadBlock = buildMandatoryPrereadBlock2(guidelineFiles, nonGuidelineAttachments);
|
|
13392
|
+
if (prereadBlock.length > 0) {
|
|
13393
|
+
parts.push("\n", prereadBlock);
|
|
13394
|
+
}
|
|
13395
|
+
parts.push("\n[[ ## user_query ## ]]\n", request.prompt.trim());
|
|
13396
|
+
return parts.join("\n").trim();
|
|
13123
13397
|
}
|
|
13124
|
-
function
|
|
13125
|
-
if (
|
|
13126
|
-
return
|
|
13398
|
+
function buildMandatoryPrereadBlock2(guidelineFiles, attachmentFiles) {
|
|
13399
|
+
if (guidelineFiles.length === 0 && attachmentFiles.length === 0) {
|
|
13400
|
+
return "";
|
|
13127
13401
|
}
|
|
13128
|
-
const
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13402
|
+
const buildList = (files) => files.map((absolutePath) => {
|
|
13403
|
+
const fileName = path52.basename(absolutePath);
|
|
13404
|
+
const fileUri = pathToFileUri22(absolutePath);
|
|
13405
|
+
return `* [${fileName}](${fileUri})`;
|
|
13406
|
+
});
|
|
13407
|
+
const sections = [];
|
|
13408
|
+
if (guidelineFiles.length > 0) {
|
|
13409
|
+
sections.push(`Read all guideline files:
|
|
13410
|
+
${buildList(guidelineFiles).join("\n")}.`);
|
|
13135
13411
|
}
|
|
13136
|
-
|
|
13412
|
+
if (attachmentFiles.length > 0) {
|
|
13413
|
+
sections.push(`Read all attachment files:
|
|
13414
|
+
${buildList(attachmentFiles).join("\n")}.`);
|
|
13415
|
+
}
|
|
13416
|
+
sections.push(
|
|
13417
|
+
"If any file is missing, fail with ERROR: missing-file <filename> and stop.",
|
|
13418
|
+
"Then apply system_instructions on the user query below."
|
|
13419
|
+
);
|
|
13420
|
+
return sections.join("\n");
|
|
13137
13421
|
}
|
|
13138
|
-
function
|
|
13139
|
-
if (
|
|
13140
|
-
return
|
|
13422
|
+
function collectGuidelineFiles2(attachments, guidelinePatterns) {
|
|
13423
|
+
if (!attachments || attachments.length === 0) {
|
|
13424
|
+
return [];
|
|
13141
13425
|
}
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
if (
|
|
13148
|
-
|
|
13149
|
-
return typeof text === "string" ? text : void 0;
|
|
13426
|
+
const unique = /* @__PURE__ */ new Map();
|
|
13427
|
+
for (const attachment of attachments) {
|
|
13428
|
+
const absolutePath = path52.resolve(attachment);
|
|
13429
|
+
const normalized = absolutePath.split(path52.sep).join("/");
|
|
13430
|
+
if (isGuidelineFile(normalized, guidelinePatterns)) {
|
|
13431
|
+
if (!unique.has(absolutePath)) {
|
|
13432
|
+
unique.set(absolutePath, absolutePath);
|
|
13150
13433
|
}
|
|
13151
|
-
|
|
13152
|
-
}).filter((part) => typeof part === "string" && part.length > 0);
|
|
13153
|
-
return parts.length > 0 ? parts.join(" \n") : void 0;
|
|
13154
|
-
}
|
|
13155
|
-
if (value && typeof value === "object" && "text" in value) {
|
|
13156
|
-
const text = value.text;
|
|
13157
|
-
return typeof text === "string" ? text : void 0;
|
|
13434
|
+
}
|
|
13158
13435
|
}
|
|
13159
|
-
return
|
|
13436
|
+
return Array.from(unique.values());
|
|
13160
13437
|
}
|
|
13161
|
-
function
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
return void 0;
|
|
13438
|
+
function collectAttachmentFiles(attachments) {
|
|
13439
|
+
if (!attachments || attachments.length === 0) {
|
|
13440
|
+
return [];
|
|
13165
13441
|
}
|
|
13166
|
-
const
|
|
13167
|
-
for (const
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
return void 0;
|
|
13442
|
+
const unique = /* @__PURE__ */ new Map();
|
|
13443
|
+
for (const attachment of attachments) {
|
|
13444
|
+
const absolutePath = path52.resolve(attachment);
|
|
13445
|
+
if (!unique.has(absolutePath)) {
|
|
13446
|
+
unique.set(absolutePath, absolutePath);
|
|
13172
13447
|
}
|
|
13173
13448
|
}
|
|
13174
|
-
return
|
|
13449
|
+
return Array.from(unique.values());
|
|
13175
13450
|
}
|
|
13176
|
-
function
|
|
13177
|
-
const
|
|
13178
|
-
|
|
13179
|
-
|
|
13451
|
+
function pathToFileUri22(filePath) {
|
|
13452
|
+
const absolutePath = path52.isAbsolute(filePath) ? filePath : path52.resolve(filePath);
|
|
13453
|
+
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
13454
|
+
if (/^[a-zA-Z]:\//.test(normalizedPath)) {
|
|
13455
|
+
return `file:///${normalizedPath}`;
|
|
13180
13456
|
}
|
|
13181
|
-
|
|
13182
|
-
return stdoutText.length > 0 ? stdoutText : void 0;
|
|
13457
|
+
return `file://${normalizedPath}`;
|
|
13183
13458
|
}
|
|
13184
|
-
function
|
|
13185
|
-
if (!
|
|
13186
|
-
return
|
|
13459
|
+
function normalizeAttachments(attachments) {
|
|
13460
|
+
if (!attachments || attachments.length === 0) {
|
|
13461
|
+
return void 0;
|
|
13187
13462
|
}
|
|
13188
|
-
const
|
|
13189
|
-
|
|
13463
|
+
const deduped = /* @__PURE__ */ new Set();
|
|
13464
|
+
for (const attachment of attachments) {
|
|
13465
|
+
deduped.add(path52.resolve(attachment));
|
|
13466
|
+
}
|
|
13467
|
+
return Array.from(deduped);
|
|
13190
13468
|
}
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
shell: shouldShellExecute(options.executable)
|
|
13198
|
-
});
|
|
13199
|
-
let stdout = "";
|
|
13200
|
-
let stderr = "";
|
|
13201
|
-
let timedOut = false;
|
|
13202
|
-
const onAbort = () => {
|
|
13203
|
-
child.kill("SIGTERM");
|
|
13204
|
-
};
|
|
13205
|
-
if (options.signal) {
|
|
13206
|
-
if (options.signal.aborted) {
|
|
13207
|
-
onAbort();
|
|
13208
|
-
} else {
|
|
13209
|
-
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
13210
|
-
}
|
|
13469
|
+
function mergeAttachments(all) {
|
|
13470
|
+
const deduped = /* @__PURE__ */ new Set();
|
|
13471
|
+
for (const list of all) {
|
|
13472
|
+
if (!list) continue;
|
|
13473
|
+
for (const inputFile of list) {
|
|
13474
|
+
deduped.add(path52.resolve(inputFile));
|
|
13211
13475
|
}
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13476
|
+
}
|
|
13477
|
+
return deduped.size > 0 ? Array.from(deduped) : void 0;
|
|
13478
|
+
}
|
|
13479
|
+
async function ensureVSCodeSubagents(options) {
|
|
13480
|
+
const { kind, count, verbose = false } = options;
|
|
13481
|
+
const vscodeCmd = kind === "vscode-insiders" ? "code-insiders" : "code";
|
|
13482
|
+
const subagentRoot = getSubagentRoot(vscodeCmd);
|
|
13483
|
+
try {
|
|
13484
|
+
if (verbose) {
|
|
13485
|
+
console.log(`Provisioning ${count} subagent(s) via: subagent ${vscodeCmd} provision`);
|
|
13219
13486
|
}
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
child.stderr.setEncoding("utf8");
|
|
13225
|
-
child.stderr.on("data", (chunk) => {
|
|
13226
|
-
stderr += chunk;
|
|
13487
|
+
const result = await provisionSubagents({
|
|
13488
|
+
targetRoot: subagentRoot,
|
|
13489
|
+
subagents: count,
|
|
13490
|
+
dryRun: false
|
|
13227
13491
|
});
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
clearTimeout(timeoutHandle);
|
|
13492
|
+
if (verbose) {
|
|
13493
|
+
if (result.created.length > 0) {
|
|
13494
|
+
console.log(`Created ${result.created.length} new subagent(s)`);
|
|
13232
13495
|
}
|
|
13233
|
-
if (
|
|
13234
|
-
|
|
13496
|
+
if (result.skippedExisting.length > 0) {
|
|
13497
|
+
console.log(`Reusing ${result.skippedExisting.length} existing unlocked subagent(s)`);
|
|
13235
13498
|
}
|
|
13499
|
+
console.log(`
|
|
13500
|
+
total unlocked subagents available: ${result.created.length + result.skippedExisting.length}`);
|
|
13501
|
+
}
|
|
13502
|
+
return {
|
|
13503
|
+
provisioned: true,
|
|
13504
|
+
message: `Provisioned ${count} subagent(s): ${result.created.length} created, ${result.skippedExisting.length} reused`
|
|
13505
|
+
};
|
|
13506
|
+
} catch (error) {
|
|
13507
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
13508
|
+
if (verbose) {
|
|
13509
|
+
console.warn(`Provisioning failed (continuing anyway): ${errorMessage}`);
|
|
13510
|
+
}
|
|
13511
|
+
return {
|
|
13512
|
+
provisioned: false,
|
|
13513
|
+
message: `Provisioning failed: ${errorMessage}`
|
|
13236
13514
|
};
|
|
13237
|
-
child.on("error", (error) => {
|
|
13238
|
-
cleanup();
|
|
13239
|
-
reject(error);
|
|
13240
|
-
});
|
|
13241
|
-
child.on("close", (code) => {
|
|
13242
|
-
cleanup();
|
|
13243
|
-
resolve({
|
|
13244
|
-
stdout,
|
|
13245
|
-
stderr,
|
|
13246
|
-
exitCode: typeof code === "number" ? code : -1,
|
|
13247
|
-
timedOut
|
|
13248
|
-
});
|
|
13249
|
-
});
|
|
13250
|
-
});
|
|
13251
|
-
}
|
|
13252
|
-
function shouldShellExecute(executable) {
|
|
13253
|
-
if (process.platform !== "win32") {
|
|
13254
|
-
return false;
|
|
13255
13515
|
}
|
|
13256
|
-
const lower = executable.toLowerCase();
|
|
13257
|
-
return lower.endsWith(".cmd") || lower.endsWith(".bat") || lower.endsWith(".ps1");
|
|
13258
13516
|
}
|
|
13259
13517
|
function isRecord(value) {
|
|
13260
13518
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -13394,7 +13652,7 @@ var LlmJudgeEvaluator = class {
|
|
|
13394
13652
|
const misses = Array.isArray(parsed.misses) ? parsed.misses.filter(isNonEmptyString).slice(0, 4) : [];
|
|
13395
13653
|
const reasoning = parsed.reasoning ?? response.reasoning;
|
|
13396
13654
|
const evaluatorRawRequest = {
|
|
13397
|
-
id:
|
|
13655
|
+
id: randomUUID2(),
|
|
13398
13656
|
provider: judgeProvider.id,
|
|
13399
13657
|
prompt,
|
|
13400
13658
|
target: context2.target.name,
|
|
@@ -14395,7 +14653,7 @@ function sanitizeFilename(value) {
|
|
|
14395
14653
|
return "prompt";
|
|
14396
14654
|
}
|
|
14397
14655
|
const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
14398
|
-
return sanitized.length > 0 ? sanitized :
|
|
14656
|
+
return sanitized.length > 0 ? sanitized : randomUUID3();
|
|
14399
14657
|
}
|
|
14400
14658
|
async function invokeProvider(provider, options) {
|
|
14401
14659
|
const { evalCase, promptInputs, attempt, agentTimeoutMs, signal } = options;
|
|
@@ -14756,7 +15014,7 @@ var Mutex = class {
|
|
|
14756
15014
|
};
|
|
14757
15015
|
|
|
14758
15016
|
// src/commands/eval/jsonl-writer.ts
|
|
14759
|
-
import { createWriteStream } from "node:fs";
|
|
15017
|
+
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
14760
15018
|
import { mkdir as mkdir4 } from "node:fs/promises";
|
|
14761
15019
|
import path10 from "node:path";
|
|
14762
15020
|
import { finished } from "node:stream/promises";
|
|
@@ -14769,7 +15027,7 @@ var JsonlWriter = class _JsonlWriter {
|
|
|
14769
15027
|
}
|
|
14770
15028
|
static async open(filePath) {
|
|
14771
15029
|
await mkdir4(path10.dirname(filePath), { recursive: true });
|
|
14772
|
-
const stream =
|
|
15030
|
+
const stream = createWriteStream2(filePath, { flags: "w", encoding: "utf8" });
|
|
14773
15031
|
return new _JsonlWriter(stream);
|
|
14774
15032
|
}
|
|
14775
15033
|
async append(record) {
|
|
@@ -14798,7 +15056,7 @@ var JsonlWriter = class _JsonlWriter {
|
|
|
14798
15056
|
};
|
|
14799
15057
|
|
|
14800
15058
|
// src/commands/eval/yaml-writer.ts
|
|
14801
|
-
import { createWriteStream as
|
|
15059
|
+
import { createWriteStream as createWriteStream3 } from "node:fs";
|
|
14802
15060
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
14803
15061
|
import path11 from "node:path";
|
|
14804
15062
|
import { finished as finished2 } from "node:stream/promises";
|
|
@@ -14813,7 +15071,7 @@ var YamlWriter = class _YamlWriter {
|
|
|
14813
15071
|
}
|
|
14814
15072
|
static async open(filePath) {
|
|
14815
15073
|
await mkdir5(path11.dirname(filePath), { recursive: true });
|
|
14816
|
-
const stream =
|
|
15074
|
+
const stream = createWriteStream3(filePath, { flags: "w", encoding: "utf8" });
|
|
14817
15075
|
return new _YamlWriter(stream);
|
|
14818
15076
|
}
|
|
14819
15077
|
async append(record) {
|
|
@@ -15269,7 +15527,7 @@ function normalizeNumber(value, fallback) {
|
|
|
15269
15527
|
return fallback;
|
|
15270
15528
|
}
|
|
15271
15529
|
function normalizeOptions(rawOptions) {
|
|
15272
|
-
const formatStr = normalizeString(rawOptions.
|
|
15530
|
+
const formatStr = normalizeString(rawOptions.outputFormat) ?? "jsonl";
|
|
15273
15531
|
const format = formatStr === "yaml" ? "yaml" : "jsonl";
|
|
15274
15532
|
const workers = normalizeNumber(rawOptions.workers, 0);
|
|
15275
15533
|
return {
|
|
@@ -15489,7 +15747,11 @@ function registerEvalCommand(program) {
|
|
|
15489
15747
|
"--workers <count>",
|
|
15490
15748
|
"Number of parallel workers (default: 1, max: 50). Can also be set per-target in targets.yaml",
|
|
15491
15749
|
(value) => parseInteger(value, 1)
|
|
15492
|
-
).option("--out <path>", "Write results to the specified path").option(
|
|
15750
|
+
).option("--out <path>", "Write results to the specified path").option(
|
|
15751
|
+
"--output-format <format>",
|
|
15752
|
+
"Output format: 'jsonl' or 'yaml' (default: jsonl)",
|
|
15753
|
+
"jsonl"
|
|
15754
|
+
).option("--dry-run", "Use mock provider responses instead of real LLM calls", false).option(
|
|
15493
15755
|
"--dry-run-delay <ms>",
|
|
15494
15756
|
"Fixed delay in milliseconds for dry-run mode (overridden by delay range if specified)",
|
|
15495
15757
|
(value) => parseInteger(value, 0),
|
|
@@ -15526,58 +15788,105 @@ function registerEvalCommand(program) {
|
|
|
15526
15788
|
// src/commands/init/index.ts
|
|
15527
15789
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
15528
15790
|
import path15 from "node:path";
|
|
15791
|
+
import * as readline from "node:readline/promises";
|
|
15529
15792
|
|
|
15530
15793
|
// src/templates/index.ts
|
|
15531
|
-
import { readFileSync } from "node:fs";
|
|
15794
|
+
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
15532
15795
|
import path14 from "node:path";
|
|
15533
15796
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
15534
15797
|
var TemplateManager = class {
|
|
15535
|
-
static
|
|
15798
|
+
static getGithubTemplates() {
|
|
15799
|
+
return this.getTemplatesFromDir("github");
|
|
15800
|
+
}
|
|
15801
|
+
static getAgentvTemplates() {
|
|
15802
|
+
return this.getTemplatesFromDir("agentv");
|
|
15803
|
+
}
|
|
15804
|
+
static getTemplatesFromDir(subdir) {
|
|
15536
15805
|
const currentDir = path14.dirname(fileURLToPath2(import.meta.url));
|
|
15537
15806
|
let templatesDir;
|
|
15538
15807
|
if (currentDir.includes(path14.sep + "dist")) {
|
|
15539
|
-
templatesDir = path14.join(currentDir, "templates");
|
|
15808
|
+
templatesDir = path14.join(currentDir, "templates", subdir);
|
|
15540
15809
|
} else {
|
|
15541
|
-
templatesDir = currentDir;
|
|
15810
|
+
templatesDir = path14.join(currentDir, subdir);
|
|
15542
15811
|
}
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15546
|
-
|
|
15547
|
-
const
|
|
15548
|
-
|
|
15549
|
-
|
|
15550
|
-
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
path: "contexts/eval-schema.json",
|
|
15562
|
-
content: evalSchema
|
|
15563
|
-
},
|
|
15564
|
-
{
|
|
15565
|
-
path: "contexts/config-schema.json",
|
|
15566
|
-
content: configSchema
|
|
15812
|
+
return this.readTemplatesRecursively(templatesDir, "");
|
|
15813
|
+
}
|
|
15814
|
+
static readTemplatesRecursively(dir, relativePath) {
|
|
15815
|
+
const templates = [];
|
|
15816
|
+
const entries = readdirSync(dir);
|
|
15817
|
+
for (const entry of entries) {
|
|
15818
|
+
const fullPath = path14.join(dir, entry);
|
|
15819
|
+
const stat4 = statSync(fullPath);
|
|
15820
|
+
const entryRelativePath = relativePath ? path14.join(relativePath, entry) : entry;
|
|
15821
|
+
if (stat4.isDirectory()) {
|
|
15822
|
+
templates.push(...this.readTemplatesRecursively(fullPath, entryRelativePath));
|
|
15823
|
+
} else {
|
|
15824
|
+
const content = readFileSync(fullPath, "utf-8");
|
|
15825
|
+
templates.push({
|
|
15826
|
+
path: entryRelativePath.split(path14.sep).join("/"),
|
|
15827
|
+
// Normalize to forward slashes
|
|
15828
|
+
content
|
|
15829
|
+
});
|
|
15567
15830
|
}
|
|
15568
|
-
|
|
15831
|
+
}
|
|
15832
|
+
return templates;
|
|
15569
15833
|
}
|
|
15570
15834
|
};
|
|
15571
15835
|
|
|
15572
15836
|
// src/commands/init/index.ts
|
|
15837
|
+
async function promptYesNo(message) {
|
|
15838
|
+
const rl = readline.createInterface({
|
|
15839
|
+
input: process.stdin,
|
|
15840
|
+
output: process.stdout
|
|
15841
|
+
});
|
|
15842
|
+
try {
|
|
15843
|
+
const answer = await rl.question(`${message} (y/N): `);
|
|
15844
|
+
return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
15845
|
+
} finally {
|
|
15846
|
+
rl.close();
|
|
15847
|
+
}
|
|
15848
|
+
}
|
|
15573
15849
|
async function initCommand(options = {}) {
|
|
15574
15850
|
const targetPath = path15.resolve(options.targetPath ?? ".");
|
|
15575
15851
|
const githubDir = path15.join(targetPath, ".github");
|
|
15852
|
+
const agentvDir = path15.join(targetPath, ".agentv");
|
|
15853
|
+
const githubTemplates = TemplateManager.getGithubTemplates();
|
|
15854
|
+
const agentvTemplates = TemplateManager.getAgentvTemplates();
|
|
15855
|
+
const existingFiles = [];
|
|
15856
|
+
if (existsSync(githubDir)) {
|
|
15857
|
+
for (const template of githubTemplates) {
|
|
15858
|
+
const targetFilePath = path15.join(githubDir, template.path);
|
|
15859
|
+
if (existsSync(targetFilePath)) {
|
|
15860
|
+
existingFiles.push(path15.relative(targetPath, targetFilePath));
|
|
15861
|
+
}
|
|
15862
|
+
}
|
|
15863
|
+
}
|
|
15864
|
+
if (existsSync(agentvDir)) {
|
|
15865
|
+
for (const template of agentvTemplates) {
|
|
15866
|
+
const targetFilePath = path15.join(agentvDir, template.path);
|
|
15867
|
+
if (existsSync(targetFilePath)) {
|
|
15868
|
+
existingFiles.push(path15.relative(targetPath, targetFilePath));
|
|
15869
|
+
}
|
|
15870
|
+
}
|
|
15871
|
+
}
|
|
15872
|
+
if (existingFiles.length > 0) {
|
|
15873
|
+
console.log("We detected an existing setup:");
|
|
15874
|
+
existingFiles.forEach((file) => console.log(` - ${file}`));
|
|
15875
|
+
console.log();
|
|
15876
|
+
const shouldReplace = await promptYesNo("Do you want to replace these files?");
|
|
15877
|
+
if (!shouldReplace) {
|
|
15878
|
+
console.log("\nInit cancelled. No files were changed.");
|
|
15879
|
+
return;
|
|
15880
|
+
}
|
|
15881
|
+
console.log();
|
|
15882
|
+
}
|
|
15576
15883
|
if (!existsSync(githubDir)) {
|
|
15577
15884
|
mkdirSync(githubDir, { recursive: true });
|
|
15578
15885
|
}
|
|
15579
|
-
|
|
15580
|
-
|
|
15886
|
+
if (!existsSync(agentvDir)) {
|
|
15887
|
+
mkdirSync(agentvDir, { recursive: true });
|
|
15888
|
+
}
|
|
15889
|
+
for (const template of githubTemplates) {
|
|
15581
15890
|
const targetFilePath = path15.join(githubDir, template.path);
|
|
15582
15891
|
const targetDirPath = path15.dirname(targetFilePath);
|
|
15583
15892
|
if (!existsSync(targetDirPath)) {
|
|
@@ -15586,11 +15895,26 @@ async function initCommand(options = {}) {
|
|
|
15586
15895
|
writeFileSync(targetFilePath, template.content, "utf-8");
|
|
15587
15896
|
console.log(`Created ${path15.relative(targetPath, targetFilePath)}`);
|
|
15588
15897
|
}
|
|
15898
|
+
for (const template of agentvTemplates) {
|
|
15899
|
+
const targetFilePath = path15.join(agentvDir, template.path);
|
|
15900
|
+
const targetDirPath = path15.dirname(targetFilePath);
|
|
15901
|
+
if (!existsSync(targetDirPath)) {
|
|
15902
|
+
mkdirSync(targetDirPath, { recursive: true });
|
|
15903
|
+
}
|
|
15904
|
+
writeFileSync(targetFilePath, template.content, "utf-8");
|
|
15905
|
+
console.log(`Created ${path15.relative(targetPath, targetFilePath)}`);
|
|
15906
|
+
}
|
|
15589
15907
|
console.log("\nAgentV initialized successfully!");
|
|
15590
15908
|
console.log(`
|
|
15591
15909
|
Files installed to ${path15.relative(targetPath, githubDir)}:`);
|
|
15592
|
-
|
|
15593
|
-
console.log(
|
|
15910
|
+
githubTemplates.forEach((t) => console.log(` - ${t.path}`));
|
|
15911
|
+
console.log(`
|
|
15912
|
+
Files installed to ${path15.relative(targetPath, agentvDir)}:`);
|
|
15913
|
+
agentvTemplates.forEach((t) => console.log(` - ${t.path}`));
|
|
15914
|
+
console.log("\nYou can now:");
|
|
15915
|
+
console.log(" 1. Edit .agentv/.env with your API credentials");
|
|
15916
|
+
console.log(" 2. Configure targets in .agentv/targets.yaml");
|
|
15917
|
+
console.log(" 3. Create eval files using the schema and prompt templates");
|
|
15594
15918
|
}
|
|
15595
15919
|
|
|
15596
15920
|
// src/commands/status.ts
|
|
@@ -16556,4 +16880,4 @@ export {
|
|
|
16556
16880
|
createProgram,
|
|
16557
16881
|
runCli
|
|
16558
16882
|
};
|
|
16559
|
-
//# sourceMappingURL=chunk-
|
|
16883
|
+
//# sourceMappingURL=chunk-5WBKOCCW.js.map
|