@controlvector/cv-agent 1.6.0 → 1.7.1

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
@@ -3036,8 +3036,11 @@ var {
3036
3036
  Help
3037
3037
  } = import_index.default;
3038
3038
 
3039
- // src/commands/agent.ts
3040
- var import_node_child_process4 = require("node:child_process");
3039
+ // src/commands/setup.ts
3040
+ var import_node_child_process = require("node:child_process");
3041
+ var import_node_fs = require("node:fs");
3042
+ var import_node_path = require("node:path");
3043
+ var import_node_os2 = require("node:os");
3041
3044
 
3042
3045
  // node_modules/chalk/source/vendor/ansi-styles/index.js
3043
3046
  var ANSI_BACKGROUND_OFFSET = 10;
@@ -3630,6 +3633,248 @@ function cleanMachineName(name) {
3630
3633
  return name.trim().toLowerCase().replace(/\s+/g, "-");
3631
3634
  }
3632
3635
 
3636
+ // src/commands/setup.ts
3637
+ var SHARED_CRED_DIR = (0, import_node_path.join)((0, import_node_os2.homedir)(), ".config", "controlvector");
3638
+ var SHARED_CRED_PATH = (0, import_node_path.join)(SHARED_CRED_DIR, "credentials.json");
3639
+ function readSharedCreds() {
3640
+ try {
3641
+ const data = JSON.parse((0, import_node_fs.readFileSync)(SHARED_CRED_PATH, "utf-8"));
3642
+ if (data.token && data.hub_url) return data;
3643
+ return null;
3644
+ } catch {
3645
+ return null;
3646
+ }
3647
+ }
3648
+ function writeSharedCreds(creds) {
3649
+ (0, import_node_fs.mkdirSync)(SHARED_CRED_DIR, { recursive: true });
3650
+ (0, import_node_fs.writeFileSync)(SHARED_CRED_PATH, JSON.stringify(creds, null, 2) + "\n", { mode: 384 });
3651
+ }
3652
+ async function validateToken(hubUrl, token) {
3653
+ try {
3654
+ const controller = new AbortController();
3655
+ const timeout = setTimeout(() => controller.abort(), 1e4);
3656
+ const res = await fetch(`${hubUrl}/api/auth/me`, {
3657
+ headers: { Authorization: `Bearer ${token}` },
3658
+ signal: controller.signal
3659
+ });
3660
+ clearTimeout(timeout);
3661
+ if (!res.ok) return null;
3662
+ const data = await res.json();
3663
+ return data.user?.username || data.user?.email || "unknown";
3664
+ } catch {
3665
+ return null;
3666
+ }
3667
+ }
3668
+ function checkBinary(cmd) {
3669
+ try {
3670
+ return (0, import_node_child_process.execSync)(`${cmd} 2>&1`, { encoding: "utf8", timeout: 5e3 }).trim().split("\n")[0];
3671
+ } catch {
3672
+ return null;
3673
+ }
3674
+ }
3675
+ async function runSetup() {
3676
+ const hubUrl = "https://api.hub.controlvector.io";
3677
+ const appUrl = "https://hub.controlvector.io";
3678
+ console.log();
3679
+ console.log(source_default.bold(" CV-Agent Setup"));
3680
+ console.log();
3681
+ console.log(" Checking environment...");
3682
+ const nodeVersion = checkBinary("node --version");
3683
+ const gitVersion = checkBinary("git --version");
3684
+ const claudeVersion = checkBinary("claude --version");
3685
+ console.log(` ${nodeVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Node.js ${nodeVersion || "\u2014 not found"}`);
3686
+ console.log(` ${gitVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Git ${gitVersion || "\u2014 not found"}`);
3687
+ console.log(` ${claudeVersion ? source_default.green("\u2713") : source_default.red("\u2717")} Claude Code ${claudeVersion || "\u2014 not found"}`);
3688
+ console.log();
3689
+ if (!nodeVersion || !gitVersion) {
3690
+ if (!nodeVersion) console.log(source_default.red(" Node.js required: https://nodejs.org"));
3691
+ if (!gitVersion) console.log(source_default.red(" Git required: https://git-scm.com"));
3692
+ process.exit(1);
3693
+ }
3694
+ if (!claudeVersion) {
3695
+ console.log(source_default.yellow(" Claude Code not found. Install with:"));
3696
+ console.log(source_default.cyan(" npm install -g @anthropic-ai/claude-code"));
3697
+ console.log();
3698
+ console.log(source_default.gray(" Continuing setup \u2014 you can install Claude Code later."));
3699
+ console.log();
3700
+ }
3701
+ let username;
3702
+ let token;
3703
+ const shared = readSharedCreds();
3704
+ if (shared) {
3705
+ const user = await validateToken(shared.hub_url, shared.token);
3706
+ if (user) {
3707
+ username = user;
3708
+ token = shared.token;
3709
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)}`);
3710
+ }
3711
+ }
3712
+ if (!token) {
3713
+ const creds = await readCredentials();
3714
+ if (creds.CV_HUB_PAT) {
3715
+ const user = await validateToken(hubUrl, creds.CV_HUB_PAT);
3716
+ if (user) {
3717
+ username = user;
3718
+ token = creds.CV_HUB_PAT;
3719
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)} (from cv-hub credentials)`);
3720
+ writeSharedCreds({ hub_url: hubUrl, token, username, created_at: (/* @__PURE__ */ new Date()).toISOString() });
3721
+ }
3722
+ }
3723
+ }
3724
+ if (!token) {
3725
+ console.log(" Let's connect you to CV-Hub.");
3726
+ console.log();
3727
+ const autoName = `${(0, import_node_os2.hostname)()}-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
3728
+ const tokenUrl = `${appUrl}/settings/tokens/new?name=${encodeURIComponent(autoName)}&scopes=agent,repo`;
3729
+ console.log(source_default.gray(` Opening: ${tokenUrl}`));
3730
+ try {
3731
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
3732
+ (0, import_node_child_process.execSync)(`${openCmd} "${tokenUrl}" 2>/dev/null`, { timeout: 5e3 });
3733
+ } catch {
3734
+ console.log(source_default.gray(" (Could not open browser \u2014 copy the URL above)"));
3735
+ }
3736
+ console.log();
3737
+ const readline = await import("node:readline");
3738
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3739
+ token = await new Promise((resolve) => {
3740
+ rl.question(" Paste your token here: ", (answer) => {
3741
+ rl.close();
3742
+ resolve(answer.trim());
3743
+ });
3744
+ });
3745
+ if (!token) {
3746
+ console.log(source_default.red(" No token provided. Run cva setup again."));
3747
+ process.exit(1);
3748
+ }
3749
+ const user = await validateToken(hubUrl, token);
3750
+ if (!user) {
3751
+ console.log(source_default.red(" Token validation failed. Check your token and try again."));
3752
+ process.exit(1);
3753
+ }
3754
+ username = user;
3755
+ console.log(source_default.green(" \u2713") + ` Authenticated as ${source_default.bold(user)}`);
3756
+ writeSharedCreds({ hub_url: hubUrl, token, username, created_at: (/* @__PURE__ */ new Date()).toISOString() });
3757
+ await writeCredentialField("CV_HUB_PAT", token);
3758
+ await writeCredentialField("CV_HUB_API", hubUrl);
3759
+ }
3760
+ console.log();
3761
+ console.log(" Claude.ai MCP connector:");
3762
+ const mcpUrl = `https://claude.ai/settings/integrations?add_mcp=${encodeURIComponent(`${hubUrl}/mcp`)}`;
3763
+ console.log(source_default.gray(` To connect Claude.ai to CV-Hub, visit:`));
3764
+ console.log(source_default.cyan(` ${mcpUrl}`));
3765
+ console.log();
3766
+ console.log(source_default.gray(' Click "Add Integration" \u2192 "Allow" when prompted.'));
3767
+ console.log(source_default.gray(" (You can do this later \u2014 setup will continue.)"));
3768
+ console.log();
3769
+ const cwd = process.cwd();
3770
+ const isGitRepo = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".git"));
3771
+ const hasCVDir = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cv"));
3772
+ const hasClaudeMd = (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, "CLAUDE.md"));
3773
+ const repoName = (0, import_node_path.basename)(cwd);
3774
+ if (isGitRepo) {
3775
+ console.log(source_default.green(" \u2713") + ` Git repo found: ${repoName}`);
3776
+ } else {
3777
+ console.log(" Initializing git repository...");
3778
+ (0, import_node_child_process.execSync)("git init && git checkout -b main", { cwd, stdio: "pipe" });
3779
+ console.log(source_default.green(" \u2713") + " Git repo initialized");
3780
+ }
3781
+ if (!hasClaudeMd) {
3782
+ const template = `# ${repoName}
3783
+
3784
+ ## Overview
3785
+ [Describe your project here]
3786
+
3787
+ ## Tech Stack
3788
+ [What languages/frameworks does this project use?]
3789
+
3790
+ ## Build & Run
3791
+ [How to build and run this project]
3792
+ `;
3793
+ (0, import_node_fs.writeFileSync)((0, import_node_path.join)(cwd, "CLAUDE.md"), template);
3794
+ console.log(source_default.green(" \u2713") + " CLAUDE.md created");
3795
+ } else {
3796
+ console.log(source_default.green(" \u2713") + " CLAUDE.md present");
3797
+ }
3798
+ if (!hasCVDir) {
3799
+ (0, import_node_fs.mkdirSync)((0, import_node_path.join)(cwd, ".cv"), { recursive: true });
3800
+ }
3801
+ if (token && username) {
3802
+ const gitHost = "git.hub.controlvector.io";
3803
+ const remoteUrl = `https://${gitHost}/${username}/${repoName}.git`;
3804
+ try {
3805
+ const existingRemote = (0, import_node_child_process.execSync)('git remote get-url cv-hub 2>/dev/null || echo ""', { cwd, encoding: "utf8" }).trim();
3806
+ if (!existingRemote) {
3807
+ try {
3808
+ const controller = new AbortController();
3809
+ const timeout = setTimeout(() => controller.abort(), 15e3);
3810
+ await fetch(`${hubUrl}/api/v1/user/repos`, {
3811
+ method: "POST",
3812
+ headers: {
3813
+ Authorization: `Bearer ${token}`,
3814
+ "Content-Type": "application/json"
3815
+ },
3816
+ body: JSON.stringify({ name: repoName, auto_init: false }),
3817
+ signal: controller.signal
3818
+ });
3819
+ clearTimeout(timeout);
3820
+ console.log(source_default.green(" \u2713") + ` Repo created on CV-Hub: ${username}/${repoName}`);
3821
+ } catch {
3822
+ }
3823
+ (0, import_node_child_process.execSync)(`git remote add cv-hub ${remoteUrl}`, { cwd, stdio: "pipe" });
3824
+ console.log(source_default.green(" \u2713") + ` Remote added: cv-hub \u2192 ${remoteUrl}`);
3825
+ } else {
3826
+ console.log(source_default.green(" \u2713") + ` CV-Hub remote exists`);
3827
+ }
3828
+ } catch {
3829
+ }
3830
+ try {
3831
+ (0, import_node_child_process.execSync)("git log --oneline -1", { cwd, stdio: "pipe" });
3832
+ const status = (0, import_node_child_process.execSync)("git status --porcelain", { cwd, encoding: "utf8" }).trim();
3833
+ if (status) {
3834
+ (0, import_node_child_process.execSync)("git add -A", { cwd, stdio: "pipe" });
3835
+ (0, import_node_child_process.execSync)('git commit -m "chore: cv-agent setup"', { cwd, stdio: "pipe" });
3836
+ console.log(source_default.green(" \u2713") + " Changes committed");
3837
+ }
3838
+ } catch {
3839
+ try {
3840
+ (0, import_node_child_process.execSync)("git add -A", { cwd, stdio: "pipe" });
3841
+ (0, import_node_child_process.execSync)('git commit -m "Initial commit via cv-agent"', { cwd, stdio: "pipe" });
3842
+ console.log(source_default.green(" \u2713") + " Initial commit created");
3843
+ } catch {
3844
+ }
3845
+ }
3846
+ try {
3847
+ (0, import_node_child_process.execSync)("git push -u cv-hub main 2>&1", { cwd, stdio: "pipe", timeout: 3e4 });
3848
+ console.log(source_default.green(" \u2713") + " Pushed to CV-Hub");
3849
+ } catch {
3850
+ console.log(source_default.gray(" (Push skipped \u2014 you can push later with: git push cv-hub main)"));
3851
+ }
3852
+ }
3853
+ console.log();
3854
+ console.log(source_default.bold(" Setup Complete"));
3855
+ console.log(source_default.gray(" " + "\u2500".repeat(40)));
3856
+ console.log(` ${source_default.green("\u2713")} Authenticated as: ${source_default.cyan(username)}`);
3857
+ console.log(` ${source_default.green("\u2713")} Repository: ${source_default.cyan(repoName)}`);
3858
+ console.log(` ${source_default.green("\u2713")} CLAUDE.md: present`);
3859
+ console.log(source_default.gray(" " + "\u2500".repeat(40)));
3860
+ console.log();
3861
+ console.log(" What's next:");
3862
+ console.log(` ${source_default.cyan("cva agent --auto-approve")} \u2014 Start listening for tasks`);
3863
+ console.log(` Or open Claude.ai and dispatch a task to this repo.`);
3864
+ console.log();
3865
+ console.log(source_default.gray(` Dashboard: ${appUrl}`));
3866
+ console.log();
3867
+ }
3868
+ function setupCommand() {
3869
+ const cmd = new Command("setup");
3870
+ cmd.description("Set up CV-Agent \u2014 authentication, repo, and connections (start here)");
3871
+ cmd.action(runSetup);
3872
+ return cmd;
3873
+ }
3874
+
3875
+ // src/commands/agent.ts
3876
+ var import_node_child_process5 = require("node:child_process");
3877
+
3633
3878
  // src/utils/api.ts
3634
3879
  async function apiCall(creds, method, path, body) {
3635
3880
  const url = `${creds.CV_HUB_API}${path}`;
@@ -3835,10 +4080,10 @@ function parseClaudeCodeOutput(line) {
3835
4080
  }
3836
4081
 
3837
4082
  // src/commands/agent-git.ts
3838
- var import_node_child_process = require("node:child_process");
4083
+ var import_node_child_process2 = require("node:child_process");
3839
4084
  function gitExec(cmd, cwd) {
3840
4085
  try {
3841
- return (0, import_node_child_process.execSync)(cmd, { cwd, encoding: "utf-8", timeout: 1e4 }).trim();
4086
+ return (0, import_node_child_process2.execSync)(cmd, { cwd, encoding: "utf-8", timeout: 1e4 }).trim();
3842
4087
  } catch {
3843
4088
  return null;
3844
4089
  }
@@ -3991,7 +4236,7 @@ function verifyGitRemote(cwd, task, gitHost) {
3991
4236
  const currentRemote = gitExec("git remote get-url origin", cwd);
3992
4237
  if (!currentRemote) {
3993
4238
  try {
3994
- (0, import_node_child_process.execSync)(`git remote add origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4239
+ (0, import_node_child_process2.execSync)(`git remote add origin ${expectedRemote}`, { cwd, timeout: 5e3 });
3995
4240
  } catch {
3996
4241
  }
3997
4242
  return { remoteName: "origin", remoteUrl: expectedRemote };
@@ -4001,7 +4246,7 @@ function verifyGitRemote(cwd, task, gitHost) {
4001
4246
  }
4002
4247
  if (currentRemote.includes(gitHost)) {
4003
4248
  try {
4004
- (0, import_node_child_process.execSync)(`git remote set-url origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4249
+ (0, import_node_child_process2.execSync)(`git remote set-url origin ${expectedRemote}`, { cwd, timeout: 5e3 });
4005
4250
  } catch {
4006
4251
  }
4007
4252
  return { remoteName: "origin", remoteUrl: expectedRemote };
@@ -4009,12 +4254,12 @@ function verifyGitRemote(cwd, task, gitHost) {
4009
4254
  const cvRemote = gitExec("git remote get-url cv-hub", cwd);
4010
4255
  if (!cvRemote) {
4011
4256
  try {
4012
- (0, import_node_child_process.execSync)(`git remote add cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4257
+ (0, import_node_child_process2.execSync)(`git remote add cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4013
4258
  } catch {
4014
4259
  }
4015
4260
  } else if (cvRemote !== expectedRemote) {
4016
4261
  try {
4017
- (0, import_node_child_process.execSync)(`git remote set-url cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4262
+ (0, import_node_child_process2.execSync)(`git remote set-url cv-hub ${expectedRemote}`, { cwd, timeout: 5e3 });
4018
4263
  } catch {
4019
4264
  }
4020
4265
  }
@@ -4104,9 +4349,9 @@ async function writeConfig(config) {
4104
4349
  }
4105
4350
 
4106
4351
  // src/commands/git-safety.ts
4107
- var import_node_child_process2 = require("node:child_process");
4352
+ var import_node_child_process3 = require("node:child_process");
4108
4353
  function git(cmd, cwd) {
4109
- return (0, import_node_child_process2.execSync)(cmd, { cwd, encoding: "utf8", timeout: 3e4 }).trim();
4354
+ return (0, import_node_child_process3.execSync)(cmd, { cwd, encoding: "utf8", timeout: 3e4 }).trim();
4110
4355
  }
4111
4356
  function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
4112
4357
  const targetBranch = branch || "main";
@@ -4201,12 +4446,12 @@ Files: ${added} added, ${modified} modified, ${deleted} deleted`;
4201
4446
  }
4202
4447
 
4203
4448
  // src/commands/deploy-manifest.ts
4204
- var import_node_child_process3 = require("node:child_process");
4205
- var import_node_fs = require("node:fs");
4206
- var import_node_path = require("node:path");
4449
+ var import_node_child_process4 = require("node:child_process");
4450
+ var import_node_fs2 = require("node:fs");
4451
+ var import_node_path2 = require("node:path");
4207
4452
  function exec(cmd, cwd, timeoutMs = 3e5, env2) {
4208
4453
  try {
4209
- const stdout = (0, import_node_child_process3.execSync)(cmd, {
4454
+ const stdout = (0, import_node_child_process4.execSync)(cmd, {
4210
4455
  cwd,
4211
4456
  encoding: "utf8",
4212
4457
  timeout: timeoutMs,
@@ -4240,16 +4485,16 @@ async function checkHealth(url, timeoutSeconds) {
4240
4485
  }
4241
4486
  function getHeadCommit(cwd) {
4242
4487
  try {
4243
- return (0, import_node_child_process3.execSync)("git rev-parse HEAD", { cwd, encoding: "utf8", timeout: 5e3 }).trim();
4488
+ return (0, import_node_child_process4.execSync)("git rev-parse HEAD", { cwd, encoding: "utf8", timeout: 5e3 }).trim();
4244
4489
  } catch {
4245
4490
  return null;
4246
4491
  }
4247
4492
  }
4248
4493
  function loadDeployManifest(workspaceRoot) {
4249
- const manifestPath = (0, import_node_path.join)(workspaceRoot, ".cva", "deploy.json");
4250
- if (!(0, import_node_fs.existsSync)(manifestPath)) return null;
4494
+ const manifestPath = (0, import_node_path2.join)(workspaceRoot, ".cva", "deploy.json");
4495
+ if (!(0, import_node_fs2.existsSync)(manifestPath)) return null;
4251
4496
  try {
4252
- const raw = (0, import_node_fs.readFileSync)(manifestPath, "utf8");
4497
+ const raw = (0, import_node_fs2.readFileSync)(manifestPath, "utf8");
4253
4498
  const manifest = JSON.parse(raw);
4254
4499
  if (!manifest.version || manifest.version < 1) {
4255
4500
  console.log(" [deploy] Invalid manifest version");
@@ -4274,7 +4519,7 @@ async function postTaskDeploy(workspaceRoot, taskId, log) {
4274
4519
  console.log(` [deploy] Building: ${buildStep.name}`);
4275
4520
  log("lifecycle", `Building: ${buildStep.name}`);
4276
4521
  const start = Date.now();
4277
- const cwd = (0, import_node_path.join)(workspaceRoot, buildStep.working_dir || ".");
4522
+ const cwd = (0, import_node_path2.join)(workspaceRoot, buildStep.working_dir || ".");
4278
4523
  const timeoutMs = (buildStep.timeout_seconds || 300) * 1e3;
4279
4524
  const result = exec(buildStep.command, cwd, timeoutMs);
4280
4525
  if (!result.ok) {
@@ -4365,7 +4610,7 @@ async function rollback(workspaceRoot, targetCommit, manifest, log) {
4365
4610
  }
4366
4611
  if (manifest.build?.steps) {
4367
4612
  for (const step of manifest.build.steps) {
4368
- exec(step.command, (0, import_node_path.join)(workspaceRoot, step.working_dir || "."), (step.timeout_seconds || 300) * 1e3);
4613
+ exec(step.command, (0, import_node_path2.join)(workspaceRoot, step.working_dir || "."), (step.timeout_seconds || 300) * 1e3);
4369
4614
  }
4370
4615
  }
4371
4616
  if (manifest.service?.restart_command) {
@@ -4395,7 +4640,7 @@ function containsAuthError(text) {
4395
4640
  }
4396
4641
  async function checkClaudeAuth() {
4397
4642
  try {
4398
- const output = (0, import_node_child_process4.execSync)("claude --version 2>&1", {
4643
+ const output = (0, import_node_child_process5.execSync)("claude --version 2>&1", {
4399
4644
  encoding: "utf8",
4400
4645
  timeout: 1e4,
4401
4646
  env: { ...process.env }
@@ -4606,7 +4851,7 @@ async function launchAutoApproveMode(prompt, options) {
4606
4851
  if (sessionId && !isContinue) {
4607
4852
  args.push("--session-id", sessionId);
4608
4853
  }
4609
- const child = (0, import_node_child_process4.spawn)("claude", args, {
4854
+ const child = (0, import_node_child_process5.spawn)("claude", args, {
4610
4855
  cwd: options.cwd,
4611
4856
  stdio: ["inherit", "pipe", "pipe"],
4612
4857
  env: options.spawnEnv || { ...process.env }
@@ -4740,7 +4985,7 @@ ${source_default.red("!")} Claude Code auth failure (stderr): "${authError}"`);
4740
4985
  }
4741
4986
  async function launchRelayMode(prompt, options) {
4742
4987
  return new Promise((resolve, reject) => {
4743
- const child = (0, import_node_child_process4.spawn)("claude", [], {
4988
+ const child = (0, import_node_child_process5.spawn)("claude", [], {
4744
4989
  cwd: options.cwd,
4745
4990
  stdio: ["pipe", "pipe", "pipe"],
4746
4991
  env: options.spawnEnv || { ...process.env }
@@ -4966,19 +5211,19 @@ async function handleSelfUpdate(task, state, creds) {
4966
5211
  let output = "";
4967
5212
  if (source === "npm" || source.startsWith("npm:")) {
4968
5213
  const pkg = source === "npm" ? "@controlvector/cv-agent@latest" : source.replace("npm:", "");
4969
- output = (0, import_node_child_process4.execSync)(`npm install -g ${pkg} 2>&1`, { encoding: "utf8", timeout: 12e4 });
5214
+ output = (0, import_node_child_process5.execSync)(`npm install -g ${pkg} 2>&1`, { encoding: "utf8", timeout: 12e4 });
4970
5215
  } else if (source.startsWith("git:")) {
4971
5216
  const repoPath = source.replace("git:", "");
4972
- output = (0, import_node_child_process4.execSync)(`cd ${repoPath} && git pull && npm install && npm run build && npm link 2>&1`, {
5217
+ output = (0, import_node_child_process5.execSync)(`cd ${repoPath} && git pull && npm install && npm run build && npm link 2>&1`, {
4973
5218
  encoding: "utf8",
4974
5219
  timeout: 3e5
4975
5220
  });
4976
5221
  } else {
4977
- output = (0, import_node_child_process4.execSync)(`npm install -g @controlvector/cv-agent@latest 2>&1`, { encoding: "utf8", timeout: 12e4 });
5222
+ output = (0, import_node_child_process5.execSync)(`npm install -g @controlvector/cv-agent@latest 2>&1`, { encoding: "utf8", timeout: 12e4 });
4978
5223
  }
4979
5224
  let newVersion = "unknown";
4980
5225
  try {
4981
- newVersion = (0, import_node_child_process4.execSync)("cva --version 2>/dev/null || echo unknown", { encoding: "utf8" }).trim();
5226
+ newVersion = (0, import_node_child_process5.execSync)("cva --version 2>/dev/null || echo unknown", { encoding: "utf8" }).trim();
4982
5227
  } catch {
4983
5228
  }
4984
5229
  postTaskEvent(creds, task.id, {
@@ -5004,7 +5249,7 @@ async function handleSelfUpdate(task, state, creds) {
5004
5249
  if (task.input?.constraints?.includes("restart")) {
5005
5250
  console.log(source_default.yellow("Restarting agent with updated binary..."));
5006
5251
  const args = process.argv.slice(1).join(" ");
5007
- (0, import_node_child_process4.execSync)(`nohup cva ${args} > /tmp/cva-restart.log 2>&1 &`, { stdio: "ignore" });
5252
+ (0, import_node_child_process5.execSync)(`nohup cva ${args} > /tmp/cva-restart.log 2>&1 &`, { stdio: "ignore" });
5008
5253
  process.exit(0);
5009
5254
  }
5010
5255
  } catch (err) {
@@ -5036,7 +5281,7 @@ async function runAgent(options) {
5036
5281
  process.exit(1);
5037
5282
  }
5038
5283
  try {
5039
- (0, import_node_child_process4.execSync)("claude --version", { stdio: "pipe", timeout: 5e3 });
5284
+ (0, import_node_child_process5.execSync)("claude --version", { stdio: "pipe", timeout: 5e3 });
5040
5285
  } catch {
5041
5286
  console.log();
5042
5287
  console.log(source_default.red("Claude Code CLI not found.") + " Install it first:");
@@ -5065,7 +5310,7 @@ async function runAgent(options) {
5065
5310
  currentAuthStatus = "api_key_fallback";
5066
5311
  }
5067
5312
  try {
5068
- (0, import_node_child_process4.execSync)("cv --version", { stdio: "pipe", timeout: 5e3 });
5313
+ (0, import_node_child_process5.execSync)("cv --version", { stdio: "pipe", timeout: 5e3 });
5069
5314
  } catch {
5070
5315
  console.log(source_default.yellow("!") + " cv-git CLI not found. Claude Code will fall back to raw git commands.");
5071
5316
  console.log(` Install it: ${source_default.cyan("npm install -g @controlvector/cv-git")}`);
@@ -5085,7 +5330,7 @@ async function runAgent(options) {
5085
5330
  }
5086
5331
  let detectedRepoId;
5087
5332
  try {
5088
- const remoteUrl = (0, import_node_child_process4.execSync)("git remote get-url origin 2>/dev/null", {
5333
+ const remoteUrl = (0, import_node_child_process5.execSync)("git remote get-url origin 2>/dev/null", {
5089
5334
  cwd: workingDir,
5090
5335
  encoding: "utf8",
5091
5336
  timeout: 5e3
@@ -5609,7 +5854,7 @@ function authCommand() {
5609
5854
  }
5610
5855
 
5611
5856
  // src/commands/remote.ts
5612
- var import_node_child_process5 = require("node:child_process");
5857
+ var import_node_child_process6 = require("node:child_process");
5613
5858
  function getGitHost(apiUrl) {
5614
5859
  return apiUrl.replace(/^https?:\/\//, "").replace(/^api\./, "git.");
5615
5860
  }
@@ -5624,16 +5869,16 @@ async function remoteAdd(ownerRepo) {
5624
5869
  }
5625
5870
  const remoteUrl = `https://${gitHost}/${owner}/${repo}.git`;
5626
5871
  try {
5627
- const existing = (0, import_node_child_process5.execSync)("git remote get-url cvhub", { encoding: "utf-8", timeout: 5e3 }).trim();
5872
+ const existing = (0, import_node_child_process6.execSync)("git remote get-url cvhub", { encoding: "utf-8", timeout: 5e3 }).trim();
5628
5873
  if (existing === remoteUrl) {
5629
5874
  console.log(source_default.gray(`Remote 'cvhub' already set to ${remoteUrl}`));
5630
5875
  return;
5631
5876
  }
5632
- (0, import_node_child_process5.execSync)(`git remote set-url cvhub ${remoteUrl}`, { timeout: 5e3 });
5877
+ (0, import_node_child_process6.execSync)(`git remote set-url cvhub ${remoteUrl}`, { timeout: 5e3 });
5633
5878
  console.log(source_default.green("Updated") + ` remote 'cvhub' -> ${remoteUrl}`);
5634
5879
  } catch {
5635
5880
  try {
5636
- (0, import_node_child_process5.execSync)(`git remote add cvhub ${remoteUrl}`, { timeout: 5e3 });
5881
+ (0, import_node_child_process6.execSync)(`git remote add cvhub ${remoteUrl}`, { timeout: 5e3 });
5637
5882
  console.log(source_default.green("Added") + ` remote 'cvhub' -> ${remoteUrl}`);
5638
5883
  } catch (err) {
5639
5884
  console.log(source_default.red("Failed to add remote:") + ` ${err.message}`);
@@ -5825,7 +6070,8 @@ function statusCommand() {
5825
6070
 
5826
6071
  // src/index.ts
5827
6072
  var program2 = new Command();
5828
- program2.name("cva").description("CV-Hub Agent \u2014 bridges Claude Code with CV-Hub task dispatch").version(true ? "1.6.0" : "1.1.0");
6073
+ 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.7.1" : "1.6.0");
6074
+ program2.addCommand(setupCommand());
5829
6075
  program2.addCommand(agentCommand());
5830
6076
  program2.addCommand(authCommand());
5831
6077
  program2.addCommand(remoteCommand());