codiedev 0.9.73 → 0.9.76
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/cli.js +9 -2
- package/dist/codieLauncher.d.ts +7 -1
- package/dist/codieLauncher.js +24 -4
- package/dist/commands/evals.d.ts +3 -0
- package/dist/commands/evals.js +193 -0
- package/dist/commands/traces.js +7 -7
- package/dist/piRuntime.d.ts +1 -0
- package/dist/piRuntime.js +33 -20
- package/dist/utils.js +2 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -31,6 +31,7 @@ const send_1 = require("./commands/send");
|
|
|
31
31
|
const capture_1 = require("./commands/capture");
|
|
32
32
|
const pack_1 = require("./commands/pack");
|
|
33
33
|
const traces_1 = require("./commands/traces");
|
|
34
|
+
const evals_1 = require("./commands/evals");
|
|
34
35
|
// --- starter packs phase 2 ---
|
|
35
36
|
const hookGate_1 = require("./packs/hookGate");
|
|
36
37
|
const sync_1 = require("./packs/sync");
|
|
@@ -94,11 +95,13 @@ Starter packs:
|
|
|
94
95
|
|
|
95
96
|
Traces (agents on the gateway):
|
|
96
97
|
codiedev traces agents Agents you maintain, with saved test cases
|
|
97
|
-
codiedev traces cases <agent> [--
|
|
98
|
-
Pull an agent's test cases (or one
|
|
98
|
+
codiedev traces cases <agent> [--dataset name] [--model id]
|
|
99
|
+
Pull an agent's test cases (or one dataset)
|
|
99
100
|
into this repo for your coding agent to
|
|
100
101
|
run, optionally on another model
|
|
101
102
|
codiedev traces report <results.json> Send the results back to Traces
|
|
103
|
+
codiedev evals report <run.json> File one variant's eval scores under an experiment
|
|
104
|
+
codiedev evals last <subject> Latest experiment on a subject + its champion
|
|
102
105
|
|
|
103
106
|
Discovery:
|
|
104
107
|
codiedev search "<query>" Semantic search across the team's
|
|
@@ -162,6 +165,7 @@ status sync never weakens it.
|
|
|
162
165
|
const COMMAND_HELP = {
|
|
163
166
|
pack: pack_1.PACK_HELP,
|
|
164
167
|
traces: traces_1.TRACES_HELP,
|
|
168
|
+
evals: evals_1.EVALS_HELP,
|
|
165
169
|
connect: `
|
|
166
170
|
codiedev connect — link your agent CLI to Codiedev
|
|
167
171
|
|
|
@@ -528,6 +532,9 @@ async function main() {
|
|
|
528
532
|
case "traces":
|
|
529
533
|
await (0, traces_1.runTraces)(rest);
|
|
530
534
|
return;
|
|
535
|
+
case "evals":
|
|
536
|
+
await (0, evals_1.runEvals)(rest);
|
|
537
|
+
return;
|
|
531
538
|
case "share":
|
|
532
539
|
await (0, share_1.runShare)(rest);
|
|
533
540
|
return;
|
package/dist/codieLauncher.d.ts
CHANGED
|
@@ -69,10 +69,16 @@ export declare function resolveCapturePlugin({ homeDir, existsSync, }: {
|
|
|
69
69
|
homeDir: string;
|
|
70
70
|
existsSync: (candidate: string) => boolean;
|
|
71
71
|
}): string;
|
|
72
|
-
|
|
72
|
+
/**
|
|
73
|
+
* The account's approved models. Every `codie` session starts here, so one
|
|
74
|
+
* dropped connection or slow gateway reply would end the session before it
|
|
75
|
+
* began; anything but a definite rejection is retried once.
|
|
76
|
+
*/
|
|
77
|
+
export declare function fetchApprovedCatalog({ baseUrl, key, fetchImpl, retryDelayMs, }: {
|
|
73
78
|
baseUrl?: string;
|
|
74
79
|
key: string;
|
|
75
80
|
fetchImpl?: typeof fetch;
|
|
81
|
+
retryDelayMs?: number;
|
|
76
82
|
}): Promise<CatalogModel[]>;
|
|
77
83
|
export declare function parseCodieArgs(argv: string[]): {
|
|
78
84
|
args: string[];
|
package/dist/codieLauncher.js
CHANGED
|
@@ -349,9 +349,29 @@ function resolveCapturePlugin({ homeDir, existsSync, }) {
|
|
|
349
349
|
}
|
|
350
350
|
return (0, url_1.pathToFileURL)(capturePath).href;
|
|
351
351
|
}
|
|
352
|
-
|
|
352
|
+
// A definite answer from the gateway (harness off, token rejected): retrying
|
|
353
|
+
// can't change it.
|
|
354
|
+
class CatalogRejected extends Error {
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* The account's approved models. Every `codie` session starts here, so one
|
|
358
|
+
* dropped connection or slow gateway reply would end the session before it
|
|
359
|
+
* began; anything but a definite rejection is retried once.
|
|
360
|
+
*/
|
|
361
|
+
async function fetchApprovedCatalog({ baseUrl, key, fetchImpl = fetch, retryDelayMs = 1_000, }) {
|
|
362
|
+
try {
|
|
363
|
+
return await fetchCatalogOnce(baseUrl, key, fetchImpl);
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
if (error instanceof CatalogRejected)
|
|
367
|
+
throw error;
|
|
368
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
369
|
+
return fetchCatalogOnce(baseUrl, key, fetchImpl);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async function fetchCatalogOnce(baseUrl, key, fetchImpl) {
|
|
353
373
|
const controller = new AbortController();
|
|
354
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
374
|
+
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
355
375
|
try {
|
|
356
376
|
const response = await fetchImpl(`${cleanBaseUrl(baseUrl)}/models`, {
|
|
357
377
|
headers: { Authorization: `Bearer ${key}` },
|
|
@@ -361,11 +381,11 @@ async function fetchApprovedCatalog({ baseUrl, key, fetchImpl = fetch, }) {
|
|
|
361
381
|
// whose gateway is still switched off. Those developers must get an
|
|
362
382
|
// answer, not an HTTP status.
|
|
363
383
|
if (response.status === 403) {
|
|
364
|
-
throw new
|
|
384
|
+
throw new CatalogRejected("The Codie harness is not enabled for your company yet. Ask your Codiedev admin to turn it on — " +
|
|
365
385
|
"your session capture keeps working in the meantime.");
|
|
366
386
|
}
|
|
367
387
|
if (response.status === 401) {
|
|
368
|
-
throw new
|
|
388
|
+
throw new CatalogRejected("Your Codiedev token was rejected. Run `codiedev connect` to relink this machine.");
|
|
369
389
|
}
|
|
370
390
|
if (!response.ok)
|
|
371
391
|
throw new Error(`model catalog returned ${response.status}`);
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// `codiedev evals report <run.json> [--harness name]`
|
|
3
|
+
// `codiedev evals last <subject> [--json]`
|
|
4
|
+
//
|
|
5
|
+
// Evals are experiments (a question about a subject: an agent, or a workload
|
|
6
|
+
// like session-summaries) and the runs that answer them, one per variant. The
|
|
7
|
+
// eval runs wherever it runs (a script, a coding agent); `report` files the
|
|
8
|
+
// scores under the experiment in Codiedev → Traces → Evals, shared with the
|
|
9
|
+
// team. `last` is where to start the next one: the latest experiment on the
|
|
10
|
+
// subject, its runs, and the champion the subject runs today.
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.EVALS_HELP = void 0;
|
|
46
|
+
exports.runEvals = runEvals;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const shared_1 = require("./shared");
|
|
50
|
+
exports.EVALS_HELP = `
|
|
51
|
+
codiedev evals — experiments and their runs, shared with the team
|
|
52
|
+
|
|
53
|
+
codiedev evals report <run.json> [--harness name]
|
|
54
|
+
File one variant's scores under an
|
|
55
|
+
experiment (created on first use)
|
|
56
|
+
codiedev evals last <subject> [--json] The latest experiment on a subject,
|
|
57
|
+
its runs, and the current champion
|
|
58
|
+
|
|
59
|
+
run.json:
|
|
60
|
+
{
|
|
61
|
+
"subject": "session-summaries", // agent name or workload
|
|
62
|
+
"question": "Is Terra medium as good as GLM high?",
|
|
63
|
+
"experimentId": "…", // optional, instead of subject + question
|
|
64
|
+
"dataset": "30 Signal & Code sessions", // optional
|
|
65
|
+
"run": {
|
|
66
|
+
"label": "terra-med-v2", "model": "openai/gpt-6.1-terra",
|
|
67
|
+
"provider": "openai", "reasoningEffort": "medium", "prompt": "summary_extract_v2",
|
|
68
|
+
"gitSha": "…", "isControl": false, "judgeModel": "anthropic/claude-sonnet-5.5",
|
|
69
|
+
"casesTotal": 30, "casesScored": 30, "errors": 0,
|
|
70
|
+
"score": 3.85, "metrics": { "fidelity": 3.6 },
|
|
71
|
+
"costPerCaseUsd": 0.026, "latencyMsAvg": 21000,
|
|
72
|
+
"wins": 20, "losses": 8, "ties": 2, "note": "…",
|
|
73
|
+
"cases": [{ "key": "case-1", "score": 4, "note": "…" }]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Scores and notes only: never put prompts, transcripts or outputs in it.
|
|
78
|
+
`.trim();
|
|
79
|
+
function flag(args, i, name) {
|
|
80
|
+
const a = args[i];
|
|
81
|
+
if (a === name && i + 1 < args.length)
|
|
82
|
+
return { value: args[i + 1], skip: 1 };
|
|
83
|
+
if (a.startsWith(`${name}=`))
|
|
84
|
+
return { value: a.slice(name.length + 1), skip: 0 };
|
|
85
|
+
return { skip: -1 };
|
|
86
|
+
}
|
|
87
|
+
function variant(run) {
|
|
88
|
+
return [run.model, run.reasoningEffort, run.prompt].filter(Boolean).join(" · ");
|
|
89
|
+
}
|
|
90
|
+
function fmtScore(n) {
|
|
91
|
+
return n === null ? "–" : n.toFixed(2);
|
|
92
|
+
}
|
|
93
|
+
function fmtCost(n) {
|
|
94
|
+
return n === null ? "–" : `$${n.toFixed(4)}`;
|
|
95
|
+
}
|
|
96
|
+
async function runReport(args, config) {
|
|
97
|
+
let file;
|
|
98
|
+
let harness;
|
|
99
|
+
for (let i = 0; i < args.length; i++) {
|
|
100
|
+
const f = flag(args, i, "--harness");
|
|
101
|
+
if (f.skip >= 0) {
|
|
102
|
+
harness = f.value;
|
|
103
|
+
i += f.skip;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (!args[i].startsWith("-") && !file)
|
|
107
|
+
file = args[i];
|
|
108
|
+
}
|
|
109
|
+
if (!file) {
|
|
110
|
+
console.error("Usage: codiedev evals report <run.json> [--harness name]");
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
let body;
|
|
114
|
+
try {
|
|
115
|
+
body = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), file), "utf8"));
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.error(`Couldn't read ${file}: ${err.message}`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
if (!body.subject || !body.question || !body.run?.label || !body.run?.model || typeof body.run?.casesTotal !== "number") {
|
|
122
|
+
console.error(`${file} needs subject, question, and run.label, run.model, run.casesTotal. See: codiedev evals help`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
const start = Date.now();
|
|
126
|
+
try {
|
|
127
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/evals/runs", {
|
|
128
|
+
config,
|
|
129
|
+
body: { ...body, run: { ...body.run, harness: harness ?? body.run.harness ?? undefined } },
|
|
130
|
+
});
|
|
131
|
+
(0, shared_1.recordAgentEvent)(config, { tool: "codiedev_evals_report", ok: true, latencyMs: Date.now() - start });
|
|
132
|
+
console.log(`✓ Reported ${body.run.label} on ${body.subject}${res.created ? " (new experiment)" : ""}: "${body.question}"`);
|
|
133
|
+
console.log(` experiment ${res.experimentId}. See it in Codiedev → Traces → Evals.`);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
const e = err;
|
|
137
|
+
(0, shared_1.recordAgentEvent)(config, { tool: "codiedev_evals_report", ok: false, latencyMs: Date.now() - start, error: e.message });
|
|
138
|
+
console.error(`Couldn't report: ${e.message}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function runLast(args, config) {
|
|
143
|
+
const json = args.includes("--json");
|
|
144
|
+
const subject = args.find((a) => !a.startsWith("-"));
|
|
145
|
+
if (!subject) {
|
|
146
|
+
console.error("Usage: codiedev evals last <subject> [--json]");
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
let res;
|
|
150
|
+
try {
|
|
151
|
+
res = await (0, shared_1.apiRequest)("GET", `/api/cli/evals/last?subject=${encodeURIComponent(subject)}`, { config });
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
const e = err;
|
|
155
|
+
console.error(e.status === 404 ? `No evals on ${subject} yet.` : `Couldn't load evals: ${e.message}`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
if (json) {
|
|
159
|
+
console.log(JSON.stringify(res, null, 2));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const { experiment, runs, champion } = res;
|
|
163
|
+
if (champion) {
|
|
164
|
+
console.log(`Champion: ${champion.run.label} (${variant(champion.run)}), score ${fmtScore(champion.run.score)}, ${fmtCost(champion.run.costPerCaseUsd)}/case`);
|
|
165
|
+
if (champion.decisionNote)
|
|
166
|
+
console.log(` Why: ${champion.decisionNote}`);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.log("Champion: none picked yet");
|
|
170
|
+
}
|
|
171
|
+
console.log("");
|
|
172
|
+
console.log(`Latest experiment (${res.experiments} on ${experiment.subject}): ${experiment.question}`);
|
|
173
|
+
if (experiment.dataset)
|
|
174
|
+
console.log(` Dataset: ${experiment.dataset}`);
|
|
175
|
+
console.log(` id ${experiment.id}, by ${experiment.createdBy}, updated ${new Date(experiment.updatedAt).toISOString().slice(0, 16).replace("T", " ")}`);
|
|
176
|
+
console.log("");
|
|
177
|
+
for (const run of [...runs].sort((a, b) => a.ranAt - b.ranAt)) {
|
|
178
|
+
const h2h = run.wins !== null ? ` · ${run.wins}W/${run.losses ?? 0}L/${run.ties ?? 0}T` : "";
|
|
179
|
+
console.log(` ${run.isControl ? "[control] " : ""}${run.label.padEnd(24)} ${fmtScore(run.score).padStart(5)} ${fmtCost(run.costPerCaseUsd).padStart(8)}/case${h2h} ${variant(run)}`);
|
|
180
|
+
}
|
|
181
|
+
console.log("");
|
|
182
|
+
console.log(`Next run on this experiment: put "experimentId": "${experiment.id}" in run.json, then codiedev evals report run.json`);
|
|
183
|
+
}
|
|
184
|
+
async function runEvals(args, configOverride) {
|
|
185
|
+
const [sub, ...rest] = args;
|
|
186
|
+
if (sub === "report")
|
|
187
|
+
return runReport(rest, configOverride ?? (0, shared_1.requireConfig)());
|
|
188
|
+
if (sub === "last")
|
|
189
|
+
return runLast(rest, configOverride ?? (0, shared_1.requireConfig)());
|
|
190
|
+
console.log(exports.EVALS_HELP);
|
|
191
|
+
if (sub && sub !== "help")
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
package/dist/commands/traces.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// `codiedev traces agents`
|
|
3
|
-
// `codiedev traces cases <agent> [--
|
|
3
|
+
// `codiedev traces cases <agent> [--dataset name] [--model id] [--out dir] [--json]`
|
|
4
4
|
// `codiedev traces report <results.json> [--harness name]`
|
|
5
5
|
//
|
|
6
6
|
// Test cases are runs an engineer saved from Codiedev → Traces. They run in
|
|
@@ -55,10 +55,10 @@ exports.TRACES_HELP = `
|
|
|
55
55
|
codiedev traces — test cases saved from Codiedev → Traces
|
|
56
56
|
|
|
57
57
|
codiedev traces agents Agents you maintain, with saved case counts
|
|
58
|
-
codiedev traces cases <agent> [--
|
|
59
|
-
Write an agent's cases (one
|
|
58
|
+
codiedev traces cases <agent> [--dataset name] [--case id[,id]] [--model id] [--out dir] [--json]
|
|
59
|
+
Write an agent's cases (one dataset, or just
|
|
60
60
|
the cases named) into this repo, default
|
|
61
|
-
.codiedev/traces/<agent>[/<
|
|
61
|
+
.codiedev/traces/<agent>[/<dataset>]/, then
|
|
62
62
|
ask your coding agent to run them.
|
|
63
63
|
--model runs them on another model, e.g.
|
|
64
64
|
the replacement for a retiring one
|
|
@@ -140,7 +140,7 @@ function parseCasesArgs(args) {
|
|
|
140
140
|
for (let i = 0; i < args.length; i++) {
|
|
141
141
|
const a = args[i];
|
|
142
142
|
let matched = false;
|
|
143
|
-
for (const [name, key] of [["--out", "out"], ["-o", "out"], ["--suite", "suite"], ["--model", "model"], ["--case", "caseIds"]]) {
|
|
143
|
+
for (const [name, key] of [["--out", "out"], ["-o", "out"], ["--dataset", "suite"], ["--suite", "suite"], ["--model", "model"], ["--case", "caseIds"]]) {
|
|
144
144
|
const f = flag(args, i, name);
|
|
145
145
|
if (f.skip >= 0) {
|
|
146
146
|
parsed[key] = f.value;
|
|
@@ -184,7 +184,7 @@ async function runAgents(config) {
|
|
|
184
184
|
async function runCases(args, config) {
|
|
185
185
|
const { agent, suite, model, caseIds, out, json } = parseCasesArgs(args);
|
|
186
186
|
if (!agent) {
|
|
187
|
-
console.error("Usage: codiedev traces cases <agent> [--
|
|
187
|
+
console.error("Usage: codiedev traces cases <agent> [--dataset name] [--model id] [--out dir] [--json]");
|
|
188
188
|
process.exit(1);
|
|
189
189
|
}
|
|
190
190
|
const start = Date.now();
|
|
@@ -210,7 +210,7 @@ async function runCases(args, config) {
|
|
|
210
210
|
}
|
|
211
211
|
if (!res.cases.length) {
|
|
212
212
|
console.log(suite
|
|
213
|
-
? `${res.agent.name} has no test cases in "${suite}". See your
|
|
213
|
+
? `${res.agent.name} has no test cases in "${suite}". See your datasets in Codiedev → Traces → Test cases.`
|
|
214
214
|
: `${res.agent.name} has no saved test cases. Open a run in Codiedev → Traces and click "Save as test case".`);
|
|
215
215
|
return;
|
|
216
216
|
}
|
package/dist/piRuntime.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface PiRuntimeDeps {
|
|
|
16
16
|
rename?: (from: string, to: string) => void;
|
|
17
17
|
remove?: (target: string) => void;
|
|
18
18
|
log?: (message: string) => void;
|
|
19
|
+
sleep?: (ms: number) => void;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* The pi CLI entry to run, installing the pinned version first if it is
|
package/dist/piRuntime.js
CHANGED
|
@@ -70,6 +70,10 @@ function installedPiEntry(installDir, readFile = (f) => fs.readFileSync(f, "utf8
|
|
|
70
70
|
return null;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
// One retry rides out a dropped connection or registry blip; a second
|
|
74
|
+
// failure is a real problem (offline, blocked registry) and is reported.
|
|
75
|
+
const INSTALL_ATTEMPTS = 2;
|
|
76
|
+
const INSTALL_RETRY_DELAY_MS = 5_000;
|
|
73
77
|
/**
|
|
74
78
|
* The pi CLI entry to run, installing the pinned version first if it is
|
|
75
79
|
* missing or a different version. Staged then renamed, so an interrupted
|
|
@@ -85,10 +89,10 @@ function ensurePiRuntime(deps) {
|
|
|
85
89
|
const remove = deps.remove ?? ((target) => fs.rmSync(target, { recursive: true, force: true }));
|
|
86
90
|
const rename = deps.rename ?? fs.renameSync;
|
|
87
91
|
const log = deps.log ?? ((message) => console.error(message));
|
|
88
|
-
const
|
|
92
|
+
const makeStagingDir = deps.makeStagingDir ?? (() => {
|
|
89
93
|
fs.mkdirSync(deps.stateDir, { recursive: true });
|
|
90
94
|
return fs.mkdtempSync(path.join(deps.stateDir, ".runtime-pi-"));
|
|
91
|
-
})
|
|
95
|
+
});
|
|
92
96
|
const run = deps.run ?? ((args) => {
|
|
93
97
|
const result = (0, child_process_1.spawnSync)(process.platform === "win32" ? "npm.cmd" : "npm", args, {
|
|
94
98
|
encoding: "utf8", stdio: ["ignore", "ignore", "pipe"], shell: process.platform === "win32",
|
|
@@ -97,26 +101,35 @@ function ensurePiRuntime(deps) {
|
|
|
97
101
|
throw result.error;
|
|
98
102
|
return { status: result.status, stderr: result.stderr ?? "" };
|
|
99
103
|
});
|
|
104
|
+
const sleep = deps.sleep ?? ((ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms));
|
|
100
105
|
log(`Installing pi (${exports.PI_RUNTIME_SPEC}). This runs once, and only for \`codie --pi\`.`);
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
for (let attempt = 1;; attempt++) {
|
|
107
|
+
const staging = makeStagingDir();
|
|
108
|
+
try {
|
|
109
|
+
const result = run((0, codieRuntimeInstall_1.buildRuntimeInstallArgs)(staging, exports.PI_RUNTIME_SPEC));
|
|
110
|
+
if (result.status !== 0)
|
|
111
|
+
throw new Error(result.stderr?.trim() || `npm exited with ${result.status}`);
|
|
112
|
+
// Trust the artifact, not the exit code.
|
|
113
|
+
const staged = installedPiEntry(staging, readFile);
|
|
114
|
+
if (!staged || !exists(staged)) {
|
|
115
|
+
throw new Error(`the install did not produce pi. Check that ${exports.PI_RUNTIME_SPEC} is available from your npm registry.`);
|
|
116
|
+
}
|
|
117
|
+
remove(installDir);
|
|
118
|
+
rename(staging, installDir);
|
|
119
|
+
break;
|
|
109
120
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
catch (error) {
|
|
122
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
123
|
+
if (attempt >= INSTALL_ATTEMPTS)
|
|
124
|
+
throw new Error(`Couldn't install pi: ${message}`);
|
|
125
|
+
log(`pi install failed (${message.split("\n")[0]}); retrying.`);
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
// No-op after a successful promote; otherwise it keeps a ~200MB staging
|
|
129
|
+
// dir from being orphaned.
|
|
130
|
+
remove(staging);
|
|
131
|
+
}
|
|
132
|
+
sleep(INSTALL_RETRY_DELAY_MS);
|
|
120
133
|
}
|
|
121
134
|
const entry = installedPiEntry(installDir, readFile);
|
|
122
135
|
if (!entry)
|
package/dist/utils.js
CHANGED
|
@@ -1681,7 +1681,8 @@ thought, use the \`codiedev\` CLI via Bash:**
|
|
|
1681
1681
|
| "find something about X" / "has anyone solved Y?" | \`codiedev search "<query>" [--limit N]\` |
|
|
1682
1682
|
| "why did we…?" / "what does the team know about X?" | \`codiedev ask "<question>"\` (synthesized answer + citations) |
|
|
1683
1683
|
| "show my library" / "what artifacts exist?" | \`codiedev library [--scope mine\\|shared\\|all] [--kind doc\\|skill]\` |
|
|
1684
|
-
| "run my agent's test cases" / "check the
|
|
1684
|
+
| "run my agent's test cases" / "check the dataset on model Y" | \`codiedev traces cases <agent> [--dataset <name>] [--model <id>]\` (writes cases + RUN_CASES.md + results.json; follow it, then \`codiedev traces report <results.json>\`) |
|
|
1685
|
+
| "what was the last eval on X?" / "file these eval results" | \`codiedev evals last <subject>\` before starting a related eval; \`codiedev evals report <run.json>\` after each variant runs (scores only — \`codiedev evals help\` for the shape) |
|
|
1685
1686
|
|
|
1686
1687
|
**Just push the file — we'll figure out where it goes.** Every artifact
|
|
1687
1688
|
is classified into one of two kinds at upload time:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codiedev",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.76",
|
|
4
4
|
"description": "Connect Claude Code, Codex, Cursor, OpenCode, or VS Code Copilot to Codiedev for team session capture and artifact collaboration — and run the governed Codie harness",
|
|
5
5
|
"bin": {
|
|
6
6
|
"codiedev": "dist/cli.js",
|