@controlvector/cv-agent 1.8.0 → 1.9.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 CHANGED
@@ -3834,18 +3834,84 @@ async function runSetup() {
3834
3834
  console.log(source_default.gray(' Click "Add Integration" \u2192 "Allow" when prompted.'));
3835
3835
  console.log(source_default.gray(" (You can do this later \u2014 setup will continue.)"));
3836
3836
  console.log();
3837
- const cwd = process.cwd();
3838
- const isGitRepo = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".git"));
3839
- const hasCVDir = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cv"));
3840
- const hasClaudeMd = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, "CLAUDE.md"));
3841
- const repoName = (0, import_node_path.basename)(cwd);
3837
+ let cwd = process.cwd();
3838
+ let isGitRepo = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".git"));
3839
+ let repoName = (0, import_node_path.basename)(cwd);
3842
3840
  if (isGitRepo) {
3843
3841
  console.log(source_default.green(" \u2713") + ` Git repo found: ${repoName}`);
3844
3842
  } else {
3845
- console.log(" Initializing git repository...");
3846
- (0, import_node_child_process.execSync)("git init && git checkout -b main", { cwd, stdio: "pipe" });
3847
- console.log(source_default.green(" \u2713") + " Git repo initialized");
3843
+ const readline = await import("node:readline");
3844
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3845
+ console.log(" No git repository found in this directory.");
3846
+ console.log();
3847
+ console.log(` ${source_default.cyan("a")} \u2014 Initialize a new project here: ${cwd}`);
3848
+ console.log(` ${source_default.cyan("b")} \u2014 Clone an existing repo from CV-Hub`);
3849
+ console.log();
3850
+ const choice = await new Promise((resolve) => {
3851
+ rl.question(" Choose [a/b]: ", (answer) => {
3852
+ rl.close();
3853
+ resolve(answer.trim().toLowerCase() || "a");
3854
+ });
3855
+ });
3856
+ if (choice === "b" && token) {
3857
+ try {
3858
+ console.log(source_default.gray(" Fetching your repositories..."));
3859
+ const controller = new AbortController();
3860
+ const timeout = setTimeout(() => controller.abort(), 15e3);
3861
+ const res = await fetch(`${hubUrl}/api/v1/repos?limit=50`, {
3862
+ headers: { Authorization: `Bearer ${token}` },
3863
+ signal: controller.signal
3864
+ });
3865
+ clearTimeout(timeout);
3866
+ if (res.ok) {
3867
+ const data = await res.json();
3868
+ const repos = data.repositories || [];
3869
+ if (repos.length === 0) {
3870
+ console.log(source_default.yellow(" No repos found on CV-Hub. Initializing a new project instead."));
3871
+ } else {
3872
+ console.log();
3873
+ console.log(" Your CV-Hub repositories:");
3874
+ const displayRepos = repos.slice(0, 20);
3875
+ displayRepos.forEach((r, i) => {
3876
+ const desc = r.description ? source_default.gray(` \u2014 ${r.description.substring(0, 40)}`) : "";
3877
+ console.log(` ${source_default.cyan(String(i + 1).padStart(2))}. ${r.slug || r.name}${desc}`);
3878
+ });
3879
+ console.log();
3880
+ const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
3881
+ const selection = await new Promise((resolve) => {
3882
+ rl2.question(` Select a repo [1-${displayRepos.length}]: `, (answer) => {
3883
+ rl2.close();
3884
+ resolve(answer.trim());
3885
+ });
3886
+ });
3887
+ const idx = parseInt(selection, 10) - 1;
3888
+ if (idx >= 0 && idx < displayRepos.length) {
3889
+ const repo = displayRepos[idx];
3890
+ const gitHost = "git.hub.controlvector.io";
3891
+ const slug = repo.slug || repo.name;
3892
+ const cloneUrl = `https://${username}:${token}@${gitHost}/${username}/${slug}.git`;
3893
+ console.log(source_default.gray(` Cloning ${username}/${slug}...`));
3894
+ (0, import_node_child_process.execSync)(`git clone ${cloneUrl} ${slug}`, { cwd, stdio: "pipe", timeout: 6e4 });
3895
+ cwd = (0, import_node_path.join)(cwd, slug);
3896
+ process.chdir(cwd);
3897
+ repoName = slug;
3898
+ isGitRepo = true;
3899
+ console.log(source_default.green(" \u2713") + ` Cloned ${username}/${slug}`);
3900
+ }
3901
+ }
3902
+ }
3903
+ } catch (err) {
3904
+ console.log(source_default.yellow(` Could not fetch repos: ${err.message}. Initializing instead.`));
3905
+ }
3906
+ }
3907
+ if (!isGitRepo) {
3908
+ console.log(" Initializing git repository...");
3909
+ (0, import_node_child_process.execSync)("git init && git checkout -b main", { cwd, stdio: "pipe" });
3910
+ console.log(source_default.green(" \u2713") + " Git repo initialized");
3911
+ }
3848
3912
  }
3913
+ const hasClaudeMd = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, "CLAUDE.md"));
3914
+ const hasCVDir = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cv"));
3849
3915
  if (!hasClaudeMd) {
3850
3916
  const template = `# ${repoName}
3851
3917
 
@@ -3933,16 +3999,76 @@ async function runSetup() {
3933
3999
  }
3934
4000
  }
3935
4001
  console.log();
4002
+ let agentStatus = "";
4003
+ const pidFile = (0, import_node_path.join)((0, import_node_os2.homedir)(), ".config", "controlvector", "agent.pid");
4004
+ let agentRunning = false;
4005
+ try {
4006
+ const pid = parseInt((0, import_node_fs.readFileSync)(pidFile, "utf-8").trim(), 10);
4007
+ if (pid > 0) {
4008
+ process.kill(pid, 0);
4009
+ agentRunning = true;
4010
+ agentStatus = `running (PID ${pid})`;
4011
+ console.log(source_default.green(" \u2713") + ` Agent already running (PID ${pid})`);
4012
+ }
4013
+ } catch {
4014
+ }
4015
+ if (!agentRunning) {
4016
+ const readline = await import("node:readline");
4017
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
4018
+ const answer = await new Promise((resolve) => {
4019
+ rl.question(" Start the CV-Agent daemon? (Y/n): ", (a) => {
4020
+ rl.close();
4021
+ resolve(a.trim().toLowerCase() || "y");
4022
+ });
4023
+ });
4024
+ if (answer === "y" || answer === "yes" || answer === "") {
4025
+ const machName = (0, import_node_os2.hostname)().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-");
4026
+ console.log(source_default.gray(` Starting agent as "${machName}"...`));
4027
+ try {
4028
+ const { spawn: spawnChild } = await import("node:child_process");
4029
+ const child = spawnChild("cva", [
4030
+ "agent",
4031
+ "--auto-approve",
4032
+ "--machine",
4033
+ machName,
4034
+ "--working-dir",
4035
+ cwd
4036
+ ], {
4037
+ detached: true,
4038
+ stdio: "ignore",
4039
+ env: { ...process.env }
4040
+ });
4041
+ child.unref();
4042
+ if (child.pid) {
4043
+ (0, import_node_fs.mkdirSync)((0, import_node_path.join)((0, import_node_os2.homedir)(), ".config", "controlvector"), { recursive: true });
4044
+ (0, import_node_fs.writeFileSync)(pidFile, String(child.pid), { mode: 384 });
4045
+ agentStatus = `running (PID ${child.pid})`;
4046
+ console.log(source_default.green(" \u2713") + ` Agent started (PID ${child.pid}) \u2014 executor "${machName}"`);
4047
+ }
4048
+ } catch (err) {
4049
+ console.log(source_default.yellow(` Could not start agent: ${err.message}`));
4050
+ console.log(source_default.gray(" Start manually with: cva agent --auto-approve"));
4051
+ agentStatus = "not started";
4052
+ }
4053
+ } else {
4054
+ agentStatus = "not started";
4055
+ console.log(source_default.gray(" Start anytime with: cva agent --auto-approve"));
4056
+ }
4057
+ }
4058
+ console.log();
3936
4059
  console.log(source_default.bold(" Setup Complete"));
3937
4060
  console.log(source_default.gray(" " + "\u2500".repeat(40)));
3938
4061
  console.log(` ${source_default.green("\u2713")} Authenticated as: ${source_default.cyan(username)}`);
3939
4062
  console.log(` ${source_default.green("\u2713")} Repository: ${source_default.cyan(repoName)}`);
3940
4063
  console.log(` ${source_default.green("\u2713")} CLAUDE.md: present`);
4064
+ if (agentStatus.startsWith("running")) {
4065
+ console.log(` ${source_default.green("\u2713")} Agent daemon: ${source_default.cyan(agentStatus)}`);
4066
+ }
3941
4067
  console.log(source_default.gray(" " + "\u2500".repeat(40)));
3942
4068
  console.log();
3943
4069
  console.log(" What's next:");
3944
- console.log(` ${source_default.cyan("cva agent --auto-approve")} \u2014 Start listening for tasks`);
3945
- console.log(` Or open Claude.ai and dispatch a task to this repo.`);
4070
+ console.log(" Open Claude.ai and try:");
4071
+ console.log(source_default.cyan(` "Create a task in ${repoName} to add a hello world index.html"`));
3946
4072
  console.log();
3947
4073
  console.log(source_default.gray(` Dashboard: ${appUrl}`));
3948
4074
  console.log();
@@ -5410,6 +5536,64 @@ async function runAgent(options) {
5410
5536
  console.log();
5411
5537
  }
5412
5538
  }
5539
+ {
5540
+ const isGitRepo = require("fs").existsSync(require("path").join(workingDir, ".git"));
5541
+ if (!isGitRepo) {
5542
+ console.log(source_default.gray(" Bootstrap: initializing git repo..."));
5543
+ try {
5544
+ (0, import_node_child_process5.execSync)("git init && git checkout -b main", { cwd: workingDir, stdio: "pipe" });
5545
+ } catch {
5546
+ }
5547
+ }
5548
+ const claudeMdPath = require("path").join(workingDir, "CLAUDE.md");
5549
+ if (!require("fs").existsSync(claudeMdPath)) {
5550
+ const name = require("path").basename(workingDir);
5551
+ const template = `# ${name}
5552
+
5553
+ ## Overview
5554
+ [Describe your project here]
5555
+
5556
+ ## Build & Run
5557
+ [How to build and run this project]
5558
+ `;
5559
+ try {
5560
+ require("fs").writeFileSync(claudeMdPath, template);
5561
+ console.log(source_default.gray(" Bootstrap: created CLAUDE.md"));
5562
+ } catch {
5563
+ }
5564
+ }
5565
+ const cvDir = require("path").join(workingDir, ".cv");
5566
+ if (!require("fs").existsSync(cvDir)) {
5567
+ try {
5568
+ require("fs").mkdirSync(cvDir, { recursive: true });
5569
+ } catch {
5570
+ }
5571
+ }
5572
+ if (creds.CV_HUB_PAT) {
5573
+ try {
5574
+ const existing = (0, import_node_child_process5.execSync)('git remote get-url cv-hub 2>/dev/null || echo ""', {
5575
+ cwd: workingDir,
5576
+ encoding: "utf8",
5577
+ timeout: 5e3
5578
+ }).trim();
5579
+ if (!existing) {
5580
+ const name = require("path").basename(workingDir);
5581
+ const gitHost = "git.hub.controlvector.io";
5582
+ let user = "user";
5583
+ try {
5584
+ const sharedPath = require("path").join(require("os").homedir(), ".config", "controlvector", "credentials.json");
5585
+ const shared = JSON.parse(require("fs").readFileSync(sharedPath, "utf-8"));
5586
+ if (shared.username) user = shared.username;
5587
+ } catch {
5588
+ }
5589
+ const remoteUrl = `https://${gitHost}/${user}/${name}.git`;
5590
+ (0, import_node_child_process5.execSync)(`git remote add cv-hub ${remoteUrl}`, { cwd: workingDir, stdio: "pipe" });
5591
+ console.log(source_default.gray(` Bootstrap: remote cv-hub \u2192 ${remoteUrl}`));
5592
+ }
5593
+ } catch {
5594
+ }
5595
+ }
5596
+ }
5413
5597
  let detectedRepoId;
5414
5598
  try {
5415
5599
  const remoteUrl = (0, import_node_child_process5.execSync)("git remote get-url origin 2>/dev/null", {
@@ -6152,7 +6336,7 @@ function statusCommand() {
6152
6336
 
6153
6337
  // src/index.ts
6154
6338
  var program2 = new Command();
6155
- program2.name("cva").description('CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch.\n\nRun "cva setup" to get started.').version(true ? "1.8.0" : "1.6.0");
6339
+ program2.name("cva").description('CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch.\n\nRun "cva setup" to get started.').version(true ? "1.9.0" : "1.6.0");
6156
6340
  program2.addCommand(setupCommand());
6157
6341
  program2.addCommand(agentCommand());
6158
6342
  program2.addCommand(authCommand());