codiedev 0.10.0-beta.4 → 0.10.0-beta.6
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 +11 -5
- package/assets/tui-brand-plugin.tsx +14 -2
- package/dist/backup/cache.js +1 -5
- package/dist/backup/match.js +0 -6
- package/dist/backup/run.js +3 -35
- package/dist/captureExclusions.js +0 -12
- package/dist/captureLog.js +0 -28
- package/dist/captureReadiness.js +0 -58
- package/dist/captureSignals.js +68 -3
- package/dist/cli.js +75 -64
- package/dist/codexHookTrust.js +125 -6
- package/dist/codexLimitScan.js +2 -109
- package/dist/codie.js +50 -114
- package/dist/codieBrandInstall.js +0 -18
- package/dist/codieLauncher.js +20 -92
- package/dist/codieRuntime.js +19 -23
- package/dist/codieRuntimeInstall.js +108 -23
- package/dist/codieUsage.js +38 -41
- package/dist/commands/agentTemplates.generated.js +136 -0
- package/dist/commands/agents.js +1066 -0
- package/dist/commands/agentsSdk.generated.js +7 -0
- package/dist/commands/ask.js +0 -3
- package/dist/commands/capture.js +0 -2
- package/dist/commands/createTicket.js +0 -10
- package/dist/commands/doctor.js +53 -120
- package/dist/commands/evals.js +187 -0
- package/dist/commands/inbox.js +0 -2
- package/dist/commands/library.js +0 -3
- package/dist/commands/pack.js +573 -0
- package/dist/commands/ping.js +0 -2
- package/dist/commands/pull.js +6 -10
- package/dist/commands/push.js +2 -12
- package/dist/commands/search.js +0 -4
- package/dist/commands/send.js +0 -5
- package/dist/commands/share.js +0 -4
- package/dist/commands/shared.js +0 -35
- package/dist/commands/traces.js +344 -0
- package/dist/commands/tracesLabel.js +348 -0
- package/dist/configDir.js +0 -10
- package/dist/connect.js +19 -116
- package/dist/connectFlow.js +0 -9
- package/dist/copilotHooks.js +391 -0
- package/dist/copilotInstallation.js +64 -0
- package/dist/cursorHooks.js +38 -30
- package/dist/cursorLifecycle.js +109 -0
- package/dist/detection.js +0 -30
- package/dist/harnessDirs.js +77 -0
- package/dist/hook.js +182 -469
- package/dist/inboxFormat.js +0 -24
- package/dist/launchContext.js +150 -0
- package/dist/launcher.js +140 -0
- package/dist/limitEvent.js +41 -35
- package/dist/limitEventReporter.js +1 -1
- package/dist/managedPi.js +240 -0
- package/dist/mcp.js +3 -384
- package/dist/nativeSteering.js +24 -0
- package/dist/packs/codie.js +182 -0
- package/dist/packs/harnesses.js +411 -0
- package/dist/packs/hookGate.js +256 -0
- package/dist/packs/install.js +286 -0
- package/dist/packs/manifest.js +126 -0
- package/dist/packs/paths.js +81 -0
- package/dist/packs/shim.js +214 -0
- package/dist/packs/store.js +155 -0
- package/dist/packs/sync.js +170 -0
- package/dist/piHooks.js +216 -0
- package/dist/piRuntime.js +120 -0
- package/dist/repoResolver.js +0 -19
- package/dist/secret.js +0 -3
- package/dist/selfUpdate.js +376 -0
- package/dist/skillMarker.js +23 -0
- package/dist/subagents.js +135 -0
- package/dist/teamSkillContext.js +10 -0
- package/dist/transcriptModels.js +6 -8
- package/dist/upgradeNudge.js +0 -30
- package/dist/utils.js +494 -824
- package/dist/version.js +0 -10
- package/dist/versionCheck.js +0 -33
- package/package.json +8 -9
- package/dist/backup/cache.d.ts +0 -14
- package/dist/backup/match.d.ts +0 -2
- package/dist/backup/run.d.ts +0 -25
- package/dist/captureExclusions.d.ts +0 -30
- package/dist/captureLog.d.ts +0 -20
- package/dist/captureReadiness.d.ts +0 -65
- package/dist/captureSignals.d.ts +0 -19
- package/dist/cli.d.ts +0 -16
- package/dist/codexHookTrust.d.ts +0 -34
- package/dist/codexLimitScan.d.ts +0 -64
- package/dist/codie.d.ts +0 -2
- package/dist/codieBrandInstall.d.ts +0 -11
- package/dist/codieLauncher.d.ts +0 -86
- package/dist/codieRuntime.d.ts +0 -29
- package/dist/codieRuntimeInstall.d.ts +0 -28
- package/dist/codieStartup.d.ts +0 -26
- package/dist/codieStartup.js +0 -30
- package/dist/codieUsage.d.ts +0 -57
- package/dist/commands/ask.d.ts +0 -1
- package/dist/commands/capture.d.ts +0 -14
- package/dist/commands/createTicket.d.ts +0 -27
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/inbox.d.ts +0 -3
- package/dist/commands/library.d.ts +0 -2
- package/dist/commands/note.d.ts +0 -1
- package/dist/commands/ping.d.ts +0 -1
- package/dist/commands/promote.d.ts +0 -1
- package/dist/commands/promote.js +0 -53
- package/dist/commands/pull.d.ts +0 -2
- package/dist/commands/push.d.ts +0 -33
- package/dist/commands/react.d.ts +0 -2
- package/dist/commands/react.js +0 -40
- package/dist/commands/reverseTicket.d.ts +0 -2
- package/dist/commands/reverseTicket.js +0 -477
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/security.d.ts +0 -1
- package/dist/commands/security.js +0 -156
- package/dist/commands/send.d.ts +0 -2
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/shared.d.ts +0 -64
- package/dist/configDir.d.ts +0 -1
- package/dist/connect.d.ts +0 -1
- package/dist/connectFlow.d.ts +0 -13
- package/dist/cursorHooks.d.ts +0 -23
- package/dist/detection.d.ts +0 -30
- package/dist/hook.d.ts +0 -6
- package/dist/inboxFormat.d.ts +0 -38
- package/dist/limitEvent.d.ts +0 -16
- package/dist/limitEventReporter.d.ts +0 -21
- package/dist/mcp.d.ts +0 -12
- package/dist/prUrl.d.ts +0 -9
- package/dist/prUrl.js +0 -33
- package/dist/repoResolver.d.ts +0 -17
- package/dist/secret.d.ts +0 -1
- package/dist/security.d.ts +0 -102
- package/dist/security.js +0 -437
- package/dist/securityDeepScan.d.ts +0 -41
- package/dist/securityDeepScan.js +0 -248
- package/dist/securityDoctor.d.ts +0 -32
- package/dist/securityDoctor.js +0 -63
- package/dist/securityFeature.d.ts +0 -5
- package/dist/securityFeature.js +0 -7
- package/dist/securityInstall.d.ts +0 -63
- package/dist/securityInstall.js +0 -239
- package/dist/securityInventory.d.ts +0 -54
- package/dist/securityInventory.js +0 -556
- package/dist/securityPilot.d.ts +0 -19
- package/dist/securityPilot.js +0 -61
- package/dist/securityPolicy.d.ts +0 -33
- package/dist/securityPolicy.js +0 -188
- package/dist/securitySession.d.ts +0 -6
- package/dist/securitySession.js +0 -72
- package/dist/transcriptModels.d.ts +0 -18
- package/dist/upgradeNudge.d.ts +0 -25
- package/dist/utils.d.ts +0 -346
- package/dist/version.d.ts +0 -1
- package/dist/versionCheck.d.ts +0 -68
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseArgs = parseArgs;
|
|
37
|
+
exports.scoreValue = scoreValue;
|
|
38
|
+
exports.runScore = runScore;
|
|
39
|
+
exports.runScores = runScores;
|
|
40
|
+
exports.runQueue = runQueue;
|
|
41
|
+
exports.runJudge = runJudge;
|
|
42
|
+
exports.runImport = runImport;
|
|
43
|
+
exports.runAddExample = runAddExample;
|
|
44
|
+
exports.runVersions = runVersions;
|
|
45
|
+
exports.runSaveVersion = runSaveVersion;
|
|
46
|
+
exports.runOverview = runOverview;
|
|
47
|
+
exports.runRuns = runRuns;
|
|
48
|
+
exports.runRun = runRun;
|
|
49
|
+
exports.runScoreKinds = runScoreKinds;
|
|
50
|
+
exports.runQueueCreate = runQueueCreate;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const shared_1 = require("./shared");
|
|
54
|
+
const BOOL_FLAGS = new Set(["--failed", "--on", "--off", "--json"]);
|
|
55
|
+
function parseArgs(args) {
|
|
56
|
+
const out = { positional: [], flags: {}, bools: new Set(), runs: [] };
|
|
57
|
+
for (let i = 0; i < args.length; i++) {
|
|
58
|
+
const a = args[i];
|
|
59
|
+
if (BOOL_FLAGS.has(a)) {
|
|
60
|
+
out.bools.add(a);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (a.startsWith("--")) {
|
|
64
|
+
const eq = a.indexOf("=");
|
|
65
|
+
const name = eq > 0 ? a.slice(0, eq) : a;
|
|
66
|
+
const value = eq > 0 ? a.slice(eq + 1) : args[++i];
|
|
67
|
+
if (value === undefined)
|
|
68
|
+
throw new Error(`${name} needs a value`);
|
|
69
|
+
if (name === "--run")
|
|
70
|
+
out.runs.push(value);
|
|
71
|
+
else
|
|
72
|
+
out.flags[name] = value;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
out.positional.push(a);
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function scoreValue(raw) {
|
|
80
|
+
const t = raw.trim();
|
|
81
|
+
if (/^(true|false)$/i.test(t))
|
|
82
|
+
return t.toLowerCase() === "true";
|
|
83
|
+
if (t !== "" && Number.isFinite(Number(t)))
|
|
84
|
+
return Number(t);
|
|
85
|
+
return t;
|
|
86
|
+
}
|
|
87
|
+
async function call(config, tool, method, route, opts) {
|
|
88
|
+
const start = Date.now();
|
|
89
|
+
try {
|
|
90
|
+
const res = await (0, shared_1.apiRequest)(method, `/api/cli/traces/${route}`, { config, ...opts });
|
|
91
|
+
(0, shared_1.recordAgentEvent)(config, { tool, ok: true, latencyMs: Date.now() - start });
|
|
92
|
+
return res;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const e = err;
|
|
96
|
+
(0, shared_1.recordAgentEvent)(config, { tool, ok: false, latencyMs: Date.now() - start, error: e.message });
|
|
97
|
+
console.error(e.message);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function usage(text) {
|
|
102
|
+
console.error(`Usage: ${text}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
async function runScore(args, config) {
|
|
106
|
+
const p = parseArgs(args);
|
|
107
|
+
const [run, name, value] = p.positional;
|
|
108
|
+
if (!run || !name || value === undefined)
|
|
109
|
+
usage("codiedev traces score <run> <score> <value> [--agent name] [--comment text] [--step n]");
|
|
110
|
+
const res = await call(config, "codiedev_traces_score", "POST", "score", {
|
|
111
|
+
body: { run, name, value: scoreValue(value), agent: p.flags["--agent"], comment: p.flags["--comment"], ...(p.flags["--step"] ? { step: Number(p.flags["--step"]) } : {}) },
|
|
112
|
+
});
|
|
113
|
+
console.log(`✓ Scored ${res.runId}: ${name} = ${value}`);
|
|
114
|
+
}
|
|
115
|
+
async function runScores(args, config) {
|
|
116
|
+
const p = parseArgs(args);
|
|
117
|
+
const agent = p.positional[0];
|
|
118
|
+
if (!agent)
|
|
119
|
+
usage("codiedev traces scores <agent> [--days n] [--json]");
|
|
120
|
+
const res = await call(config, "codiedev_traces_scores", "GET", "scores", { query: { agent, days: p.flags["--days"] ?? "7" } });
|
|
121
|
+
if (p.bools.has("--json")) {
|
|
122
|
+
process.stdout.write(JSON.stringify(res, null, 2) + "\n");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!res.summary.length)
|
|
126
|
+
console.log(`No scores on ${res.agent} in the last ${p.flags["--days"] ?? 7} days.`);
|
|
127
|
+
for (const s of res.summary) {
|
|
128
|
+
const head = s.dataType === "boolean" && s.average !== null ? `${Math.round(s.average * 100)}% true`
|
|
129
|
+
: s.dataType === "numeric" && s.average !== null ? `avg ${Math.round(s.average * 100) / 100}`
|
|
130
|
+
: s.categories.map((c) => `${c.label} ${c.count}`).join(", ");
|
|
131
|
+
const from = [s.bySource.annotation ? `${s.bySource.annotation} people` : "", s.bySource.api ? `${s.bySource.api} your app` : "", s.bySource.judge ? `${s.bySource.judge} judge` : ""].filter(Boolean).join(", ");
|
|
132
|
+
console.log(`${s.name.padEnd(24)} ${head.padEnd(28)} ${s.count} scores (${from})`);
|
|
133
|
+
}
|
|
134
|
+
if (res.kinds.length)
|
|
135
|
+
console.log(`\nScore kinds: ${res.kinds.map((k) => `${k.name} (${k.dataType === "numeric" ? `${k.min ?? ""}–${k.max ?? ""}` : k.dataType === "boolean" ? "true/false" : k.categories.join("/")})`).join(", ")}`);
|
|
136
|
+
}
|
|
137
|
+
async function runQueue(args, config) {
|
|
138
|
+
const [verb, ...rest] = args;
|
|
139
|
+
if (verb === "list" || verb === undefined) {
|
|
140
|
+
const res = await call(config, "codiedev_traces_queue_list", "GET", "queues", {});
|
|
141
|
+
const live = res.queues.filter((q) => !q.archived);
|
|
142
|
+
if (!live.length)
|
|
143
|
+
console.log("No review queues yet. Make one in Codiedev → Traces → Review.");
|
|
144
|
+
for (const q of live)
|
|
145
|
+
console.log(`${q.name.padEnd(28)} ${String(q.pending).padStart(4)} to review ${String(q.done).padStart(4)} done ${q.scoreNames.join(", ")}`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (verb === "create")
|
|
149
|
+
return runQueueCreate(rest, config);
|
|
150
|
+
if (verb !== "add")
|
|
151
|
+
usage("codiedev traces queue list | queue create <name> [--scores a,b] | queue add <queue> --agent <name> [--failed] [--days n] [--run id ...]");
|
|
152
|
+
const p = parseArgs(rest);
|
|
153
|
+
const queue = p.positional[0];
|
|
154
|
+
if (!queue || (!p.flags["--agent"] && !p.runs.length))
|
|
155
|
+
usage("codiedev traces queue add <queue> --agent <name> [--failed] [--days n] [--run id ...]");
|
|
156
|
+
const res = await call(config, "codiedev_traces_queue_add", "POST", "queue", {
|
|
157
|
+
body: { queue, agent: p.flags["--agent"], failed: p.bools.has("--failed"), ...(p.flags["--days"] ? { days: Number(p.flags["--days"]) } : {}), ...(p.runs.length ? { runs: p.runs } : {}) },
|
|
158
|
+
});
|
|
159
|
+
console.log(`✓ Added ${res.added} ${res.added === 1 ? "run" : "runs"} to ${res.queue}${res.skipped ? ` (${res.skipped} already there or not yours)` : ""}. Review them in Codiedev → Traces → Review.`);
|
|
160
|
+
}
|
|
161
|
+
function printJudge(agent, judge) {
|
|
162
|
+
if (!judge || judge === "none") {
|
|
163
|
+
console.log(`Automatic scoring isn't set up for ${agent}.`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
console.log(`${agent}: automatic scoring ${judge.enabled ? "on" : "off"}`);
|
|
167
|
+
console.log(` scores ${judge.scoreNames.join(", ")} · ${Math.round(judge.sampleRate * 100)}% of runs, up to ${judge.dailyMaxRuns}/day · ${judge.model}`);
|
|
168
|
+
if (judge.judgeKey)
|
|
169
|
+
console.log(` billed to ${judge.judgeKey.name}${judge.judgeKey.monthlyBudgetUsd !== null ? ` ($${judge.judgeKey.monthlyBudgetUsd}/mo)` : ""} · ${judge.judgedToday} judged in 24h${judge.errorsToday ? `, ${judge.errorsToday} failed` : ""}`);
|
|
170
|
+
if (judge.lastError)
|
|
171
|
+
console.log(` last problem: ${judge.lastError}`);
|
|
172
|
+
}
|
|
173
|
+
async function runJudge(args, config) {
|
|
174
|
+
const p = parseArgs(args);
|
|
175
|
+
const agent = p.positional[0];
|
|
176
|
+
const help = "codiedev traces judge <agent> [--on | --off] [--scores a,b] [--instructions text] [--model id] [--sample percent] [--daily n] [--budget usd | --key cdvm_…]";
|
|
177
|
+
if (!agent)
|
|
178
|
+
usage(help);
|
|
179
|
+
const changing = p.bools.has("--on") || p.bools.has("--off") || Object.keys(p.flags).length > 0;
|
|
180
|
+
if (!changing) {
|
|
181
|
+
const res = await call(config, "codiedev_traces_judge", "GET", "judge", { query: { agent } });
|
|
182
|
+
printJudge(res.agent, res.judge);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const res = await call(config, "codiedev_traces_judge_set", "POST", "judge", {
|
|
186
|
+
body: {
|
|
187
|
+
agent,
|
|
188
|
+
...(p.bools.has("--on") ? { enabled: true } : p.bools.has("--off") ? { enabled: false } : {}),
|
|
189
|
+
...(p.flags["--scores"] ? { scores: p.flags["--scores"].split(",").map((s) => s.trim()).filter(Boolean) } : {}),
|
|
190
|
+
...(p.flags["--instructions"] ? { instructions: p.flags["--instructions"] } : {}),
|
|
191
|
+
...(p.flags["--model"] ? { model: p.flags["--model"] } : {}),
|
|
192
|
+
...(p.flags["--sample"] ? { sampleRate: Number(p.flags["--sample"]) / 100 } : {}),
|
|
193
|
+
...(p.flags["--daily"] ? { dailyMaxRuns: Number(p.flags["--daily"]) } : {}),
|
|
194
|
+
...(p.flags["--budget"] ? { newKeyBudgetUsd: Number(p.flags["--budget"]) } : {}),
|
|
195
|
+
...(p.flags["--key"] ? { pastedKey: p.flags["--key"] } : {}),
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
printJudge(res.agent, res.judge);
|
|
199
|
+
}
|
|
200
|
+
async function runImport(args, config) {
|
|
201
|
+
const p = parseArgs(args);
|
|
202
|
+
const [agent, file] = p.positional;
|
|
203
|
+
const dataset = p.flags["--dataset"];
|
|
204
|
+
if (!agent || !file || !dataset)
|
|
205
|
+
usage("codiedev traces import <agent> <file.csv|file.jsonl> --dataset <name>");
|
|
206
|
+
let text;
|
|
207
|
+
try {
|
|
208
|
+
text = fs.readFileSync(path.resolve(process.cwd(), file), "utf8");
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
console.error(`Couldn't read ${file}: ${err.message}`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
const res = await call(config, "codiedev_traces_import", "POST", "examples", { body: { agent, dataset, text } });
|
|
215
|
+
console.log(`✓ Imported ${res.added} ${res.added === 1 ? "example" : "examples"} into ${dataset} for ${agent}.`);
|
|
216
|
+
for (const e of res.errors.slice(0, 10))
|
|
217
|
+
console.log(` skipped${e.line ? ` line ${e.line}` : ""}: ${e.error}`);
|
|
218
|
+
}
|
|
219
|
+
async function runAddExample(args, config) {
|
|
220
|
+
const p = parseArgs(args);
|
|
221
|
+
const agent = p.positional[0];
|
|
222
|
+
const dataset = p.flags["--dataset"];
|
|
223
|
+
const input = p.flags["--input"];
|
|
224
|
+
if (!agent || !dataset || !input)
|
|
225
|
+
usage("codiedev traces add-example <agent> --dataset <name> --input <text> [--expected <text>] [--name <text>]");
|
|
226
|
+
await call(config, "codiedev_traces_add_example", "POST", "examples", { body: { agent, dataset, input, expected: p.flags["--expected"], name: p.flags["--name"] } });
|
|
227
|
+
console.log(`✓ Added an example to ${dataset} for ${agent}.`);
|
|
228
|
+
}
|
|
229
|
+
async function runVersions(args, config) {
|
|
230
|
+
const dataset = parseArgs(args).positional[0];
|
|
231
|
+
if (!dataset)
|
|
232
|
+
usage("codiedev traces versions <dataset>");
|
|
233
|
+
const res = await call(config, "codiedev_traces_versions", "GET", "versions", { query: { dataset } });
|
|
234
|
+
if (!res.versions.length)
|
|
235
|
+
console.log(`${dataset} has no saved versions. Save one with: codiedev traces save-version "${dataset}"`);
|
|
236
|
+
for (const v of res.versions)
|
|
237
|
+
console.log(`v${v.version} ${String(v.cases).padStart(4)} cases ${new Date(v.createdAt).toISOString().slice(0, 10)} +${v.added} −${v.removed} ${v.changed} edited${v.note ? ` ${v.note}` : ""}`);
|
|
238
|
+
if (res.unsaved)
|
|
239
|
+
console.log(`Unsaved since v${res.versions[0].version}: +${res.unsaved.added} −${res.unsaved.removed} ${res.unsaved.changed} edited`);
|
|
240
|
+
}
|
|
241
|
+
async function runSaveVersion(args, config) {
|
|
242
|
+
const p = parseArgs(args);
|
|
243
|
+
const dataset = p.positional[0];
|
|
244
|
+
if (!dataset)
|
|
245
|
+
usage("codiedev traces save-version <dataset> [--note text]");
|
|
246
|
+
const res = await call(config, "codiedev_traces_save_version", "POST", "versions", { body: { dataset, note: p.flags["--note"] } });
|
|
247
|
+
console.log(`✓ Saved ${dataset} as v${res.version} (${res.cases} cases). Run it later with --dataset "${dataset}" --version ${res.version}.`);
|
|
248
|
+
}
|
|
249
|
+
const usd = (n) => (n === 0 ? "$0" : n < 0.01 ? "<$0.01" : `$${n.toFixed(2)}`);
|
|
250
|
+
const json = (p, value) => { if (p.bools.has("--json")) {
|
|
251
|
+
process.stdout.write(JSON.stringify(value, null, 2) + "\n");
|
|
252
|
+
return true;
|
|
253
|
+
} return false; };
|
|
254
|
+
async function runOverview(args, config) {
|
|
255
|
+
const p = parseArgs(args);
|
|
256
|
+
const res = await call(config, "codiedev_traces_overview", "GET", "overview", { query: { days: p.flags["--days"] ?? "7" } });
|
|
257
|
+
if (json(p, res))
|
|
258
|
+
return;
|
|
259
|
+
if (!res.agents.length) {
|
|
260
|
+
console.log("No agents you can see yet. Connect one in Codiedev → Traces.");
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
console.log(`Agents, last ${res.range}:`);
|
|
264
|
+
for (const a of res.agents)
|
|
265
|
+
console.log(` ${a.name.padEnd(28)} ${String(a.runs).padStart(6)} runs ${String(a.failedRuns).padStart(5)} failed ${usd(a.spend7dUsd).padStart(9)} 7d spend ${a.keepsPromptsDays ? `prompts ${a.keepsPromptsDays}d` : "metadata only"}${a.spike ? " spend spike" : ""}${a.budgetBlock ? " budget block" : ""}`);
|
|
266
|
+
if (res.issues.length) {
|
|
267
|
+
console.log("\nWhat's going wrong:");
|
|
268
|
+
for (const i of res.issues)
|
|
269
|
+
console.log(` ${i.label.padEnd(18)} ${String(i.runs).padStart(5)} runs ${usd(i.wastedUsd).padStart(9)} wasted ${i.agents.join(", ")}${i.exampleRun ? ` e.g. ${i.exampleRun}` : ""}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function runRuns(args, config) {
|
|
273
|
+
const p = parseArgs(args);
|
|
274
|
+
const agent = p.positional[0];
|
|
275
|
+
if (!agent)
|
|
276
|
+
usage("codiedev traces runs <agent> [--failed] [--flag errors|truncated|tool_loop|context_overflow|budget_block] [--model id] [--verdict pass|fail] [--days n] [--limit n] [--json]");
|
|
277
|
+
const res = await call(config, "codiedev_traces_runs", "GET", "runs", {
|
|
278
|
+
query: { agent, days: p.flags["--days"] ?? "7", ...(p.bools.has("--failed") ? { failed: "1" } : {}), ...(p.flags["--flag"] ? { flag: p.flags["--flag"] } : {}), ...(p.flags["--model"] ? { model: p.flags["--model"] } : {}), ...(p.flags["--verdict"] ? { verdict: p.flags["--verdict"] } : {}), limit: p.flags["--limit"] ?? "50" },
|
|
279
|
+
});
|
|
280
|
+
if (json(p, res))
|
|
281
|
+
return;
|
|
282
|
+
console.log(`${res.total} ${res.total === 1 ? "run" : "runs"} for ${res.agent}, last ${res.range}${res.total > res.runs.length ? ` (newest ${res.runs.length})` : ""}:`);
|
|
283
|
+
for (const r of res.runs)
|
|
284
|
+
console.log(` ${r.startedAt.slice(0, 16).replace("T", " ")} ${r.status === "failed" ? "FAIL" : " ok "} ${r.runId.padEnd(24)} ${String(r.steps).padStart(3)} calls ${usd(r.costUsd).padStart(8)} ${r.model ?? ""}${r.flags.length ? ` [${r.flags.join(", ")}]` : ""}${r.verdict ? ` marked ${r.verdict}` : ""}`);
|
|
285
|
+
if (res.runs.length)
|
|
286
|
+
console.log(`\nOpen one: codiedev traces run ${res.runs[0].runId} --agent "${res.agent}"`);
|
|
287
|
+
}
|
|
288
|
+
async function runRun(args, config) {
|
|
289
|
+
const p = parseArgs(args);
|
|
290
|
+
const run = p.positional[0];
|
|
291
|
+
if (!run)
|
|
292
|
+
usage("codiedev traces run <run> [--agent name] [--json]");
|
|
293
|
+
const res = await call(config, "codiedev_traces_run", "GET", "run", { query: { run, ...(p.flags["--agent"] ? { agent: p.flags["--agent"] } : {}) } });
|
|
294
|
+
if (json(p, res))
|
|
295
|
+
return;
|
|
296
|
+
const r = res.run;
|
|
297
|
+
console.log(`${r.title} · ${r.id}`);
|
|
298
|
+
console.log(`${new Date(r.startedAt).toISOString().slice(0, 16).replace("T", " ")} · ${r.status === "failed" ? "FAILED" : "ok"} · ${Math.round(r.durationMs / 100) / 10}s · ${usd(r.costUsd)}${r.flags.length ? ` · ${r.flags.join(", ")}` : ""}`);
|
|
299
|
+
if (r.diagnosis)
|
|
300
|
+
console.log(`\nWhat went wrong: ${r.diagnosis.title}\n ${r.diagnosis.why}\n\nFix (for your coding agent):\n${r.diagnosis.fix.split("\n").map((l) => ` ${l}`).join("\n")}`);
|
|
301
|
+
if (r.annotation)
|
|
302
|
+
console.log(`\nMarked ${r.annotation.verdict} by ${r.annotation.by}${r.annotation.reason ? `: ${r.annotation.reason}` : ""}`);
|
|
303
|
+
if (res.scores.length)
|
|
304
|
+
console.log(`\nScores: ${res.scores.map((s) => `${s.name} ${s.text}${s.step ? ` (step ${s.step})` : ""} by ${s.by ?? s.source}${s.comment ? ` "${s.comment}"` : ""}`).join("; ")}`);
|
|
305
|
+
console.log("\nSteps:");
|
|
306
|
+
for (const s of r.spans.filter((x) => x.kind !== "run")) {
|
|
307
|
+
console.log(` ${s.kind === "tool" ? "tool" : "call"} ${s.name} ${Math.round(s.durationMs)}ms${s.costUsd !== undefined ? ` ${usd(s.costUsd)}` : ""}${s.finishReason ? ` finish: ${s.finishReason}` : ""}${s.statusCode && s.statusCode >= 400 ? ` HTTP ${s.statusCode}` : ""}${s.flag ? ` [${s.flag}]` : ""}${s.note ? ` ${s.note}` : ""}`);
|
|
308
|
+
if (s.input)
|
|
309
|
+
console.log(` prompt: ${s.input.replace(/\s+/g, " ").slice(0, 300)}`);
|
|
310
|
+
if (s.output)
|
|
311
|
+
console.log(` reply: ${s.output.replace(/\s+/g, " ").slice(0, 300)}`);
|
|
312
|
+
}
|
|
313
|
+
if (!r.bodiesVisible)
|
|
314
|
+
console.log("\n(Prompts and replies are shown only to the agent's maintainers.)");
|
|
315
|
+
}
|
|
316
|
+
async function runScoreKinds(args, config) {
|
|
317
|
+
const [verb, ...rest] = args;
|
|
318
|
+
if (verb === "add") {
|
|
319
|
+
const p = parseArgs(rest);
|
|
320
|
+
const name = p.positional[0];
|
|
321
|
+
const type = p.flags["--type"];
|
|
322
|
+
if (!name || !type)
|
|
323
|
+
usage("codiedev traces score-kinds add <name> --type number|categories|boolean [--min n --max n] [--categories a,b,c] [--description text]");
|
|
324
|
+
const dataType = type === "number" || type === "numeric" ? "numeric" : type === "categories" || type === "categorical" ? "categorical" : type === "boolean" || type === "bool" ? "boolean" : type;
|
|
325
|
+
await call(config, "codiedev_traces_score_kind_add", "POST", "score-kinds", {
|
|
326
|
+
body: { name, type: dataType, ...(p.flags["--min"] ? { min: Number(p.flags["--min"]) } : {}), ...(p.flags["--max"] ? { max: Number(p.flags["--max"]) } : {}), ...(p.flags["--categories"] ? { categories: p.flags["--categories"].split(",").map((c) => c.trim()) } : {}), ...(p.flags["--description"] ? { description: p.flags["--description"] } : {}) },
|
|
327
|
+
});
|
|
328
|
+
console.log(`✓ Added score kind ${name}.`);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
const p = parseArgs(verb === undefined || verb === "list" ? rest : args);
|
|
332
|
+
const res = await call(config, "codiedev_traces_score_kinds", "GET", "score-kinds", {});
|
|
333
|
+
if (json(p, res))
|
|
334
|
+
return;
|
|
335
|
+
const live = res.kinds.filter((k) => !k.archived);
|
|
336
|
+
if (!live.length)
|
|
337
|
+
console.log("No score kinds yet. Add one: codiedev traces score-kinds add helpfulness --type number --min 1 --max 5");
|
|
338
|
+
for (const k of live)
|
|
339
|
+
console.log(` ${k.name.padEnd(24)} ${k.dataType === "numeric" ? `number ${k.min ?? ""}–${k.max ?? ""}` : k.dataType === "boolean" ? "true / false" : k.categories.join(" / ")}${k.description ? ` ${k.description}` : ""}`);
|
|
340
|
+
}
|
|
341
|
+
async function runQueueCreate(args, config) {
|
|
342
|
+
const p = parseArgs(args);
|
|
343
|
+
const name = p.positional[0];
|
|
344
|
+
if (!name)
|
|
345
|
+
usage("codiedev traces queue create <name> [--scores a,b] [--description text]");
|
|
346
|
+
await call(config, "codiedev_traces_queue_create", "POST", "queues", { body: { name, scores: (p.flags["--scores"] ?? "").split(",").map((s) => s.trim()).filter(Boolean), ...(p.flags["--description"] ? { description: p.flags["--description"] } : {}) } });
|
|
347
|
+
console.log(`✓ Created review queue ${name}. Add runs: codiedev traces queue add "${name}" --agent <name> --failed`);
|
|
348
|
+
}
|
package/dist/configDir.js
CHANGED
|
@@ -34,16 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.codiedevStateDir = codiedevStateDir;
|
|
37
|
-
// Single source of truth for where the CLI's config/state lives on disk.
|
|
38
|
-
//
|
|
39
|
-
// Defaults to ~/.codiedev. The desktop app sets CODIEDEV_CONFIG_DIR to
|
|
40
|
-
// ~/.codiedev-desktop so a desktop session never touches the user's real
|
|
41
|
-
// prod config — env-based (not a flag) so detached capture-finish/upload
|
|
42
|
-
// children inherit the override automatically.
|
|
43
|
-
//
|
|
44
|
-
// Deliberately dependency-free (only node:path/os) so it can be imported
|
|
45
|
-
// by both utils.ts and modules utils.ts itself imports (e.g. captureLog.ts)
|
|
46
|
-
// without creating a circular import.
|
|
47
37
|
const path = __importStar(require("path"));
|
|
48
38
|
const os = __importStar(require("os"));
|
|
49
39
|
const CONFIG_DIR = process.env.CODIEDEV_CONFIG_DIR?.trim()
|
package/dist/connect.js
CHANGED
|
@@ -39,36 +39,19 @@ const https = __importStar(require("https"));
|
|
|
39
39
|
const http = __importStar(require("http"));
|
|
40
40
|
const crypto = __importStar(require("crypto"));
|
|
41
41
|
const os = __importStar(require("os"));
|
|
42
|
-
const fs = __importStar(require("fs"));
|
|
43
42
|
const path = __importStar(require("path"));
|
|
44
43
|
const utils_1 = require("./utils");
|
|
45
44
|
const connectFlow_1 = require("./connectFlow");
|
|
46
45
|
const version_1 = require("./version");
|
|
47
46
|
const upgradeNudge_1 = require("./upgradeNudge");
|
|
48
47
|
const shared_1 = require("./commands/shared");
|
|
49
|
-
const
|
|
50
|
-
const securityPolicy_1 = require("./securityPolicy");
|
|
51
|
-
const securityFeature_1 = require("./securityFeature");
|
|
52
|
-
// cli.codiedev.com is a Convex custom domain on the prod deployment; the
|
|
53
|
-
// underlying judicious-falcon-861.convex.site URL keeps serving, so configs
|
|
54
|
-
// written by older CLI versions stay valid without a re-connect.
|
|
48
|
+
const harnessDirs_1 = require("./harnessDirs");
|
|
55
49
|
const BACKEND_URL = process.env.CODIEDEV_URL || "https://cli.codiedev.com";
|
|
56
|
-
/**
|
|
57
|
-
* Reads a line from stdin without echoing the typed/pasted characters —
|
|
58
|
-
* for tokens, passwords, anything that shouldn't end up in terminal
|
|
59
|
-
* scrollback or screenshots. Echoes `*` per character so the user gets
|
|
60
|
-
* visual feedback that input is being received.
|
|
61
|
-
*
|
|
62
|
-
* Falls back to the regular `prompt()` if stdin isn't a TTY (e.g., piped
|
|
63
|
-
* input in CI). Without a TTY there's no echo to suppress anyway, and
|
|
64
|
-
* raw mode would error.
|
|
65
|
-
*/
|
|
66
50
|
function promptHidden(question) {
|
|
67
51
|
return new Promise((resolve) => {
|
|
68
52
|
const stdin = process.stdin;
|
|
69
53
|
const stdout = process.stdout;
|
|
70
54
|
if (!stdin.isTTY) {
|
|
71
|
-
// CI / piped input — no terminal to mute. Fall back to readline.
|
|
72
55
|
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
73
56
|
rl.question(question, (answer) => {
|
|
74
57
|
rl.close();
|
|
@@ -85,23 +68,18 @@ function promptHidden(question) {
|
|
|
85
68
|
};
|
|
86
69
|
const onData = (chunk) => {
|
|
87
70
|
const key = chunk.toString("utf8");
|
|
88
|
-
// Iterate so a single `chunk` containing a multi-char paste still
|
|
89
|
-
// masks each character individually.
|
|
90
71
|
for (const ch of key) {
|
|
91
|
-
// Ctrl+C — abort like a normal terminal interrupt.
|
|
92
72
|
if (ch === "") {
|
|
93
73
|
cleanup();
|
|
94
74
|
stdout.write("\n");
|
|
95
75
|
process.exit(130);
|
|
96
76
|
}
|
|
97
|
-
// Enter — finalize.
|
|
98
77
|
if (ch === "\r" || ch === "\n") {
|
|
99
78
|
cleanup();
|
|
100
79
|
stdout.write("\n");
|
|
101
80
|
resolve(buf.trim());
|
|
102
81
|
return;
|
|
103
82
|
}
|
|
104
|
-
// Backspace / DEL — erase one masked char.
|
|
105
83
|
if (ch === "" || ch === "\b") {
|
|
106
84
|
if (buf.length > 0) {
|
|
107
85
|
buf = buf.slice(0, -1);
|
|
@@ -109,7 +87,6 @@ function promptHidden(question) {
|
|
|
109
87
|
}
|
|
110
88
|
continue;
|
|
111
89
|
}
|
|
112
|
-
// Ignore other control bytes (escape sequences from arrow keys, etc.)
|
|
113
90
|
if (ch.charCodeAt(0) < 0x20)
|
|
114
91
|
continue;
|
|
115
92
|
buf += ch;
|
|
@@ -165,11 +142,6 @@ function postJson(url, body, extraHeaders = {}) {
|
|
|
165
142
|
});
|
|
166
143
|
}
|
|
167
144
|
async function runConnect(args = []) {
|
|
168
|
-
// `--force` (or `-f`) re-prompts for a token even if `~/.codiedev/config.json`
|
|
169
|
-
// already has one. Default behavior reuses the saved token so users can
|
|
170
|
-
// re-run `connect` (e.g., after installing Claude Code) without having to
|
|
171
|
-
// mint a fresh token from the portal — which is what bit Sonifi's first
|
|
172
|
-
// engineer when he interpreted "no visible token" as "the old one is gone".
|
|
173
145
|
const force = args.includes("--force") || args.includes("-f");
|
|
174
146
|
console.log("\nWelcome to Codiedev CLI\n");
|
|
175
147
|
await (0, upgradeNudge_1.maybePrintUpgradeNudge)();
|
|
@@ -183,8 +155,6 @@ async function runConnect(args = []) {
|
|
|
183
155
|
console.log(`Reusing API token from ~/.codiedev/config.json (run with --force to use a new one).\n`);
|
|
184
156
|
}
|
|
185
157
|
else {
|
|
186
|
-
// Hidden prompt — masks the token with `*` as it's typed/pasted so it
|
|
187
|
-
// doesn't end up in terminal scrollback or screenshots.
|
|
188
158
|
token = await promptHidden("Enter your Codiedev API token: ");
|
|
189
159
|
if (!token) {
|
|
190
160
|
console.error("Error: API token is required.");
|
|
@@ -202,10 +172,8 @@ async function runConnect(args = []) {
|
|
|
202
172
|
console.error(`\nError: Failed to validate token — ${err.message}`);
|
|
203
173
|
process.exit(1);
|
|
204
174
|
}
|
|
205
|
-
// Extract fields from response
|
|
206
175
|
const companyId = responseData.companyId;
|
|
207
176
|
const companyName = responseData.companyName;
|
|
208
|
-
const agentSecurityEnabled = responseData.agentSecurityEnabled === true;
|
|
209
177
|
const repos = responseData.repos ?? [];
|
|
210
178
|
if (!companyId || !companyName) {
|
|
211
179
|
console.error("\nError: Invalid response from server. Token may be invalid.");
|
|
@@ -218,7 +186,6 @@ async function runConnect(args = []) {
|
|
|
218
186
|
repos,
|
|
219
187
|
lastSynced: new Date().toISOString(),
|
|
220
188
|
backendUrl: BACKEND_URL,
|
|
221
|
-
agentSecurityEnabled,
|
|
222
189
|
deviceId: saved?.deviceId || crypto.randomUUID(),
|
|
223
190
|
deviceName: saved?.deviceName || os.hostname(),
|
|
224
191
|
captureIgnoredPaths: saved?.captureIgnoredPaths ?? [],
|
|
@@ -230,15 +197,7 @@ async function runConnect(args = []) {
|
|
|
230
197
|
console.error(`\nError: Failed to save config — ${err.message}`);
|
|
231
198
|
process.exit(1);
|
|
232
199
|
}
|
|
233
|
-
// Once we have a valid token + config, every subsequent step posts a
|
|
234
|
-
// per-step row to /api/telemetry/install-event so the admin page can show
|
|
235
|
-
// a timeline when a customer says "it connected but it doesn't work."
|
|
236
|
-
// Fire-and-forget — never blocks the connect flow.
|
|
237
200
|
(0, shared_1.recordInstallEvent)(config, { step: "started", ok: true });
|
|
238
|
-
// One-way device status sync. Local config remains authoritative: a network
|
|
239
|
-
// failure here never removes or weakens an ignored path. This also registers
|
|
240
|
-
// a freshly connected device with an empty list so the portal can distinguish
|
|
241
|
-
// "connected, no exclusions" from "old CLI has never reported status".
|
|
242
201
|
try {
|
|
243
202
|
await postJson(`${BACKEND_URL}/api/cli/capture-exclusions`, {
|
|
244
203
|
deviceId: config.deviceId,
|
|
@@ -249,17 +208,6 @@ async function runConnect(args = []) {
|
|
|
249
208
|
catch (err) {
|
|
250
209
|
console.warn(`Warning: Local capture settings are active, but portal status did not sync — ${err.message}`);
|
|
251
210
|
}
|
|
252
|
-
// Migration: strip MCP server entries written by pre-CLI-only versions
|
|
253
|
-
// of `codiedev connect`. These pointed at `npx codiedev-mcp`, a binary
|
|
254
|
-
// that was removed in 0.3.4 and that 0.7.11+ no longer ships. Without
|
|
255
|
-
// cleanup, customers upgrading from any prior version see persistent
|
|
256
|
-
// "MCP server failed to start" errors in their agent UIs even though
|
|
257
|
-
// the CLI works fine. Each helper is idempotent and a no-op when the
|
|
258
|
-
// relevant config file doesn't exist.
|
|
259
|
-
//
|
|
260
|
-
// Each call is wrapped because the user's upgrade path matters more
|
|
261
|
-
// than the cleanup. A locked / wrong-owner config file (rare but real)
|
|
262
|
-
// shouldn't block the install loop or strand them on an old version.
|
|
263
211
|
for (const [label, fn] of [
|
|
264
212
|
["Claude Code", utils_1.cleanupClaudeCodeMcp],
|
|
265
213
|
["Codex", utils_1.cleanupCodexMcp],
|
|
@@ -278,29 +226,16 @@ async function runConnect(args = []) {
|
|
|
278
226
|
const hasCodex = (0, utils_1.codexInstalled)();
|
|
279
227
|
const hasCursor = (0, utils_1.cursorInstalled)();
|
|
280
228
|
const hasOpenCode = (0, utils_1.openCodeInstalled)();
|
|
229
|
+
const hasCopilot = (0, utils_1.copilotInstalled)();
|
|
230
|
+
const hasPi = (0, utils_1.piInstalled)();
|
|
281
231
|
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "claude-code", ok: hasClaude });
|
|
282
232
|
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "codex", ok: hasCodex });
|
|
283
233
|
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "cursor", ok: hasCursor });
|
|
284
234
|
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "opencode", ok: hasOpenCode });
|
|
235
|
+
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "copilot", ok: hasCopilot });
|
|
236
|
+
(0, shared_1.recordInstallEvent)(config, { step: "detect", target: "pi", ok: hasPi });
|
|
285
237
|
const installed = [];
|
|
286
|
-
// Machine-readable target keys reported back to the backend via
|
|
287
|
-
// /api/cli/markInstalled so the portal's "Connected" state reflects
|
|
288
|
-
// what's actually wired up on this machine, not just "token validated."
|
|
289
238
|
const installedTargets = [];
|
|
290
|
-
const home = os.homedir();
|
|
291
|
-
const securityConfigPaths = [
|
|
292
|
-
path.join(home, ".claude", "settings.json"),
|
|
293
|
-
path.join(home, ".codex", "hooks.json"),
|
|
294
|
-
path.join(home, ".cursor", "hooks.json"),
|
|
295
|
-
path.join(home, ".config", "opencode", "plugins", "codiedev.js"),
|
|
296
|
-
path.join(home, ".codex", "config.toml"),
|
|
297
|
-
];
|
|
298
|
-
// Snapshot before any hook update. Rollback is intentionally not automatic:
|
|
299
|
-
// an administrator can inspect these 0600 copies before restoring them.
|
|
300
|
-
const securitySnapshot = (0, securityInstall_1.createSecurityInstallSnapshot)(securityConfigPaths);
|
|
301
|
-
// Wrap each per-target write so we emit one install_target row each. The
|
|
302
|
-
// existing user-visible behavior (console.warn on failure, continue) is
|
|
303
|
-
// unchanged — telemetry just observes the outcome.
|
|
304
239
|
const runInstall = (target, fn, label, targetKey) => {
|
|
305
240
|
try {
|
|
306
241
|
fn();
|
|
@@ -320,56 +255,26 @@ async function runConnect(args = []) {
|
|
|
320
255
|
}
|
|
321
256
|
};
|
|
322
257
|
if (hasClaude) {
|
|
323
|
-
runInstall("claude-code-hook",
|
|
324
|
-
runInstall("claude-code-instructions", utils_1.installClaudeCodeInstructions,
|
|
258
|
+
runInstall("claude-code-hook", utils_1.installHook, `Claude Code SessionEnd (capture) + UserPromptSubmit (skill discovery) + Stop (auto-backup) hooks (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.claudeConfigDir)(), "settings.json"))})`, "claudeCode-hook");
|
|
259
|
+
runInstall("claude-code-instructions", utils_1.installClaudeCodeInstructions, `Claude Code agent instructions (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.claudeConfigDir)(), "CLAUDE.md"))})`, "claudeCode-instructions");
|
|
325
260
|
}
|
|
326
261
|
if (hasCodex) {
|
|
327
|
-
runInstall("codex-hook",
|
|
328
|
-
runInstall("codex-instructions", utils_1.installCodexInstructions,
|
|
262
|
+
runInstall("codex-hook", utils_1.installCodexHook, `Codex Stop (capture + auto-backup) hooks (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.codexHome)(), "hooks.json"))})`, "codex-hook");
|
|
263
|
+
runInstall("codex-instructions", utils_1.installCodexInstructions, `Codex agent instructions (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.codexHome)(), "AGENTS.md"))})`, "codex-instructions");
|
|
329
264
|
}
|
|
330
265
|
if (hasCursor) {
|
|
331
|
-
runInstall("cursor-hook",
|
|
266
|
+
runInstall("cursor-hook", utils_1.installCursorHook, "Cursor sessionStart + stop backup + sessionEnd capture hooks (~/.cursor/hooks.json)", "cursor-hook");
|
|
332
267
|
runInstall("cursor-instructions", utils_1.installCursorInstructions, "Cursor agent instructions (~/.cursor/rules/codiedev.mdc)", "cursor-instructions");
|
|
333
268
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
runInstall("opencode-capture-adapter", () => (0, utils_1.installOpenCodeCapturePlugin)(agentSecurityEnabled), "OpenCode session capture adapter (~/.config/opencode/plugins/codiedev.js)", "opencode-capture");
|
|
338
|
-
// Record the exact installed hook bytes and the pre-update rollback files.
|
|
339
|
-
// This supplies health/integrity checks without requiring a package publish
|
|
340
|
-
// or trusting whichever `node` happens to be first on PATH later.
|
|
341
|
-
try {
|
|
342
|
-
const hookScriptPath = path.join(__dirname, "hook.js");
|
|
343
|
-
if (agentSecurityEnabled && fs.existsSync(hookScriptPath)) {
|
|
344
|
-
const targets = [];
|
|
345
|
-
if (installedTargets.includes("claudeCode-hook"))
|
|
346
|
-
targets.push({ surface: "claude-code", configPath: securityConfigPaths[0] });
|
|
347
|
-
if (installedTargets.includes("codex-hook"))
|
|
348
|
-
targets.push({ surface: "codex", configPath: securityConfigPaths[1] });
|
|
349
|
-
if (installedTargets.includes("cursor-hook"))
|
|
350
|
-
targets.push({ surface: "cursor", configPath: securityConfigPaths[2] });
|
|
351
|
-
if (installedTargets.includes("opencode-capture"))
|
|
352
|
-
targets.push({ surface: "codie-harness", configPath: securityConfigPaths[3] });
|
|
353
|
-
(0, securityInstall_1.writeSecurityInstallManifest)({ hookScriptPath, snapshot: securitySnapshot, targets });
|
|
354
|
-
}
|
|
269
|
+
if (hasCopilot) {
|
|
270
|
+
runInstall("copilot-hook", utils_1.installCopilotHook, `GitHub Copilot (VS Code + CLI) sessionStart + agentStop backup + sessionEnd capture hooks (${(0, utils_1.copilotHooksPath)()})`, "copilot-hook");
|
|
271
|
+
runInstall("copilot-instructions", utils_1.installCopilotInstructions, "GitHub Copilot CLI team artifact instructions", "copilot-instructions");
|
|
355
272
|
}
|
|
356
|
-
|
|
357
|
-
|
|
273
|
+
runInstall("pi-extension", utils_1.installPiExtension, `pi session start + skill discovery + capture extension (${(0, harnessDirs_1.displayPath)((0, utils_1.piExtensionPath)())})`, "pi-extension");
|
|
274
|
+
if (hasPi) {
|
|
275
|
+
runInstall("pi-instructions", utils_1.installPiInstructions, `pi agent instructions (${(0, harnessDirs_1.displayPath)((0, utils_1.piInstructionsPath)())})`, "pi-instructions");
|
|
358
276
|
}
|
|
359
|
-
|
|
360
|
-
// an endpoint decision never depends on live network latency.
|
|
361
|
-
if (agentSecurityEnabled) {
|
|
362
|
-
try {
|
|
363
|
-
await (0, securityPolicy_1.syncEndpointSecurityPolicy)(config);
|
|
364
|
-
}
|
|
365
|
-
catch (err) {
|
|
366
|
-
console.warn(`Warning: Agent-security policy will use safe defaults until sync succeeds — ${err.message}`);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
// Tell the backend which targets we wired up so the portal's onboarding
|
|
370
|
-
// card flips to "Connected" only when something actually installed —
|
|
371
|
-
// not on bare token validation. Best-effort: a network failure here
|
|
372
|
-
// doesn't undo the local install, and `codiedev doctor` still works.
|
|
277
|
+
runInstall("opencode-capture-adapter", utils_1.installOpenCodeCapturePlugin, `OpenCode session capture adapter (${(0, harnessDirs_1.displayPath)(path.join((0, harnessDirs_1.openCodeConfigDir)(), "plugins", "codiedev.js"))})`, "opencode-capture");
|
|
373
278
|
if (installedTargets.length > 0) {
|
|
374
279
|
try {
|
|
375
280
|
await postJson(`${BACKEND_URL}/api/cli/markInstalled`, {
|
|
@@ -388,7 +293,7 @@ async function runConnect(args = []) {
|
|
|
388
293
|
});
|
|
389
294
|
}
|
|
390
295
|
}
|
|
391
|
-
if (!hasClaude && !hasCodex && !hasCursor && !hasOpenCode) {
|
|
296
|
+
if (!hasClaude && !hasCodex && !hasCursor && !hasOpenCode && !hasCopilot && !hasPi) {
|
|
392
297
|
console.warn("\nNo existing AI client detected; the Codie/OpenCode adapter is ready for a later install.");
|
|
393
298
|
console.warn("If you just installed Claude Code, launch it once (so ~/.claude is created),");
|
|
394
299
|
console.warn("then re-run `npx codiedev connect` to wire up the capture hook.");
|
|
@@ -404,8 +309,6 @@ async function runConnect(args = []) {
|
|
|
404
309
|
}
|
|
405
310
|
console.log();
|
|
406
311
|
console.log("Run `codiedev doctor` to verify everything's wired up.");
|
|
407
|
-
|
|
408
|
-
console.log("Run `codiedev security pilot` to validate blocking safely.");
|
|
409
|
-
}
|
|
312
|
+
console.log("If `codiedev` is not on PATH, run `npx codiedev@latest doctor` instead.");
|
|
410
313
|
console.log();
|
|
411
314
|
}
|
package/dist/connectFlow.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Pure helper for `npx codiedev connect` — decides where the API token
|
|
3
|
-
// comes from. Splitting this out lets us TDD the policy (re-use vs. re-prompt)
|
|
4
|
-
// without touching readline or fs at all.
|
|
5
|
-
//
|
|
6
|
-
// Motivation: Jackson hit a confusing flow where he had a working token in
|
|
7
|
-
// `~/.codiedev/config.json`, re-ran `connect` (to pick up Claude Code that
|
|
8
|
-
// he'd just installed), and was forced to paste a token again. Since the
|
|
9
|
-
// portal only displays the plaintext on creation, his only option was to
|
|
10
|
-
// generate a new one — leaving him thinking the old one had been lost.
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.resolveConnectToken = resolveConnectToken;
|
|
13
4
|
function resolveConnectToken(input) {
|