codiedev 0.10.0-beta.5 → 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 +4 -4
- package/dist/captureSignals.js +2 -0
- package/dist/cli.js +38 -50
- package/dist/codexHookTrust.js +67 -4
- package/dist/codie.js +23 -74
- package/dist/codieLauncher.js +18 -22
- 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/doctor.js +12 -38
- package/dist/commands/evals.js +187 -0
- package/dist/commands/pack.js +1 -1
- package/dist/commands/traces.js +79 -15
- package/dist/commands/tracesLabel.js +348 -0
- package/dist/connect.js +11 -52
- package/dist/copilotHooks.js +0 -4
- package/dist/cursorHooks.js +0 -15
- package/dist/harnessDirs.js +4 -0
- package/dist/hook.js +33 -197
- package/dist/limitEventReporter.js +1 -1
- package/dist/managedPi.js +240 -0
- package/dist/mcp.js +0 -307
- package/dist/packs/harnesses.js +40 -3
- package/dist/packs/install.js +2 -1
- package/dist/piHooks.js +216 -0
- package/dist/piRuntime.js +120 -0
- package/dist/selfUpdate.js +47 -2
- package/dist/utils.js +232 -115
- package/package.json +5 -7
- package/dist/codieStartup.js +0 -27
- package/dist/commands/promote.js +0 -53
- package/dist/commands/react.js +0 -38
- package/dist/commands/reverseTicket.js +0 -444
- package/dist/commands/security.js +0 -156
- package/dist/prUrl.js +0 -28
- package/dist/security.js +0 -417
- package/dist/securityDeepScan.js +0 -235
- package/dist/securityDoctor.js +0 -61
- package/dist/securityFeature.js +0 -6
- package/dist/securityInstall.js +0 -232
- package/dist/securityInventory.js +0 -566
- package/dist/securityPilot.js +0 -59
- package/dist/securityPolicy.js +0 -181
- package/dist/securitySession.js +0 -72
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ The CLI will prompt you for an API token (get one at https://codiedev.com/portal
|
|
|
18
18
|
|
|
19
19
|
- **Claude Code** — `SessionEnd` hook in `~/.claude/settings.json`
|
|
20
20
|
- **Codex** — `Stop` hook in `~/.codex/hooks.json`
|
|
21
|
-
- **Cursor** — native session,
|
|
21
|
+
- **Cursor** — native session, subagent/tool observation, backup, and capture hooks in `~/.cursor/hooks.json`
|
|
22
22
|
- **OpenCode / Codie** — plugin in `~/.config/opencode/plugins/codiedev.js`
|
|
23
23
|
|
|
24
24
|
Installed clients are wired automatically. The OpenCode adapter is staged even
|
|
@@ -57,9 +57,9 @@ Codex doesn't currently expose a `SessionEnd` event, so the hook runs on `Stop`
|
|
|
57
57
|
|
|
58
58
|
## Cursor note
|
|
59
59
|
|
|
60
|
-
Cursor uses its native hook events for session start/end,
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
Cursor uses its native hook events for session start/end, tool and subagent
|
|
61
|
+
observation, and stop-time backup. Cursor's `beforeSubmitPrompt` cannot inject
|
|
62
|
+
dynamic context today, so task-specific discovery is not claimed.
|
|
63
63
|
Cursor sessions keep their source
|
|
64
64
|
label and real transcript statistics through the shared capture pipeline.
|
|
65
65
|
|
package/dist/captureSignals.js
CHANGED
|
@@ -102,6 +102,8 @@ function parseCaptureSignals(content, source) {
|
|
|
102
102
|
}
|
|
103
103
|
if (e.type === "copilot.skill_invoked")
|
|
104
104
|
addSkill(invocations, e.skill);
|
|
105
|
+
if (e.type === "pi.skill_invoked")
|
|
106
|
+
addSkill(invocations, e.skill);
|
|
105
107
|
if (e.type === "copilot.usage_summary") {
|
|
106
108
|
if (typeof e.premiumRequests === "number" && e.premiumRequests >= 0)
|
|
107
109
|
premiumRequests = e.premiumRequests;
|
package/dist/cli.js
CHANGED
|
@@ -9,19 +9,17 @@ const ask_1 = require("./commands/ask");
|
|
|
9
9
|
const ping_1 = require("./commands/ping");
|
|
10
10
|
const inbox_1 = require("./commands/inbox");
|
|
11
11
|
const note_1 = require("./commands/note");
|
|
12
|
-
const promote_1 = require("./commands/promote");
|
|
13
|
-
const reverseTicket_1 = require("./commands/reverseTicket");
|
|
14
12
|
const createTicket_1 = require("./commands/createTicket");
|
|
15
13
|
const doctor_1 = require("./commands/doctor");
|
|
16
14
|
const search_1 = require("./commands/search");
|
|
17
15
|
const library_1 = require("./commands/library");
|
|
18
16
|
const share_1 = require("./commands/share");
|
|
19
17
|
const send_1 = require("./commands/send");
|
|
20
|
-
const react_1 = require("./commands/react");
|
|
21
18
|
const capture_1 = require("./commands/capture");
|
|
22
|
-
const security_1 = require("./commands/security");
|
|
23
19
|
const pack_1 = require("./commands/pack");
|
|
24
20
|
const traces_1 = require("./commands/traces");
|
|
21
|
+
const agents_1 = require("./commands/agents");
|
|
22
|
+
const evals_1 = require("./commands/evals");
|
|
25
23
|
const hookGate_1 = require("./packs/hookGate");
|
|
26
24
|
const sync_1 = require("./packs/sync");
|
|
27
25
|
const version_1 = require("./version");
|
|
@@ -34,14 +32,8 @@ Codiedev CLI
|
|
|
34
32
|
|
|
35
33
|
Connect:
|
|
36
34
|
codiedev connect Link Claude Code / Codex / Cursor /
|
|
37
|
-
GitHub Copilot to your org
|
|
38
|
-
codiedev doctor Verify setup
|
|
39
|
-
codiedev security pilot Run safe synthetic policy checks
|
|
40
|
-
codiedev security inventory Inventory MCPs, skills, hooks, plugins,
|
|
41
|
-
instructions, and editor extensions
|
|
42
|
-
codiedev security scan --deep Run installed open-source scanners too
|
|
43
|
-
codiedev security sync Fetch administrator policy locally
|
|
44
|
-
codiedev security rollback --yes Restore pre-update hook configuration
|
|
35
|
+
GitHub Copilot / pi to your org
|
|
36
|
+
codiedev doctor Verify setup and capture
|
|
45
37
|
|
|
46
38
|
Harness:
|
|
47
39
|
codie Launch the governed Codie harness.
|
|
@@ -61,14 +53,6 @@ Artifacts:
|
|
|
61
53
|
team's collective memory. Returns an
|
|
62
54
|
LLM-synthesized answer with citations
|
|
63
55
|
pointing at sessions + artifacts.
|
|
64
|
-
codiedev promote <artifact-id> Promote an auto-extracted artifact
|
|
65
|
-
to an authored one
|
|
66
|
-
codiedev reverse-ticket [<pr-url>] Generate a Jira ticket draft.
|
|
67
|
-
No URL = branch mode (uses your current
|
|
68
|
-
local git branch, no PR needed).
|
|
69
|
-
Draft lands in /portal/agentic-ticketing.
|
|
70
|
-
codiedev reverse-ticket --base <ref> Override the base ref in branch mode
|
|
71
|
-
(defaults to origin/main).
|
|
72
56
|
codiedev create-ticket [<prompt>] Forward-write a scoped ticket plan.
|
|
73
57
|
Claude investigates the codebase, asks
|
|
74
58
|
"single repo or multiple? where?", then
|
|
@@ -89,19 +73,27 @@ Messaging:
|
|
|
89
73
|
|
|
90
74
|
Starter packs:
|
|
91
75
|
codiedev pack list Packs assigned to your team
|
|
92
|
-
codiedev pack install [slug] [--harness claude,codex,copilot,cursor,codie]
|
|
76
|
+
codiedev pack install [slug] [--harness claude,codex,copilot,cursor,codie,pi]
|
|
93
77
|
[--dry-run] [--json]
|
|
94
78
|
Install a pack (or all) into every
|
|
95
79
|
detected tool
|
|
96
80
|
codiedev pack status Installed packs, up to date or not
|
|
97
81
|
|
|
98
82
|
Traces (agents on the gateway):
|
|
83
|
+
codiedev agents init | deploy | run | runs | show | secrets | webhook
|
|
84
|
+
Deploy agents and run them in fresh sandboxes
|
|
85
|
+
(codiedev agents help)
|
|
99
86
|
codiedev traces agents Agents you maintain, with saved test cases
|
|
100
|
-
codiedev traces cases <agent> [--
|
|
101
|
-
Pull an agent's test cases (or one
|
|
87
|
+
codiedev traces cases <agent> [--dataset name [--version n]] [--model id]
|
|
88
|
+
Pull an agent's test cases (or one dataset)
|
|
102
89
|
into this repo for your coding agent to
|
|
103
90
|
run, optionally on another model
|
|
104
91
|
codiedev traces report <results.json> Send the results back to Traces
|
|
92
|
+
codiedev traces overview | runs | run | score | scores | score-kinds | queue | judge | import | add-example | versions | save-version
|
|
93
|
+
Agents, runs, failures, scores, review queues,
|
|
94
|
+
automatic scoring and datasets (codiedev traces help)
|
|
95
|
+
codiedev evals report <run.json> File one variant's eval scores under an experiment
|
|
96
|
+
codiedev evals last <subject> Latest experiment on a subject + its champion
|
|
105
97
|
|
|
106
98
|
Discovery:
|
|
107
99
|
codiedev search "<query>" Semantic search across the team's
|
|
@@ -110,9 +102,6 @@ Discovery:
|
|
|
110
102
|
[--type T] [--tag X] [--limit N]
|
|
111
103
|
List artifacts in your workspace
|
|
112
104
|
|
|
113
|
-
Feed:
|
|
114
|
-
codiedev react <postId> <emoji> Toggle a reaction on a feed post
|
|
115
|
-
|
|
116
105
|
Privacy:
|
|
117
106
|
codiedev ignore <path> Never capture this folder or its children
|
|
118
107
|
codiedev unignore <path> Stop ignoring a folder
|
|
@@ -168,6 +157,8 @@ status sync never weakens it.
|
|
|
168
157
|
const COMMAND_HELP = {
|
|
169
158
|
pack: pack_1.PACK_HELP,
|
|
170
159
|
traces: traces_1.TRACES_HELP,
|
|
160
|
+
agents: agents_1.AGENTS_HELP,
|
|
161
|
+
evals: evals_1.EVALS_HELP,
|
|
171
162
|
connect: `
|
|
172
163
|
codiedev connect — link your agent CLI to Codiedev
|
|
173
164
|
|
|
@@ -177,9 +168,11 @@ codiedev connect — link your agent CLI to Codiedev
|
|
|
177
168
|
- ~/.claude/CLAUDE.md instructions (teaches Claude the commands)
|
|
178
169
|
- ~/.codex/hooks.json hook (same, for Codex)
|
|
179
170
|
- ~/.codex/AGENTS.md instructions (same, for Codex)
|
|
180
|
-
- ~/.cursor/hooks.json hooks (session,
|
|
171
|
+
- ~/.cursor/hooks.json hooks (session, backup, capture)
|
|
181
172
|
- ~/.cursor/rules/codiedev.mdc (teaches Cursor the commands)
|
|
182
173
|
- ~/.copilot/hooks/codiedev.json (GitHub Copilot: VS Code + CLI capture)
|
|
174
|
+
- ~/.pi/agent/extensions/codiedev.ts (pi: session, prompt, capture)
|
|
175
|
+
- ~/.pi/agent/AGENTS.md (teaches pi the commands)
|
|
183
176
|
|
|
184
177
|
Re-run anytime to swap accounts or refresh the instruction block.
|
|
185
178
|
|
|
@@ -285,20 +278,6 @@ codiedev note — capture a passing thought, linked to your session
|
|
|
285
278
|
unignore: IGNORE_HELP,
|
|
286
279
|
ignored: IGNORE_HELP,
|
|
287
280
|
capture: IGNORE_HELP,
|
|
288
|
-
promote: `
|
|
289
|
-
codiedev promote — promote an auto-extracted artifact to authored
|
|
290
|
-
|
|
291
|
-
Usage:
|
|
292
|
-
codiedev promote <artifact-id> [--key filename.md]
|
|
293
|
-
|
|
294
|
-
The session-capture pipeline auto-extracts spec/bugfix/decision
|
|
295
|
-
artifacts from each agent session. Promote turns one of those into
|
|
296
|
-
a first-class authored artifact your team can ping, pull, and
|
|
297
|
-
update versions of.
|
|
298
|
-
|
|
299
|
-
Find artifact-ids in the portal under Knowledge → Memory, or via
|
|
300
|
-
the portal search.
|
|
301
|
-
`.trim(),
|
|
302
281
|
"create-ticket": `
|
|
303
282
|
codiedev create-ticket — forward-write a scoped ticket plan
|
|
304
283
|
|
|
@@ -424,6 +403,16 @@ Run 'codiedev help <command>' for each, or see the quick list:
|
|
|
424
403
|
|
|
425
404
|
Tokens are per-user. Rotate any time by revoking + creating a new one.
|
|
426
405
|
`.trim();
|
|
406
|
+
const REMOVED_COMMANDS = {
|
|
407
|
+
promote: "Share an auto-saved spec with 'Promote to team' in the portal's My artifacts list.",
|
|
408
|
+
"reverse-ticket": "Use 'codiedev create-ticket' to draft Jira tickets.",
|
|
409
|
+
reverseTicket: "Use 'codiedev create-ticket' to draft Jira tickets.",
|
|
410
|
+
react: "React to feed posts in the portal.",
|
|
411
|
+
};
|
|
412
|
+
function removedCommand(command) {
|
|
413
|
+
console.error(`'codiedev ${command}' has been removed. ${REMOVED_COMMANDS[command] ?? ""}`.trim());
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
427
416
|
async function main() {
|
|
428
417
|
const [, , command, ...rest] = process.argv;
|
|
429
418
|
if (command === "hook-gate") {
|
|
@@ -476,9 +465,6 @@ async function main() {
|
|
|
476
465
|
case "verify":
|
|
477
466
|
await (0, doctor_1.runDoctor)(rest);
|
|
478
467
|
return;
|
|
479
|
-
case "security":
|
|
480
|
-
await (0, security_1.runSecurityCommand)(rest);
|
|
481
|
-
return;
|
|
482
468
|
case "push":
|
|
483
469
|
await (0, push_1.runPush)(rest);
|
|
484
470
|
return;
|
|
@@ -511,11 +497,10 @@ async function main() {
|
|
|
511
497
|
await (0, note_1.runNote)(rest);
|
|
512
498
|
return;
|
|
513
499
|
case "promote":
|
|
514
|
-
await (0, promote_1.runPromote)(rest);
|
|
515
|
-
return;
|
|
516
500
|
case "reverse-ticket":
|
|
517
501
|
case "reverseTicket":
|
|
518
|
-
|
|
502
|
+
case "react":
|
|
503
|
+
removedCommand(command);
|
|
519
504
|
return;
|
|
520
505
|
case "create-ticket":
|
|
521
506
|
case "createTicket":
|
|
@@ -531,15 +516,18 @@ async function main() {
|
|
|
531
516
|
case "traces":
|
|
532
517
|
await (0, traces_1.runTraces)(rest);
|
|
533
518
|
return;
|
|
519
|
+
case "agents":
|
|
520
|
+
await (0, agents_1.runAgents)(rest);
|
|
521
|
+
return;
|
|
522
|
+
case "evals":
|
|
523
|
+
await (0, evals_1.runEvals)(rest);
|
|
524
|
+
return;
|
|
534
525
|
case "share":
|
|
535
526
|
await (0, share_1.runShare)(rest);
|
|
536
527
|
return;
|
|
537
528
|
case "send":
|
|
538
529
|
await (0, send_1.runSend)(rest);
|
|
539
530
|
return;
|
|
540
|
-
case "react":
|
|
541
|
-
await (0, react_1.runReact)(rest);
|
|
542
|
-
return;
|
|
543
531
|
case "ignore":
|
|
544
532
|
case "unignore":
|
|
545
533
|
case "ignored":
|
package/dist/codexHookTrust.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.codexPluginContentHash = codexPluginContentHash;
|
|
36
37
|
exports.codexCommandHookHash = codexCommandHookHash;
|
|
37
38
|
exports.codiedevCodexHookTrustEntries = codiedevCodexHookTrustEntries;
|
|
38
39
|
exports.writeCodexHookTrust = writeCodexHookTrust;
|
|
@@ -69,6 +70,42 @@ const MATCHER_EVENTS = new Set([
|
|
|
69
70
|
"SubagentStart",
|
|
70
71
|
"SubagentStop",
|
|
71
72
|
]);
|
|
73
|
+
function codexPluginContentHash(root) {
|
|
74
|
+
const hash = crypto.createHash("sha256");
|
|
75
|
+
hash.update("codex-plugin-bundle-v1");
|
|
76
|
+
const u64 = (n) => {
|
|
77
|
+
const b = Buffer.alloc(8);
|
|
78
|
+
b.writeBigUInt64LE(BigInt(n));
|
|
79
|
+
return b;
|
|
80
|
+
};
|
|
81
|
+
const pending = [root];
|
|
82
|
+
while (pending.length) {
|
|
83
|
+
const current = pending.pop();
|
|
84
|
+
const relative = path.relative(root, current).split(path.sep).join("/");
|
|
85
|
+
const name = path.posix.basename(relative);
|
|
86
|
+
if (name === "__pycache__" || name === ".venv" || name.endsWith(".pyc") || name.endsWith(".egg-info"))
|
|
87
|
+
continue;
|
|
88
|
+
const nameBytes = Buffer.from(relative, "utf8");
|
|
89
|
+
hash.update(u64(nameBytes.length));
|
|
90
|
+
hash.update(nameBytes);
|
|
91
|
+
const stat = fs.lstatSync(current);
|
|
92
|
+
if (stat.isDirectory()) {
|
|
93
|
+
hash.update("directory");
|
|
94
|
+
const entries = fs.readdirSync(current).sort((a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)));
|
|
95
|
+
for (const entry of entries.reverse())
|
|
96
|
+
pending.push(path.join(current, entry));
|
|
97
|
+
}
|
|
98
|
+
else if (stat.isFile()) {
|
|
99
|
+
hash.update("file");
|
|
100
|
+
hash.update(u64(stat.size));
|
|
101
|
+
hash.update(fs.readFileSync(current));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
throw new Error(`unsupported plugin entry type: ${current}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return `sha256:${hash.digest("hex")}`;
|
|
108
|
+
}
|
|
72
109
|
function canonicalize(value) {
|
|
73
110
|
if (Array.isArray(value))
|
|
74
111
|
return value.map(canonicalize);
|
|
@@ -155,6 +192,27 @@ function codiedevCodexHookTrustEntries(hooksPath, hooksFile) {
|
|
|
155
192
|
}
|
|
156
193
|
return entries;
|
|
157
194
|
}
|
|
195
|
+
function stripBlockKeepingForeign(text, begin, end) {
|
|
196
|
+
const foreign = [];
|
|
197
|
+
const stripped = text.replace(new RegExp(`\\n?${begin}\\n([\\s\\S]*?)${end}\\n?`, "g"), (_match, body) => {
|
|
198
|
+
let table = null;
|
|
199
|
+
const flush = () => {
|
|
200
|
+
if (table && table.join("").trim())
|
|
201
|
+
foreign.push(table.join("\n").trimEnd());
|
|
202
|
+
};
|
|
203
|
+
for (const line of body.split("\n")) {
|
|
204
|
+
if (/^\s*\[/.test(line)) {
|
|
205
|
+
flush();
|
|
206
|
+
table = /^\s*\[hooks\.state\./.test(line) ? null : [];
|
|
207
|
+
}
|
|
208
|
+
if (table)
|
|
209
|
+
table.push(line);
|
|
210
|
+
}
|
|
211
|
+
flush();
|
|
212
|
+
return "\n";
|
|
213
|
+
});
|
|
214
|
+
return foreign.length ? `${stripped.trimEnd()}\n\n${foreign.join("\n\n")}\n` : stripped;
|
|
215
|
+
}
|
|
158
216
|
function tableHeader(key) {
|
|
159
217
|
return `[hooks.state.${JSON.stringify(key)}]`;
|
|
160
218
|
}
|
|
@@ -176,7 +234,7 @@ function removeTable(lines, header) {
|
|
|
176
234
|
function writeCodexHookTrust(configPath, hooksPath, hooksFile) {
|
|
177
235
|
const entries = codiedevCodexHookTrustEntries(hooksPath, hooksFile);
|
|
178
236
|
let existing = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf8") : "";
|
|
179
|
-
existing = existing
|
|
237
|
+
existing = stripBlockKeepingForeign(existing, TRUST_BEGIN, TRUST_END);
|
|
180
238
|
let lines = existing.split("\n");
|
|
181
239
|
for (const entry of entries)
|
|
182
240
|
lines = removeTable(lines, tableHeader(entry.key));
|
|
@@ -225,11 +283,14 @@ function inspectCodexHookTrust(configPath, hooksPath, hooksFile, requiredSubcomm
|
|
|
225
283
|
}
|
|
226
284
|
const PACK_TRUST_BEGIN = "# codiedev-pack-trust:begin";
|
|
227
285
|
const PACK_TRUST_END = "# codiedev-pack-trust:end";
|
|
228
|
-
function packCodexHookTrustEntries(hooksPath, hooksFile) {
|
|
286
|
+
function packCodexHookTrustEntries(hooksPath, hooksFile, plugin) {
|
|
229
287
|
const events = hooksFile?.hooks;
|
|
230
288
|
if (!events || typeof events !== "object")
|
|
231
289
|
return [];
|
|
232
|
-
const source =
|
|
290
|
+
const source = plugin
|
|
291
|
+
? `${plugin.id}:${path.relative(plugin.root, hooksPath).split(path.sep).join("/")}`
|
|
292
|
+
: normalizedHooksPath(hooksPath);
|
|
293
|
+
const contentHash = plugin ? codexPluginContentHash(plugin.root) : undefined;
|
|
233
294
|
const entries = [];
|
|
234
295
|
for (const [eventName, groupsValue] of Object.entries(events)) {
|
|
235
296
|
const eventLabel = EVENT_LABELS[eventName];
|
|
@@ -248,6 +309,7 @@ function packCodexHookTrustEntries(hooksPath, hooksFile) {
|
|
|
248
309
|
eventName,
|
|
249
310
|
command: handler.command,
|
|
250
311
|
currentHash: codexCommandHookHash(eventName, group, handler),
|
|
312
|
+
...(contentHash ? { contentHash } : {}),
|
|
251
313
|
});
|
|
252
314
|
});
|
|
253
315
|
});
|
|
@@ -256,7 +318,7 @@ function packCodexHookTrustEntries(hooksPath, hooksFile) {
|
|
|
256
318
|
}
|
|
257
319
|
function writeCodexPackHookTrust(configPath, entries) {
|
|
258
320
|
let existing = fs.existsSync(configPath) ? fs.readFileSync(configPath, "utf8") : "";
|
|
259
|
-
existing = existing
|
|
321
|
+
existing = stripBlockKeepingForeign(existing, PACK_TRUST_BEGIN, PACK_TRUST_END);
|
|
260
322
|
let lines = existing.split("\n");
|
|
261
323
|
for (const entry of entries)
|
|
262
324
|
lines = removeTable(lines, tableHeader(entry.key));
|
|
@@ -274,6 +336,7 @@ function writeCodexPackHookTrust(configPath, entries) {
|
|
|
274
336
|
tableHeader(entry.key),
|
|
275
337
|
"enabled = true",
|
|
276
338
|
`trusted_hash = ${JSON.stringify(entry.currentHash)}`,
|
|
339
|
+
...(entry.contentHash ? [`trusted_content_hash = ${JSON.stringify(entry.contentHash)}`] : []),
|
|
277
340
|
"",
|
|
278
341
|
]).join("\n");
|
|
279
342
|
const next = `${base}${base ? "\n\n" : ""}${PACK_TRUST_BEGIN}\n${trustBlock}${PACK_TRUST_END}\n`;
|
package/dist/codie.js
CHANGED
|
@@ -45,10 +45,10 @@ const codieBrandInstall_1 = require("./codieBrandInstall");
|
|
|
45
45
|
const codieUsage_1 = require("./codieUsage");
|
|
46
46
|
const codieRuntime_1 = require("./codieRuntime");
|
|
47
47
|
const codieRuntimeInstall_1 = require("./codieRuntimeInstall");
|
|
48
|
-
const codieStartup_1 = require("./codieStartup");
|
|
49
48
|
const upgradeNudge_1 = require("./upgradeNudge");
|
|
50
49
|
const codie_1 = require("./packs/codie");
|
|
51
50
|
const paths_1 = require("./packs/paths");
|
|
51
|
+
const managedPi_1 = require("./managedPi");
|
|
52
52
|
const USAGE_SETTLE_MS = 1200;
|
|
53
53
|
function git(args) {
|
|
54
54
|
const result = (0, child_process_1.spawnSync)("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
@@ -166,68 +166,8 @@ async function runNonInteractive(runtime, runtimeArgs, env) {
|
|
|
166
166
|
process.once("SIGINT", forwardInterrupt);
|
|
167
167
|
process.once("SIGTERM", forwardTermination);
|
|
168
168
|
return await new Promise((resolve, reject) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const retainedPrefixBytes = Math.max(...errorPrefixes.map((prefix) => prefix.length)) - 1;
|
|
172
|
-
const createOutputGate = (write) => {
|
|
173
|
-
let tail = Buffer.alloc(0);
|
|
174
|
-
let possibleError;
|
|
175
|
-
return {
|
|
176
|
-
push(chunk, blocked) {
|
|
177
|
-
if (blocked) {
|
|
178
|
-
if (possibleError)
|
|
179
|
-
possibleError.push(Buffer.from(chunk));
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (possibleError) {
|
|
183
|
-
possibleError.push(Buffer.from(chunk));
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const combined = Buffer.concat([tail, chunk]);
|
|
187
|
-
let errorStart = -1;
|
|
188
|
-
for (const prefix of errorPrefixes) {
|
|
189
|
-
const index = combined.indexOf(prefix);
|
|
190
|
-
if (index >= 0 && (errorStart < 0 || index < errorStart))
|
|
191
|
-
errorStart = index;
|
|
192
|
-
}
|
|
193
|
-
if (errorStart >= 0) {
|
|
194
|
-
if (errorStart > 0)
|
|
195
|
-
write(combined.subarray(0, errorStart));
|
|
196
|
-
possibleError = [combined.subarray(errorStart)];
|
|
197
|
-
tail = Buffer.alloc(0);
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const flushBytes = Math.max(0, combined.length - retainedPrefixBytes);
|
|
201
|
-
if (flushBytes > 0)
|
|
202
|
-
write(combined.subarray(0, flushBytes));
|
|
203
|
-
tail = combined.subarray(flushBytes);
|
|
204
|
-
},
|
|
205
|
-
finish(blocked) {
|
|
206
|
-
if (tail.length > 0)
|
|
207
|
-
write(tail);
|
|
208
|
-
const heldError = possibleError ? Buffer.concat(possibleError).toString() : "";
|
|
209
|
-
const genericBlockError = heldError.includes("UnknownError") &&
|
|
210
|
-
heldError.includes("Unexpected server error");
|
|
211
|
-
if (heldError && (!blocked || !genericBlockError))
|
|
212
|
-
write(heldError);
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
};
|
|
216
|
-
const stdoutGate = createOutputGate((chunk) => process.stdout.write(chunk));
|
|
217
|
-
const stderrGate = createOutputGate((chunk) => process.stderr.write(chunk));
|
|
218
|
-
child.stdout?.on("data", (chunk) => {
|
|
219
|
-
stdoutGate.push(Buffer.from(chunk), Boolean(blockReason));
|
|
220
|
-
});
|
|
221
|
-
child.stderr?.on("data", (chunk) => {
|
|
222
|
-
const text = chunk.toString();
|
|
223
|
-
const reason = (0, codieLauncher_1.extractCodieSecurityBlock)(text);
|
|
224
|
-
if (reason) {
|
|
225
|
-
blockReason = reason;
|
|
226
|
-
signalChild("SIGTERM");
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
stderrGate.push(Buffer.from(chunk), Boolean(blockReason));
|
|
230
|
-
});
|
|
169
|
+
child.stdout?.on("data", (chunk) => process.stdout.write(chunk));
|
|
170
|
+
child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
|
|
231
171
|
child.once("error", (error) => {
|
|
232
172
|
if (child.stdin)
|
|
233
173
|
process.stdin.unpipe(child.stdin);
|
|
@@ -240,11 +180,6 @@ async function runNonInteractive(runtime, runtimeArgs, env) {
|
|
|
240
180
|
process.stdin.unpipe(child.stdin);
|
|
241
181
|
process.removeListener("SIGINT", forwardInterrupt);
|
|
242
182
|
process.removeListener("SIGTERM", forwardTermination);
|
|
243
|
-
stdoutGate.finish(Boolean(blockReason));
|
|
244
|
-
stderrGate.finish(Boolean(blockReason));
|
|
245
|
-
if (blockReason) {
|
|
246
|
-
console.error(`Codie Security blocked this action:\n${blockReason}`);
|
|
247
|
-
}
|
|
248
183
|
resolve(status);
|
|
249
184
|
});
|
|
250
185
|
});
|
|
@@ -263,12 +198,28 @@ async function main() {
|
|
|
263
198
|
process.exitCode = update.status ?? 0;
|
|
264
199
|
return;
|
|
265
200
|
}
|
|
266
|
-
const policyRefresh = await (0, codieStartup_1.refreshCodieSecurityPolicy)(connected);
|
|
267
|
-
if (policyRefresh.status === "cached") {
|
|
268
|
-
console.error(`codie: security policy refresh failed; using the cached policy (${policyRefresh.error})`);
|
|
269
|
-
}
|
|
270
201
|
const gatewayUrl = process.env.CODIEDEV_GATEWAY_URL || "https://gateway.codiedev.com/api/v1";
|
|
271
202
|
const catalog = await (0, codieLauncher_1.fetchApprovedCatalog)({ baseUrl: gatewayUrl, key });
|
|
203
|
+
if (process.argv[2] === "--pi") {
|
|
204
|
+
let skillPaths = [];
|
|
205
|
+
try {
|
|
206
|
+
const approved = new Set(catalog.map((model) => (0, codieLauncher_1.bareModel)(model.id)).filter(Boolean));
|
|
207
|
+
skillPaths = (0, codie_1.codiePackConfig)((0, paths_1.packsRoot)(), { approvedModels: approved, catalog }).skillPaths;
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error(`codie: skipping starter packs (${error instanceof Error ? error.message : error})`);
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
process.exitCode = (0, managedPi_1.runManagedPi)({
|
|
214
|
+
args: process.argv.slice(3), key, gatewayUrl, catalog, stateDir: (0, configDir_1.codiedevStateDir)(), skillPaths,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.error(`codie: ${error instanceof Error ? error.message : String(error)}`);
|
|
219
|
+
process.exitCode = error instanceof managedPi_1.ManagedPiArgError ? 2 : 1;
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
272
223
|
const parsed = (0, codieLauncher_1.parseCodieArgs)(process.argv.slice(2));
|
|
273
224
|
if (parsed.args.length === 1 && parsed.args[0] === "models") {
|
|
274
225
|
console.log("Codiedev approved models\n");
|
|
@@ -343,8 +294,6 @@ async function main() {
|
|
|
343
294
|
};
|
|
344
295
|
const runtimeArgs = (0, codieLauncher_1.withCodieWorkingDirectory)(parsed.args, process.cwd());
|
|
345
296
|
const nonInteractiveRun = runtimeArgs[0] === "run";
|
|
346
|
-
if (nonInteractiveRun)
|
|
347
|
-
env.CODIEDEV_SECURITY_BLOCK_OUTPUT = "marker";
|
|
348
297
|
if (nonInteractiveRun) {
|
|
349
298
|
const reportCost = Boolean(process.stderr.isTTY);
|
|
350
299
|
const startedAt = Date.now();
|
package/dist/codieLauncher.js
CHANGED
|
@@ -33,10 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.HIDDEN_WORDMARK = exports.CODIEDEV_WORDMARK = exports.LEGACY_CODIEDEV_WORDMARK = exports.STOCK_WORDMARK = exports.BRAND_PLUGIN_SPEC = exports.USAGE_MODULE_PLACEHOLDER =
|
|
36
|
+
exports.HIDDEN_WORDMARK = exports.CODIEDEV_WORDMARK = exports.LEGACY_CODIEDEV_WORDMARK = exports.STOCK_WORDMARK = exports.BRAND_PLUGIN_SPEC = exports.USAGE_MODULE_PLACEHOLDER = void 0;
|
|
37
37
|
exports.usableModelCost = usableModelCost;
|
|
38
38
|
exports.usableModelLimit = usableModelLimit;
|
|
39
|
-
exports.extractCodieSecurityBlock = extractCodieSecurityBlock;
|
|
40
39
|
exports.withCodieWorkingDirectory = withCodieWorkingDirectory;
|
|
41
40
|
exports.bareModel = bareModel;
|
|
42
41
|
exports.buildCodieConfig = buildCodieConfig;
|
|
@@ -83,22 +82,6 @@ function usableModelLimit(value) {
|
|
|
83
82
|
return undefined;
|
|
84
83
|
return { context, output };
|
|
85
84
|
}
|
|
86
|
-
exports.CODIE_SECURITY_BLOCK_MARKER = "__CODIEDEV_SECURITY_BLOCK__";
|
|
87
|
-
function extractCodieSecurityBlock(stderr) {
|
|
88
|
-
for (const line of stderr.split(/\r?\n/)) {
|
|
89
|
-
const markerIndex = line.indexOf(exports.CODIE_SECURITY_BLOCK_MARKER);
|
|
90
|
-
if (markerIndex < 0)
|
|
91
|
-
continue;
|
|
92
|
-
try {
|
|
93
|
-
const parsed = JSON.parse(line.slice(markerIndex + exports.CODIE_SECURITY_BLOCK_MARKER.length));
|
|
94
|
-
if (typeof parsed?.reason === "string" && parsed.reason.trim())
|
|
95
|
-
return parsed.reason.trim();
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
85
|
function withCodieWorkingDirectory(args, cwd) {
|
|
103
86
|
if (args[0] !== "run")
|
|
104
87
|
return args;
|
|
@@ -305,20 +288,33 @@ function resolveCapturePlugin({ homeDir, existsSync, }) {
|
|
|
305
288
|
}
|
|
306
289
|
return (0, url_1.pathToFileURL)(capturePath).href;
|
|
307
290
|
}
|
|
308
|
-
|
|
291
|
+
class CatalogRejected extends Error {
|
|
292
|
+
}
|
|
293
|
+
async function fetchApprovedCatalog({ baseUrl, key, fetchImpl = fetch, retryDelayMs = 1_000, }) {
|
|
294
|
+
try {
|
|
295
|
+
return await fetchCatalogOnce(baseUrl, key, fetchImpl);
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
if (error instanceof CatalogRejected)
|
|
299
|
+
throw error;
|
|
300
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
301
|
+
return fetchCatalogOnce(baseUrl, key, fetchImpl);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
async function fetchCatalogOnce(baseUrl, key, fetchImpl) {
|
|
309
305
|
const controller = new AbortController();
|
|
310
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
306
|
+
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
311
307
|
try {
|
|
312
308
|
const response = await fetchImpl(`${cleanBaseUrl(baseUrl)}/models`, {
|
|
313
309
|
headers: { Authorization: `Bearer ${key}` },
|
|
314
310
|
signal: controller.signal,
|
|
315
311
|
});
|
|
316
312
|
if (response.status === 403) {
|
|
317
|
-
throw new
|
|
313
|
+
throw new CatalogRejected("The Codie harness is not enabled for your company yet. Ask your Codiedev admin to turn it on — " +
|
|
318
314
|
"your session capture keeps working in the meantime.");
|
|
319
315
|
}
|
|
320
316
|
if (response.status === 401) {
|
|
321
|
-
throw new
|
|
317
|
+
throw new CatalogRejected("Your Codiedev token was rejected. Run `codiedev connect` to relink this machine.");
|
|
322
318
|
}
|
|
323
319
|
if (!response.ok)
|
|
324
320
|
throw new Error(`model catalog returned ${response.status}`);
|