@controlvector/cv-agent 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.cjs +128 -6
- package/dist/bundle.cjs.map +3 -3
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +115 -1
- package/dist/commands/agent.js.map +1 -1
- package/dist/utils/api.d.ts +5 -1
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +22 -4
- package/dist/utils/api.js.map +1 -1
- package/package.json +1 -1
package/dist/bundle.cjs
CHANGED
|
@@ -3643,9 +3643,8 @@ async function apiCall(creds, method, path, body) {
|
|
|
3643
3643
|
body: body ? JSON.stringify(body) : void 0
|
|
3644
3644
|
});
|
|
3645
3645
|
}
|
|
3646
|
-
async function registerExecutor(creds, machineName, workingDir) {
|
|
3647
|
-
const
|
|
3648
|
-
const res = await apiCall(creds, "POST", "/api/v1/executors", {
|
|
3646
|
+
async function registerExecutor(creds, machineName, workingDir, repositoryId) {
|
|
3647
|
+
const body = {
|
|
3649
3648
|
name: `cva:${machineName}`,
|
|
3650
3649
|
machine_name: machineName,
|
|
3651
3650
|
type: "claude_code",
|
|
@@ -3654,7 +3653,11 @@ async function registerExecutor(creds, machineName, workingDir) {
|
|
|
3654
3653
|
tools: ["bash", "read", "write", "edit", "glob", "grep"],
|
|
3655
3654
|
maxConcurrentTasks: 1
|
|
3656
3655
|
}
|
|
3657
|
-
}
|
|
3656
|
+
};
|
|
3657
|
+
if (repositoryId) {
|
|
3658
|
+
body.repository_id = repositoryId;
|
|
3659
|
+
}
|
|
3660
|
+
const res = await apiCall(creds, "POST", "/api/v1/executors", body);
|
|
3658
3661
|
if (!res.ok) {
|
|
3659
3662
|
const err = await res.text();
|
|
3660
3663
|
throw new Error(`Failed to register executor: ${res.status} ${err}`);
|
|
@@ -3662,6 +3665,16 @@ async function registerExecutor(creds, machineName, workingDir) {
|
|
|
3662
3665
|
const data = await res.json();
|
|
3663
3666
|
return { id: data.executor.id, name: data.executor.name };
|
|
3664
3667
|
}
|
|
3668
|
+
async function resolveRepoId(creds, owner, repo) {
|
|
3669
|
+
try {
|
|
3670
|
+
const res = await apiCall(creds, "GET", `/api/v1/repos/${owner}/${repo}`);
|
|
3671
|
+
if (!res.ok) return null;
|
|
3672
|
+
const data = await res.json();
|
|
3673
|
+
return data.repository ? { id: data.repository.id, slug: data.repository.slug } : null;
|
|
3674
|
+
} catch {
|
|
3675
|
+
return null;
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3665
3678
|
async function markOffline(creds, executorId) {
|
|
3666
3679
|
await apiCall(creds, "POST", `/api/v1/executors/${executorId}/offline`).catch(() => {
|
|
3667
3680
|
});
|
|
@@ -4206,6 +4219,7 @@ var PERMISSION_PATTERNS = [
|
|
|
4206
4219
|
/\? \(y\/n\)/
|
|
4207
4220
|
];
|
|
4208
4221
|
var MAX_OUTPUT_BYTES = 200 * 1024;
|
|
4222
|
+
var MAX_OUTPUT_FINAL_BYTES = 50 * 1024;
|
|
4209
4223
|
var OUTPUT_PROGRESS_INTERVAL = 4096;
|
|
4210
4224
|
async function launchAutoApproveMode(prompt, options) {
|
|
4211
4225
|
const sessionId = options.taskId ? options.taskId.replace(/-/g, "").slice(0, 32).padEnd(32, "0").replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, "$1-$2-$3-$4-$5") : void 0;
|
|
@@ -4266,6 +4280,11 @@ async function launchAutoApproveMode(prompt, options) {
|
|
|
4266
4280
|
).catch(() => {
|
|
4267
4281
|
});
|
|
4268
4282
|
}
|
|
4283
|
+
postTaskEvent(options.creds, options.taskId, {
|
|
4284
|
+
event_type: "output",
|
|
4285
|
+
content: { chunk, byte_offset: lastProgressBytes }
|
|
4286
|
+
}).catch(() => {
|
|
4287
|
+
});
|
|
4269
4288
|
}
|
|
4270
4289
|
}
|
|
4271
4290
|
});
|
|
@@ -4376,6 +4395,11 @@ async function launchRelayMode(prompt, options) {
|
|
|
4376
4395
|
{ output_chunk: chunk }
|
|
4377
4396
|
).catch(() => {
|
|
4378
4397
|
});
|
|
4398
|
+
postTaskEvent(options.creds, options.taskId, {
|
|
4399
|
+
event_type: "output",
|
|
4400
|
+
content: { chunk, byte_offset: lastProgressBytes }
|
|
4401
|
+
}).catch(() => {
|
|
4402
|
+
});
|
|
4379
4403
|
}
|
|
4380
4404
|
if (Date.now() - lastRedirectCheck > 1e4) {
|
|
4381
4405
|
try {
|
|
@@ -4495,6 +4519,68 @@ async function pollForEventResponse(creds, taskId, eventId, timeoutMs) {
|
|
|
4495
4519
|
}
|
|
4496
4520
|
return null;
|
|
4497
4521
|
}
|
|
4522
|
+
async function handleSelfUpdate(task, state, creds) {
|
|
4523
|
+
const startTime = Date.now();
|
|
4524
|
+
try {
|
|
4525
|
+
await startTask(creds, state.executorId, task.id);
|
|
4526
|
+
sendTaskLog(creds, state.executorId, task.id, "lifecycle", "Self-update started");
|
|
4527
|
+
const source = (task.input?.description || task.description || "npm").trim();
|
|
4528
|
+
let output = "";
|
|
4529
|
+
if (source === "npm" || source.startsWith("npm:")) {
|
|
4530
|
+
const pkg = source === "npm" ? "@controlvector/cv-agent@latest" : source.replace("npm:", "");
|
|
4531
|
+
output = (0, import_node_child_process2.execSync)(`npm install -g ${pkg} 2>&1`, { encoding: "utf8", timeout: 12e4 });
|
|
4532
|
+
} else if (source.startsWith("git:")) {
|
|
4533
|
+
const repoPath = source.replace("git:", "");
|
|
4534
|
+
output = (0, import_node_child_process2.execSync)(`cd ${repoPath} && git pull && npm install && npm run build && npm link 2>&1`, {
|
|
4535
|
+
encoding: "utf8",
|
|
4536
|
+
timeout: 3e5
|
|
4537
|
+
});
|
|
4538
|
+
} else {
|
|
4539
|
+
output = (0, import_node_child_process2.execSync)(`npm install -g @controlvector/cv-agent@latest 2>&1`, { encoding: "utf8", timeout: 12e4 });
|
|
4540
|
+
}
|
|
4541
|
+
let newVersion = "unknown";
|
|
4542
|
+
try {
|
|
4543
|
+
newVersion = (0, import_node_child_process2.execSync)("cva --version 2>/dev/null || echo unknown", { encoding: "utf8" }).trim();
|
|
4544
|
+
} catch {
|
|
4545
|
+
}
|
|
4546
|
+
postTaskEvent(creds, task.id, {
|
|
4547
|
+
event_type: "output_final",
|
|
4548
|
+
content: { output: output.slice(-1e4), new_version: newVersion }
|
|
4549
|
+
}).catch(() => {
|
|
4550
|
+
});
|
|
4551
|
+
sendTaskLog(
|
|
4552
|
+
creds,
|
|
4553
|
+
state.executorId,
|
|
4554
|
+
task.id,
|
|
4555
|
+
"lifecycle",
|
|
4556
|
+
`Self-update completed. New version: ${newVersion}`,
|
|
4557
|
+
{ output: output.slice(-5e3) },
|
|
4558
|
+
100
|
|
4559
|
+
);
|
|
4560
|
+
await completeTask(creds, state.executorId, task.id, {
|
|
4561
|
+
summary: `Updated to ${newVersion}`,
|
|
4562
|
+
exit_code: 0,
|
|
4563
|
+
stats: { duration_seconds: Math.round((Date.now() - startTime) / 1e3) }
|
|
4564
|
+
});
|
|
4565
|
+
state.completedCount++;
|
|
4566
|
+
if (task.input?.constraints?.includes("restart")) {
|
|
4567
|
+
console.log(source_default.yellow("Restarting agent with updated binary..."));
|
|
4568
|
+
const args = process.argv.slice(1).join(" ");
|
|
4569
|
+
(0, import_node_child_process2.execSync)(`nohup cva ${args} > /tmp/cva-restart.log 2>&1 &`, { stdio: "ignore" });
|
|
4570
|
+
process.exit(0);
|
|
4571
|
+
}
|
|
4572
|
+
} catch (err) {
|
|
4573
|
+
sendTaskLog(creds, state.executorId, task.id, "error", `Self-update failed: ${err.message}`);
|
|
4574
|
+
try {
|
|
4575
|
+
await failTask(creds, state.executorId, task.id, err.message);
|
|
4576
|
+
} catch {
|
|
4577
|
+
}
|
|
4578
|
+
state.failedCount++;
|
|
4579
|
+
} finally {
|
|
4580
|
+
state.currentTaskId = null;
|
|
4581
|
+
state.lastTaskEnd = Date.now();
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4498
4584
|
async function runAgent(options) {
|
|
4499
4585
|
const creds = await readCredentials();
|
|
4500
4586
|
if (!creds.CV_HUB_API) {
|
|
@@ -4539,8 +4625,31 @@ async function runAgent(options) {
|
|
|
4539
4625
|
console.log();
|
|
4540
4626
|
}
|
|
4541
4627
|
}
|
|
4628
|
+
let detectedRepoId;
|
|
4629
|
+
try {
|
|
4630
|
+
const remoteUrl = (0, import_node_child_process2.execSync)("git remote get-url origin 2>/dev/null", {
|
|
4631
|
+
cwd: workingDir,
|
|
4632
|
+
encoding: "utf8",
|
|
4633
|
+
timeout: 5e3
|
|
4634
|
+
}).trim();
|
|
4635
|
+
const cvHubMatch = remoteUrl.match(
|
|
4636
|
+
/git\.hub\.controlvector\.io[:/]([^/]+)\/([^/.]+)/
|
|
4637
|
+
);
|
|
4638
|
+
if (cvHubMatch) {
|
|
4639
|
+
const [, repoOwner, repoSlug] = cvHubMatch;
|
|
4640
|
+
try {
|
|
4641
|
+
const repoData = await resolveRepoId(creds, repoOwner, repoSlug);
|
|
4642
|
+
if (repoData?.id) {
|
|
4643
|
+
detectedRepoId = repoData.id;
|
|
4644
|
+
console.log(source_default.gray(` Repo: ${repoOwner}/${repoSlug}`));
|
|
4645
|
+
}
|
|
4646
|
+
} catch {
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
} catch {
|
|
4650
|
+
}
|
|
4542
4651
|
const executor = await withRetry(
|
|
4543
|
-
() => registerExecutor(creds, machineName, workingDir),
|
|
4652
|
+
() => registerExecutor(creds, machineName, workingDir, detectedRepoId),
|
|
4544
4653
|
"Executor registration"
|
|
4545
4654
|
);
|
|
4546
4655
|
const mode = options.autoApprove ? "auto-approve" : "relay";
|
|
@@ -4599,6 +4708,10 @@ ${source_default.red("!")} Error: ${err.message}`);
|
|
|
4599
4708
|
async function executeTask(task, state, creds, options) {
|
|
4600
4709
|
const startTime = Date.now();
|
|
4601
4710
|
state.currentTaskId = task.id;
|
|
4711
|
+
if (task.task_type === "_system_update") {
|
|
4712
|
+
await handleSelfUpdate(task, state, creds);
|
|
4713
|
+
return;
|
|
4714
|
+
}
|
|
4602
4715
|
process.stdout.write("\r\x1B[K");
|
|
4603
4716
|
console.log(`\u{1F4E5} ${source_default.bold.cyan("RECEIVED")} \u2014 Task: ${task.title} (${task.priority})`);
|
|
4604
4717
|
console.log(source_default.bold("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
@@ -4705,6 +4818,15 @@ ${source_default.red("Timeout")} Task timed out after ${formatDuration(timeoutMs
|
|
|
4705
4818
|
console.log();
|
|
4706
4819
|
console.log(`\u2705 ${source_default.bold.green("COMPLETED")} \u2014 Duration: ${elapsed}`);
|
|
4707
4820
|
printBanner("COMPLETED", elapsed, allChangedFiles, postGitState.headSha);
|
|
4821
|
+
postTaskEvent(creds, task.id, {
|
|
4822
|
+
event_type: "output_final",
|
|
4823
|
+
content: {
|
|
4824
|
+
output: result.output.slice(-MAX_OUTPUT_FINAL_BYTES),
|
|
4825
|
+
exit_code: result.exitCode,
|
|
4826
|
+
duration_seconds: Math.round((Date.now() - startTime) / 1e3)
|
|
4827
|
+
}
|
|
4828
|
+
}).catch(() => {
|
|
4829
|
+
});
|
|
4708
4830
|
await withRetry(
|
|
4709
4831
|
() => completeTask(creds, state.executorId, task.id, payload),
|
|
4710
4832
|
"Report completion"
|
|
@@ -5081,7 +5203,7 @@ function statusCommand() {
|
|
|
5081
5203
|
|
|
5082
5204
|
// src/index.ts
|
|
5083
5205
|
var program2 = new Command();
|
|
5084
|
-
program2.name("cva").description("CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch").version(true ? "1.
|
|
5206
|
+
program2.name("cva").description("CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch").version(true ? "1.3.0" : "1.1.0");
|
|
5085
5207
|
program2.addCommand(agentCommand());
|
|
5086
5208
|
program2.addCommand(authCommand());
|
|
5087
5209
|
program2.addCommand(remoteCommand());
|