@controlvector/cv-agent 1.9.0 → 1.9.2
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 +210 -31
- package/dist/bundle.cjs.map +3 -3
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +64 -6
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/git-safety.d.ts +12 -6
- package/dist/commands/git-safety.d.ts.map +1 -1
- package/dist/commands/git-safety.js +114 -22
- package/dist/commands/git-safety.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +40 -0
- package/dist/commands/setup.js.map +1 -1
- package/package.json +1 -1
package/dist/bundle.cjs
CHANGED
|
@@ -3847,10 +3847,10 @@ async function runSetup() {
|
|
|
3847
3847
|
console.log(` ${source_default.cyan("a")} \u2014 Initialize a new project here: ${cwd}`);
|
|
3848
3848
|
console.log(` ${source_default.cyan("b")} \u2014 Clone an existing repo from CV-Hub`);
|
|
3849
3849
|
console.log();
|
|
3850
|
-
const choice = await new Promise((
|
|
3850
|
+
const choice = await new Promise((resolve2) => {
|
|
3851
3851
|
rl.question(" Choose [a/b]: ", (answer) => {
|
|
3852
3852
|
rl.close();
|
|
3853
|
-
|
|
3853
|
+
resolve2(answer.trim().toLowerCase() || "a");
|
|
3854
3854
|
});
|
|
3855
3855
|
});
|
|
3856
3856
|
if (choice === "b" && token) {
|
|
@@ -3878,10 +3878,10 @@ async function runSetup() {
|
|
|
3878
3878
|
});
|
|
3879
3879
|
console.log();
|
|
3880
3880
|
const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
3881
|
-
const selection = await new Promise((
|
|
3881
|
+
const selection = await new Promise((resolve2) => {
|
|
3882
3882
|
rl2.question(` Select a repo [1-${displayRepos.length}]: `, (answer) => {
|
|
3883
3883
|
rl2.close();
|
|
3884
|
-
|
|
3884
|
+
resolve2(answer.trim());
|
|
3885
3885
|
});
|
|
3886
3886
|
});
|
|
3887
3887
|
const idx = parseInt(selection, 10) - 1;
|
|
@@ -3929,6 +3929,41 @@ async function runSetup() {
|
|
|
3929
3929
|
} else {
|
|
3930
3930
|
console.log(source_default.green(" \u2713") + " CLAUDE.md present");
|
|
3931
3931
|
}
|
|
3932
|
+
const gitignorePath = (0, import_node_path.join)(cwd, ".gitignore");
|
|
3933
|
+
const CREDENTIAL_PATTERNS = [
|
|
3934
|
+
"# Credentials and secrets (auto-added by cv-agent)",
|
|
3935
|
+
".env",
|
|
3936
|
+
".env.*",
|
|
3937
|
+
".claude/",
|
|
3938
|
+
".claude.json",
|
|
3939
|
+
".credentials*",
|
|
3940
|
+
"*.pem",
|
|
3941
|
+
"*.key",
|
|
3942
|
+
".ssh/",
|
|
3943
|
+
".gnupg/",
|
|
3944
|
+
".npm/",
|
|
3945
|
+
".config/",
|
|
3946
|
+
".zsh_history",
|
|
3947
|
+
".bash_history",
|
|
3948
|
+
".zsh_sessions/",
|
|
3949
|
+
"node_modules/",
|
|
3950
|
+
".DS_Store"
|
|
3951
|
+
];
|
|
3952
|
+
try {
|
|
3953
|
+
let gitignoreContent = "";
|
|
3954
|
+
if ((0, import_node_fs.existsSync)(gitignorePath)) {
|
|
3955
|
+
gitignoreContent = (0, import_node_fs.readFileSync)(gitignorePath, "utf-8");
|
|
3956
|
+
}
|
|
3957
|
+
const missing = CREDENTIAL_PATTERNS.filter((p) => !gitignoreContent.includes(p));
|
|
3958
|
+
if (missing.length > 0) {
|
|
3959
|
+
const addition = (gitignoreContent && !gitignoreContent.endsWith("\n") ? "\n" : "") + missing.join("\n") + "\n";
|
|
3960
|
+
(0, import_node_fs.writeFileSync)(gitignorePath, gitignoreContent + addition);
|
|
3961
|
+
console.log(source_default.green(" \u2713") + " .gitignore updated with credential protection");
|
|
3962
|
+
} else {
|
|
3963
|
+
console.log(source_default.green(" \u2713") + " .gitignore has credential protection");
|
|
3964
|
+
}
|
|
3965
|
+
} catch {
|
|
3966
|
+
}
|
|
3932
3967
|
if (!hasCVDir) {
|
|
3933
3968
|
(0, import_node_fs.mkdirSync)((0, import_node_path.join)(cwd, ".cv"), { recursive: true });
|
|
3934
3969
|
}
|
|
@@ -4015,10 +4050,10 @@ async function runSetup() {
|
|
|
4015
4050
|
if (!agentRunning) {
|
|
4016
4051
|
const readline = await import("node:readline");
|
|
4017
4052
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
4018
|
-
const answer = await new Promise((
|
|
4053
|
+
const answer = await new Promise((resolve2) => {
|
|
4019
4054
|
rl.question(" Start the CV-Agent daemon? (Y/n): ", (a) => {
|
|
4020
4055
|
rl.close();
|
|
4021
|
-
|
|
4056
|
+
resolve2(a.trim().toLowerCase() || "y");
|
|
4022
4057
|
});
|
|
4023
4058
|
});
|
|
4024
4059
|
if (answer === "y" || answer === "yes" || answer === "") {
|
|
@@ -4558,11 +4593,78 @@ async function writeConfig(config) {
|
|
|
4558
4593
|
|
|
4559
4594
|
// src/commands/git-safety.ts
|
|
4560
4595
|
var import_node_child_process3 = require("node:child_process");
|
|
4596
|
+
var import_node_fs2 = require("node:fs");
|
|
4597
|
+
var import_node_path2 = require("node:path");
|
|
4598
|
+
var import_node_os3 = require("node:os");
|
|
4599
|
+
var DANGEROUS_PATTERNS = [
|
|
4600
|
+
".claude/",
|
|
4601
|
+
".claude.json",
|
|
4602
|
+
".credentials",
|
|
4603
|
+
".zsh_history",
|
|
4604
|
+
".bash_history",
|
|
4605
|
+
".zsh_sessions/",
|
|
4606
|
+
".ssh/",
|
|
4607
|
+
".gnupg/",
|
|
4608
|
+
".npm/",
|
|
4609
|
+
".config/",
|
|
4610
|
+
".CFUserTextEncoding",
|
|
4611
|
+
"Library/",
|
|
4612
|
+
"Applications/",
|
|
4613
|
+
".Trash/",
|
|
4614
|
+
".DS_Store",
|
|
4615
|
+
"node_modules/",
|
|
4616
|
+
".env",
|
|
4617
|
+
".env.local",
|
|
4618
|
+
".env.production"
|
|
4619
|
+
];
|
|
4561
4620
|
function git(cmd, cwd) {
|
|
4562
4621
|
return (0, import_node_child_process3.execSync)(cmd, { cwd, encoding: "utf8", timeout: 3e4 }).trim();
|
|
4563
4622
|
}
|
|
4623
|
+
function checkWorkspaceSafety(workspaceRoot) {
|
|
4624
|
+
const resolved = (0, import_node_path2.resolve)(workspaceRoot);
|
|
4625
|
+
const home = (0, import_node_path2.resolve)((0, import_node_os3.homedir)());
|
|
4626
|
+
if (resolved === home) {
|
|
4627
|
+
return `Workspace is user HOME directory (${home}). Refusing to auto-commit to prevent indexing personal files.`;
|
|
4628
|
+
}
|
|
4629
|
+
if (home.startsWith(resolved + "/")) {
|
|
4630
|
+
return `Workspace (${resolved}) is a parent of HOME. Refusing to auto-commit.`;
|
|
4631
|
+
}
|
|
4632
|
+
if (!(0, import_node_fs2.existsSync)((0, import_node_path2.join)(resolved, ".git"))) {
|
|
4633
|
+
return `No .git directory in ${resolved}. Not a git repository.`;
|
|
4634
|
+
}
|
|
4635
|
+
return null;
|
|
4636
|
+
}
|
|
4637
|
+
function filterDangerousFiles(statusLines) {
|
|
4638
|
+
const safe = [];
|
|
4639
|
+
const blocked = [];
|
|
4640
|
+
for (const line of statusLines) {
|
|
4641
|
+
const filePath = line.substring(3).trim();
|
|
4642
|
+
const isDangerous = DANGEROUS_PATTERNS.some(
|
|
4643
|
+
(pattern) => filePath.startsWith(pattern) || filePath.includes("/" + pattern)
|
|
4644
|
+
);
|
|
4645
|
+
if (isDangerous) {
|
|
4646
|
+
blocked.push(filePath);
|
|
4647
|
+
} else {
|
|
4648
|
+
safe.push(line);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
return { safe, blocked };
|
|
4652
|
+
}
|
|
4564
4653
|
function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
|
|
4565
4654
|
const targetBranch = branch || "main";
|
|
4655
|
+
const safetyError = checkWorkspaceSafety(workspaceRoot);
|
|
4656
|
+
if (safetyError) {
|
|
4657
|
+
console.log(` [git-safety] BLOCKED: ${safetyError}`);
|
|
4658
|
+
return {
|
|
4659
|
+
hadChanges: false,
|
|
4660
|
+
filesAdded: 0,
|
|
4661
|
+
filesModified: 0,
|
|
4662
|
+
filesDeleted: 0,
|
|
4663
|
+
pushed: false,
|
|
4664
|
+
skipped: true,
|
|
4665
|
+
skipReason: safetyError
|
|
4666
|
+
};
|
|
4667
|
+
}
|
|
4566
4668
|
try {
|
|
4567
4669
|
let statusOutput;
|
|
4568
4670
|
try {
|
|
@@ -4570,8 +4672,8 @@ function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
|
|
|
4570
4672
|
} catch {
|
|
4571
4673
|
return { hadChanges: false, filesAdded: 0, filesModified: 0, filesDeleted: 0, pushed: false, error: "git status failed" };
|
|
4572
4674
|
}
|
|
4573
|
-
const
|
|
4574
|
-
if (
|
|
4675
|
+
const allLines = statusOutput.split("\n").filter(Boolean);
|
|
4676
|
+
if (allLines.length === 0) {
|
|
4575
4677
|
try {
|
|
4576
4678
|
const unpushed = git(`git log origin/${targetBranch}..HEAD --oneline 2>/dev/null`, workspaceRoot);
|
|
4577
4679
|
if (unpushed) {
|
|
@@ -4583,8 +4685,16 @@ function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
|
|
|
4583
4685
|
}
|
|
4584
4686
|
return { hadChanges: false, filesAdded: 0, filesModified: 0, filesDeleted: 0, pushed: false };
|
|
4585
4687
|
}
|
|
4688
|
+
const { safe: safeLines, blocked } = filterDangerousFiles(allLines);
|
|
4689
|
+
if (blocked.length > 0) {
|
|
4690
|
+
console.log(` [git-safety] Blocked ${blocked.length} sensitive file(s) from staging: ${blocked.slice(0, 5).join(", ")}${blocked.length > 5 ? "..." : ""}`);
|
|
4691
|
+
}
|
|
4692
|
+
if (safeLines.length === 0) {
|
|
4693
|
+
console.log(` [git-safety] All ${allLines.length} changed files were blocked by safety filter`);
|
|
4694
|
+
return { hadChanges: false, filesAdded: 0, filesModified: 0, filesDeleted: 0, pushed: false };
|
|
4695
|
+
}
|
|
4586
4696
|
let added = 0, modified = 0, deleted = 0;
|
|
4587
|
-
for (const line of
|
|
4697
|
+
for (const line of safeLines) {
|
|
4588
4698
|
const code = line.substring(0, 2);
|
|
4589
4699
|
if (code.includes("?")) added++;
|
|
4590
4700
|
else if (code.includes("D")) deleted++;
|
|
@@ -4592,9 +4702,15 @@ function gitSafetyNet(workspaceRoot, taskTitle, taskId, branch) {
|
|
|
4592
4702
|
else added++;
|
|
4593
4703
|
}
|
|
4594
4704
|
console.log(
|
|
4595
|
-
` [git-safety] ${
|
|
4705
|
+
` [git-safety] ${safeLines.length} safe changes (${added} new, ${modified} modified, ${deleted} deleted) \u2014 committing now`
|
|
4596
4706
|
);
|
|
4597
|
-
|
|
4707
|
+
for (const line of safeLines) {
|
|
4708
|
+
const filePath = line.substring(3).trim();
|
|
4709
|
+
try {
|
|
4710
|
+
git(`git add -- ${JSON.stringify(filePath)}`, workspaceRoot);
|
|
4711
|
+
} catch {
|
|
4712
|
+
}
|
|
4713
|
+
}
|
|
4598
4714
|
const shortId = taskId.substring(0, 8);
|
|
4599
4715
|
const commitMsg = `task: ${taskTitle} [${shortId}]
|
|
4600
4716
|
|
|
@@ -4655,8 +4771,8 @@ Files: ${added} added, ${modified} modified, ${deleted} deleted`;
|
|
|
4655
4771
|
|
|
4656
4772
|
// src/commands/deploy-manifest.ts
|
|
4657
4773
|
var import_node_child_process4 = require("node:child_process");
|
|
4658
|
-
var
|
|
4659
|
-
var
|
|
4774
|
+
var import_node_fs3 = require("node:fs");
|
|
4775
|
+
var import_node_path3 = require("node:path");
|
|
4660
4776
|
function exec(cmd, cwd, timeoutMs = 3e5, env2) {
|
|
4661
4777
|
try {
|
|
4662
4778
|
const stdout = (0, import_node_child_process4.execSync)(cmd, {
|
|
@@ -4699,10 +4815,10 @@ function getHeadCommit(cwd) {
|
|
|
4699
4815
|
}
|
|
4700
4816
|
}
|
|
4701
4817
|
function loadDeployManifest(workspaceRoot) {
|
|
4702
|
-
const manifestPath = (0,
|
|
4703
|
-
if (!(0,
|
|
4818
|
+
const manifestPath = (0, import_node_path3.join)(workspaceRoot, ".cva", "deploy.json");
|
|
4819
|
+
if (!(0, import_node_fs3.existsSync)(manifestPath)) return null;
|
|
4704
4820
|
try {
|
|
4705
|
-
const raw = (0,
|
|
4821
|
+
const raw = (0, import_node_fs3.readFileSync)(manifestPath, "utf8");
|
|
4706
4822
|
const manifest = JSON.parse(raw);
|
|
4707
4823
|
if (!manifest.version || manifest.version < 1) {
|
|
4708
4824
|
console.log(" [deploy] Invalid manifest version");
|
|
@@ -4727,7 +4843,7 @@ async function postTaskDeploy(workspaceRoot, taskId, log) {
|
|
|
4727
4843
|
console.log(` [deploy] Building: ${buildStep.name}`);
|
|
4728
4844
|
log("lifecycle", `Building: ${buildStep.name}`);
|
|
4729
4845
|
const start = Date.now();
|
|
4730
|
-
const cwd = (0,
|
|
4846
|
+
const cwd = (0, import_node_path3.join)(workspaceRoot, buildStep.working_dir || ".");
|
|
4731
4847
|
const timeoutMs = (buildStep.timeout_seconds || 300) * 1e3;
|
|
4732
4848
|
const result = exec(buildStep.command, cwd, timeoutMs);
|
|
4733
4849
|
if (!result.ok) {
|
|
@@ -4818,7 +4934,7 @@ async function rollback(workspaceRoot, targetCommit, manifest, log) {
|
|
|
4818
4934
|
}
|
|
4819
4935
|
if (manifest.build?.steps) {
|
|
4820
4936
|
for (const step of manifest.build.steps) {
|
|
4821
|
-
exec(step.command, (0,
|
|
4937
|
+
exec(step.command, (0, import_node_path3.join)(workspaceRoot, step.working_dir || "."), (step.timeout_seconds || 300) * 1e3);
|
|
4822
4938
|
}
|
|
4823
4939
|
}
|
|
4824
4940
|
if (manifest.service?.restart_command) {
|
|
@@ -4976,6 +5092,22 @@ Target repository: ${task.owner}/${task.repo}
|
|
|
4976
5092
|
`;
|
|
4977
5093
|
prompt += `
|
|
4978
5094
|
|
|
5095
|
+
## Security \u2014 NEVER Commit Secrets
|
|
5096
|
+
`;
|
|
5097
|
+
prompt += `Do NOT add, commit, or push any of the following:
|
|
5098
|
+
`;
|
|
5099
|
+
prompt += `- API keys, tokens, passwords, or credentials
|
|
5100
|
+
`;
|
|
5101
|
+
prompt += `- .env files, .credentials files, .claude/ directory
|
|
5102
|
+
`;
|
|
5103
|
+
prompt += `- SSH keys (.ssh/), GPG keys (.gnupg/)
|
|
5104
|
+
`;
|
|
5105
|
+
prompt += `- Shell history (.zsh_history, .bash_history)
|
|
5106
|
+
`;
|
|
5107
|
+
prompt += `If you need to reference an API key, use an environment variable placeholder.
|
|
5108
|
+
`;
|
|
5109
|
+
prompt += `
|
|
5110
|
+
|
|
4979
5111
|
---
|
|
4980
5112
|
`;
|
|
4981
5113
|
prompt += `When complete, provide a brief summary of what you accomplished.
|
|
@@ -5054,7 +5186,7 @@ async function launchAutoApproveMode(prompt, options) {
|
|
|
5054
5186
|
let fullOutput = "";
|
|
5055
5187
|
let lastProgressBytes = 0;
|
|
5056
5188
|
const runOnce = (inputPrompt, isContinue) => {
|
|
5057
|
-
return new Promise((
|
|
5189
|
+
return new Promise((resolve2, reject) => {
|
|
5058
5190
|
const args = isContinue ? ["-p", inputPrompt, "--continue", "--allowedTools", ...ALLOWED_TOOLS] : ["-p", inputPrompt, "--allowedTools", ...ALLOWED_TOOLS];
|
|
5059
5191
|
if (sessionId && !isContinue) {
|
|
5060
5192
|
args.push("--session-id", sessionId);
|
|
@@ -5153,7 +5285,7 @@ ${source_default.red("!")} Claude Code auth failure (stderr): "${authError}"`);
|
|
|
5153
5285
|
});
|
|
5154
5286
|
child.on("close", (code, signal) => {
|
|
5155
5287
|
_activeChild = null;
|
|
5156
|
-
|
|
5288
|
+
resolve2({
|
|
5157
5289
|
exitCode: signal === "SIGKILL" ? 137 : code ?? 1,
|
|
5158
5290
|
stderr,
|
|
5159
5291
|
output: fullOutput,
|
|
@@ -5192,7 +5324,7 @@ ${source_default.red("!")} Claude Code auth failure (stderr): "${authError}"`);
|
|
|
5192
5324
|
return result;
|
|
5193
5325
|
}
|
|
5194
5326
|
async function launchRelayMode(prompt, options) {
|
|
5195
|
-
return new Promise((
|
|
5327
|
+
return new Promise((resolve2, reject) => {
|
|
5196
5328
|
const child = (0, import_node_child_process5.spawn)("claude", [], {
|
|
5197
5329
|
cwd: options.cwd,
|
|
5198
5330
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -5385,9 +5517,9 @@ ${source_default.red("!")} Claude Code auth failure (stderr): "${authError}"`);
|
|
|
5385
5517
|
child.on("close", (code, signal) => {
|
|
5386
5518
|
_activeChild = null;
|
|
5387
5519
|
if (signal === "SIGKILL") {
|
|
5388
|
-
|
|
5520
|
+
resolve2({ exitCode: 137, stderr, output: fullOutput, authFailure });
|
|
5389
5521
|
} else {
|
|
5390
|
-
|
|
5522
|
+
resolve2({ exitCode: code ?? 1, stderr, output: fullOutput, authFailure });
|
|
5391
5523
|
}
|
|
5392
5524
|
});
|
|
5393
5525
|
child.on("error", (err) => {
|
|
@@ -5488,14 +5620,45 @@ async function runAgent(options) {
|
|
|
5488
5620
|
console.log();
|
|
5489
5621
|
process.exit(1);
|
|
5490
5622
|
}
|
|
5623
|
+
if (process.env.CV_DEBUG) {
|
|
5624
|
+
console.log(source_default.gray(` PATH: ${process.env.PATH}`));
|
|
5625
|
+
console.log(source_default.gray(` HOME: ${process.env.HOME}`));
|
|
5626
|
+
console.log(source_default.gray(` SHELL: ${process.env.SHELL}`));
|
|
5627
|
+
}
|
|
5628
|
+
let claudeBinary = "claude";
|
|
5491
5629
|
try {
|
|
5492
5630
|
(0, import_node_child_process5.execSync)("claude --version", { stdio: "pipe", timeout: 5e3 });
|
|
5493
5631
|
} catch {
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5632
|
+
const candidates = [
|
|
5633
|
+
"/usr/local/bin/claude",
|
|
5634
|
+
"/opt/homebrew/bin/claude",
|
|
5635
|
+
`${process.env.HOME}/.npm-global/bin/claude`,
|
|
5636
|
+
`${process.env.HOME}/.nvm/versions/node/*/bin/claude`
|
|
5637
|
+
];
|
|
5638
|
+
let found = false;
|
|
5639
|
+
for (const candidate of candidates) {
|
|
5640
|
+
try {
|
|
5641
|
+
const resolved = (0, import_node_child_process5.execSync)(`ls ${candidate} 2>/dev/null | head -1`, { encoding: "utf8", timeout: 3e3 }).trim();
|
|
5642
|
+
if (resolved) {
|
|
5643
|
+
(0, import_node_child_process5.execSync)(`${resolved} --version`, { stdio: "pipe", timeout: 5e3 });
|
|
5644
|
+
claudeBinary = resolved;
|
|
5645
|
+
found = true;
|
|
5646
|
+
console.log(source_default.yellow("!") + ` Claude Code found at ${resolved} (not on PATH)`);
|
|
5647
|
+
break;
|
|
5648
|
+
}
|
|
5649
|
+
} catch {
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
if (!found) {
|
|
5653
|
+
console.log();
|
|
5654
|
+
console.log(source_default.red("Claude Code CLI not found.") + " Install it first:");
|
|
5655
|
+
console.log(` ${source_default.cyan("npm install -g @anthropic-ai/claude-code")}`);
|
|
5656
|
+
console.log();
|
|
5657
|
+
console.log(source_default.gray(` Current PATH: ${process.env.PATH}`));
|
|
5658
|
+
console.log(source_default.gray(" If running via Launch Agent, ensure PATH includes the directory where claude is installed."));
|
|
5659
|
+
console.log();
|
|
5660
|
+
process.exit(1);
|
|
5661
|
+
}
|
|
5499
5662
|
}
|
|
5500
5663
|
const { env: claudeEnv, usingApiKey } = await getClaudeEnv();
|
|
5501
5664
|
const authCheck = await checkClaudeAuth();
|
|
@@ -5562,6 +5725,22 @@ async function runAgent(options) {
|
|
|
5562
5725
|
} catch {
|
|
5563
5726
|
}
|
|
5564
5727
|
}
|
|
5728
|
+
const gitignorePath = require("path").join(workingDir, ".gitignore");
|
|
5729
|
+
try {
|
|
5730
|
+
const fs3 = require("fs");
|
|
5731
|
+
const credPatterns = ".env\n.env.*\n.claude/\n.claude.json\n.credentials*\n*.pem\n*.key\n.ssh/\n.gnupg/\n.npm/\n.config/\n.zsh_history\n.bash_history\nnode_modules/\n.DS_Store\n";
|
|
5732
|
+
let existing = "";
|
|
5733
|
+
try {
|
|
5734
|
+
existing = fs3.readFileSync(gitignorePath, "utf-8");
|
|
5735
|
+
} catch {
|
|
5736
|
+
}
|
|
5737
|
+
if (!existing.includes(".claude/")) {
|
|
5738
|
+
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
5739
|
+
fs3.writeFileSync(gitignorePath, existing + prefix + "# Credentials (auto-added by cv-agent)\n" + credPatterns);
|
|
5740
|
+
console.log(source_default.gray(" Bootstrap: .gitignore credential protection added"));
|
|
5741
|
+
}
|
|
5742
|
+
} catch {
|
|
5743
|
+
}
|
|
5565
5744
|
const cvDir = require("path").join(workingDir, ".cv");
|
|
5566
5745
|
if (!require("fs").existsSync(cvDir)) {
|
|
5567
5746
|
try {
|
|
@@ -6049,7 +6228,7 @@ async function promptForToken() {
|
|
|
6049
6228
|
input: process.stdin,
|
|
6050
6229
|
output: process.stdout
|
|
6051
6230
|
});
|
|
6052
|
-
return new Promise((
|
|
6231
|
+
return new Promise((resolve2) => {
|
|
6053
6232
|
rl.question("Enter your CV-Hub PAT token: ", (answer) => {
|
|
6054
6233
|
rl.close();
|
|
6055
6234
|
const token = answer.trim();
|
|
@@ -6057,7 +6236,7 @@ async function promptForToken() {
|
|
|
6057
6236
|
console.log(source_default.red("No token provided."));
|
|
6058
6237
|
process.exit(1);
|
|
6059
6238
|
}
|
|
6060
|
-
|
|
6239
|
+
resolve2(token);
|
|
6061
6240
|
});
|
|
6062
6241
|
});
|
|
6063
6242
|
}
|
|
@@ -6336,7 +6515,7 @@ function statusCommand() {
|
|
|
6336
6515
|
|
|
6337
6516
|
// src/index.ts
|
|
6338
6517
|
var program2 = new Command();
|
|
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.
|
|
6518
|
+
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.2" : "1.6.0");
|
|
6340
6519
|
program2.addCommand(setupCommand());
|
|
6341
6520
|
program2.addCommand(agentCommand());
|
|
6342
6521
|
program2.addCommand(authCommand());
|