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.
Files changed (157) hide show
  1. package/README.md +11 -5
  2. package/assets/tui-brand-plugin.tsx +14 -2
  3. package/dist/backup/cache.js +1 -5
  4. package/dist/backup/match.js +0 -6
  5. package/dist/backup/run.js +3 -35
  6. package/dist/captureExclusions.js +0 -12
  7. package/dist/captureLog.js +0 -28
  8. package/dist/captureReadiness.js +0 -58
  9. package/dist/captureSignals.js +68 -3
  10. package/dist/cli.js +75 -64
  11. package/dist/codexHookTrust.js +125 -6
  12. package/dist/codexLimitScan.js +2 -109
  13. package/dist/codie.js +50 -114
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +20 -92
  16. package/dist/codieRuntime.js +19 -23
  17. package/dist/codieRuntimeInstall.js +108 -23
  18. package/dist/codieUsage.js +38 -41
  19. package/dist/commands/agentTemplates.generated.js +136 -0
  20. package/dist/commands/agents.js +1066 -0
  21. package/dist/commands/agentsSdk.generated.js +7 -0
  22. package/dist/commands/ask.js +0 -3
  23. package/dist/commands/capture.js +0 -2
  24. package/dist/commands/createTicket.js +0 -10
  25. package/dist/commands/doctor.js +53 -120
  26. package/dist/commands/evals.js +187 -0
  27. package/dist/commands/inbox.js +0 -2
  28. package/dist/commands/library.js +0 -3
  29. package/dist/commands/pack.js +573 -0
  30. package/dist/commands/ping.js +0 -2
  31. package/dist/commands/pull.js +6 -10
  32. package/dist/commands/push.js +2 -12
  33. package/dist/commands/search.js +0 -4
  34. package/dist/commands/send.js +0 -5
  35. package/dist/commands/share.js +0 -4
  36. package/dist/commands/shared.js +0 -35
  37. package/dist/commands/traces.js +344 -0
  38. package/dist/commands/tracesLabel.js +348 -0
  39. package/dist/configDir.js +0 -10
  40. package/dist/connect.js +19 -116
  41. package/dist/connectFlow.js +0 -9
  42. package/dist/copilotHooks.js +391 -0
  43. package/dist/copilotInstallation.js +64 -0
  44. package/dist/cursorHooks.js +38 -30
  45. package/dist/cursorLifecycle.js +109 -0
  46. package/dist/detection.js +0 -30
  47. package/dist/harnessDirs.js +77 -0
  48. package/dist/hook.js +182 -469
  49. package/dist/inboxFormat.js +0 -24
  50. package/dist/launchContext.js +150 -0
  51. package/dist/launcher.js +140 -0
  52. package/dist/limitEvent.js +41 -35
  53. package/dist/limitEventReporter.js +1 -1
  54. package/dist/managedPi.js +240 -0
  55. package/dist/mcp.js +3 -384
  56. package/dist/nativeSteering.js +24 -0
  57. package/dist/packs/codie.js +182 -0
  58. package/dist/packs/harnesses.js +411 -0
  59. package/dist/packs/hookGate.js +256 -0
  60. package/dist/packs/install.js +286 -0
  61. package/dist/packs/manifest.js +126 -0
  62. package/dist/packs/paths.js +81 -0
  63. package/dist/packs/shim.js +214 -0
  64. package/dist/packs/store.js +155 -0
  65. package/dist/packs/sync.js +170 -0
  66. package/dist/piHooks.js +216 -0
  67. package/dist/piRuntime.js +120 -0
  68. package/dist/repoResolver.js +0 -19
  69. package/dist/secret.js +0 -3
  70. package/dist/selfUpdate.js +376 -0
  71. package/dist/skillMarker.js +23 -0
  72. package/dist/subagents.js +135 -0
  73. package/dist/teamSkillContext.js +10 -0
  74. package/dist/transcriptModels.js +6 -8
  75. package/dist/upgradeNudge.js +0 -30
  76. package/dist/utils.js +494 -824
  77. package/dist/version.js +0 -10
  78. package/dist/versionCheck.js +0 -33
  79. package/package.json +8 -9
  80. package/dist/backup/cache.d.ts +0 -14
  81. package/dist/backup/match.d.ts +0 -2
  82. package/dist/backup/run.d.ts +0 -25
  83. package/dist/captureExclusions.d.ts +0 -30
  84. package/dist/captureLog.d.ts +0 -20
  85. package/dist/captureReadiness.d.ts +0 -65
  86. package/dist/captureSignals.d.ts +0 -19
  87. package/dist/cli.d.ts +0 -16
  88. package/dist/codexHookTrust.d.ts +0 -34
  89. package/dist/codexLimitScan.d.ts +0 -64
  90. package/dist/codie.d.ts +0 -2
  91. package/dist/codieBrandInstall.d.ts +0 -11
  92. package/dist/codieLauncher.d.ts +0 -86
  93. package/dist/codieRuntime.d.ts +0 -29
  94. package/dist/codieRuntimeInstall.d.ts +0 -28
  95. package/dist/codieStartup.d.ts +0 -26
  96. package/dist/codieStartup.js +0 -30
  97. package/dist/codieUsage.d.ts +0 -57
  98. package/dist/commands/ask.d.ts +0 -1
  99. package/dist/commands/capture.d.ts +0 -14
  100. package/dist/commands/createTicket.d.ts +0 -27
  101. package/dist/commands/delete.d.ts +0 -1
  102. package/dist/commands/doctor.d.ts +0 -1
  103. package/dist/commands/inbox.d.ts +0 -3
  104. package/dist/commands/library.d.ts +0 -2
  105. package/dist/commands/note.d.ts +0 -1
  106. package/dist/commands/ping.d.ts +0 -1
  107. package/dist/commands/promote.d.ts +0 -1
  108. package/dist/commands/promote.js +0 -53
  109. package/dist/commands/pull.d.ts +0 -2
  110. package/dist/commands/push.d.ts +0 -33
  111. package/dist/commands/react.d.ts +0 -2
  112. package/dist/commands/react.js +0 -40
  113. package/dist/commands/reverseTicket.d.ts +0 -2
  114. package/dist/commands/reverseTicket.js +0 -477
  115. package/dist/commands/search.d.ts +0 -2
  116. package/dist/commands/security.d.ts +0 -1
  117. package/dist/commands/security.js +0 -156
  118. package/dist/commands/send.d.ts +0 -2
  119. package/dist/commands/share.d.ts +0 -2
  120. package/dist/commands/shared.d.ts +0 -64
  121. package/dist/configDir.d.ts +0 -1
  122. package/dist/connect.d.ts +0 -1
  123. package/dist/connectFlow.d.ts +0 -13
  124. package/dist/cursorHooks.d.ts +0 -23
  125. package/dist/detection.d.ts +0 -30
  126. package/dist/hook.d.ts +0 -6
  127. package/dist/inboxFormat.d.ts +0 -38
  128. package/dist/limitEvent.d.ts +0 -16
  129. package/dist/limitEventReporter.d.ts +0 -21
  130. package/dist/mcp.d.ts +0 -12
  131. package/dist/prUrl.d.ts +0 -9
  132. package/dist/prUrl.js +0 -33
  133. package/dist/repoResolver.d.ts +0 -17
  134. package/dist/secret.d.ts +0 -1
  135. package/dist/security.d.ts +0 -102
  136. package/dist/security.js +0 -437
  137. package/dist/securityDeepScan.d.ts +0 -41
  138. package/dist/securityDeepScan.js +0 -248
  139. package/dist/securityDoctor.d.ts +0 -32
  140. package/dist/securityDoctor.js +0 -63
  141. package/dist/securityFeature.d.ts +0 -5
  142. package/dist/securityFeature.js +0 -7
  143. package/dist/securityInstall.d.ts +0 -63
  144. package/dist/securityInstall.js +0 -239
  145. package/dist/securityInventory.d.ts +0 -54
  146. package/dist/securityInventory.js +0 -556
  147. package/dist/securityPilot.d.ts +0 -19
  148. package/dist/securityPilot.js +0 -61
  149. package/dist/securityPolicy.d.ts +0 -33
  150. package/dist/securityPolicy.js +0 -188
  151. package/dist/securitySession.d.ts +0 -6
  152. package/dist/securitySession.js +0 -72
  153. package/dist/transcriptModels.d.ts +0 -18
  154. package/dist/upgradeNudge.d.ts +0 -25
  155. package/dist/utils.d.ts +0 -346
  156. package/dist/version.d.ts +0 -1
  157. package/dist/versionCheck.d.ts +0 -68
@@ -1,8 +1,4 @@
1
1
  "use strict";
2
- // `codiedev search "<query>"` — semantic + keyword search across the org's
3
- // captured sessions, artifacts, and skills. Hits are filtered by companyId
4
- // server-side, so a single search surfaces results from every teammate's
5
- // prior sessions in the same workspace.
6
2
  Object.defineProperty(exports, "__esModule", { value: true });
7
3
  exports.runSearch = runSearch;
8
4
  const shared_1 = require("./shared");
@@ -1,8 +1,4 @@
1
1
  "use strict";
2
- // `codiedev send <filename> <recipient> [message]` — share an artifact AND
3
- // send a short message that lands in the teammate's inbox. The active-
4
- // handoff version of `codiedev share`. Use this when the user is actively
5
- // looping someone in.
6
2
  Object.defineProperty(exports, "__esModule", { value: true });
7
3
  exports.runSend = runSend;
8
4
  const shared_1 = require("./shared");
@@ -13,7 +9,6 @@ function parseArgs(args) {
13
9
  console.error('Usage: codiedev send <filename> <recipient> ["<message>"]');
14
10
  process.exit(1);
15
11
  }
16
- // Recombine remaining tokens — supports both quoted and unquoted messages.
17
12
  const message = rest.length > 0 ? (0, shared_1.stripQuotes)(rest.join(" ")) : undefined;
18
13
  return { filename, to, message };
19
14
  }
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- // `codiedev share <filename> <recipient> [--role read|edit]` — silently
3
- // grant a teammate access to an artifact (no notification). Use
4
- // `codiedev send` instead when the user wants to actively loop someone in.
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.runShare = runShare;
7
4
  const shared_1 = require("./shared");
@@ -71,7 +68,6 @@ async function runShare(args, configOverride) {
71
68
  latencyMs: Date.now() - start,
72
69
  error: err.message,
73
70
  });
74
- // Ambiguous recipients return 409 with candidates in the body.
75
71
  const body = err.body;
76
72
  if (body && Array.isArray(body.candidates) && body.candidates.length > 0) {
77
73
  console.error(`Recipient "${parsed.to}" is ambiguous. Candidates:`);
@@ -45,13 +45,6 @@ const https = __importStar(require("https"));
45
45
  const http = __importStar(require("http"));
46
46
  const utils_1 = require("../utils");
47
47
  const version_1 = require("../version");
48
- /**
49
- * Layer per-command env overrides on top of the on-disk config. Useful for
50
- * ad-hoc testing — point a prod-connected CLI at a dev Convex deployment
51
- * without re-running `codiedev connect`. Both CODIEDEV_URL and CODIEDEV_TOKEN
52
- * must be set together (half-overrides would mismatch URL and auth realm).
53
- * Other fields (companyId, repos[]) come from the file unchanged.
54
- */
55
48
  function applyConfigEnvOverrides(config) {
56
49
  const url = process.env.CODIEDEV_URL;
57
50
  const token = process.env.CODIEDEV_TOKEN;
@@ -60,10 +53,6 @@ function applyConfigEnvOverrides(config) {
60
53
  }
61
54
  return config;
62
55
  }
63
- /**
64
- * Require a connected Codiedev config. Exits the process with a helpful
65
- * message if the user hasn't run `codiedev connect` yet.
66
- */
67
56
  function requireConfig() {
68
57
  const config = (0, utils_1.readConfig)();
69
58
  if (!config) {
@@ -72,10 +61,6 @@ function requireConfig() {
72
61
  }
73
62
  return applyConfigEnvOverrides(config);
74
63
  }
75
- /**
76
- * Perform an authenticated HTTP request against the Codiedev backend.
77
- * Returns the parsed JSON response body. Throws on non-2xx.
78
- */
79
64
  function apiRequest(method, path, options) {
80
65
  return new Promise((resolve, reject) => {
81
66
  const base = options.config.backendUrl;
@@ -135,12 +120,6 @@ function apiRequest(method, path, options) {
135
120
  req.end();
136
121
  });
137
122
  }
138
- /**
139
- * Fire-and-forget per-invocation telemetry from CLI subcommands. Mirrors
140
- * the MCP server's emitTelemetry but stamps `source: "cli"` so adoption
141
- * dashboards can distinguish between the two surfaces. Never blocks the
142
- * user's command, never throws — telemetry must not change behavior.
143
- */
144
123
  function recordAgentEvent(config, event) {
145
124
  apiRequest("POST", "/api/telemetry/mcp-event", {
146
125
  config,
@@ -153,7 +132,6 @@ function recordAgentEvent(config, event) {
153
132
  source: "cli",
154
133
  },
155
134
  }).catch(() => {
156
- // Swallow — telemetry must never affect user-facing flow.
157
135
  });
158
136
  }
159
137
  function recordInstallEvent(config, event) {
@@ -169,14 +147,8 @@ function recordInstallEvent(config, event) {
169
147
  cliVersion: version_1.CLI_VERSION,
170
148
  },
171
149
  }).catch(() => {
172
- // Swallow — telemetry must never affect connect flow.
173
150
  });
174
151
  }
175
- /**
176
- * Wraps a CLI subcommand body so success and failure both record telemetry
177
- * and the original error propagates after the event is queued. Use this in
178
- * each `runXxx` command instead of inline timing + try/catch boilerplate.
179
- */
180
152
  async function withTelemetry(config, tool, fn) {
181
153
  const start = Date.now();
182
154
  try {
@@ -194,9 +166,6 @@ async function withTelemetry(config, tool, fn) {
194
166
  throw err;
195
167
  }
196
168
  }
197
- /**
198
- * Relative-time formatter for inbox / listing output.
199
- */
200
169
  function timeAgo(ts) {
201
170
  const diff = Date.now() - ts;
202
171
  const mins = Math.floor(diff / 60000);
@@ -210,10 +179,6 @@ function timeAgo(ts) {
210
179
  const days = Math.floor(hours / 24);
211
180
  return `${days}d ago`;
212
181
  }
213
- /**
214
- * Strip surrounding quotes from a CLI argument if the user wrapped it.
215
- * `codiedev ping <name> "hey"` on some shells passes the quotes through.
216
- */
217
182
  function stripQuotes(s) {
218
183
  if ((s.startsWith('"') && s.endsWith('"')) ||
219
184
  (s.startsWith("'") && s.endsWith("'"))) {
@@ -0,0 +1,344 @@
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.TRACES_HELP = void 0;
37
+ exports.slugify = slugify;
38
+ exports.casesBrief = casesBrief;
39
+ exports.resultsTemplate = resultsTemplate;
40
+ exports.runTraces = runTraces;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const shared_1 = require("./shared");
44
+ const tracesLabel_1 = require("./tracesLabel");
45
+ exports.TRACES_HELP = `
46
+ codiedev traces — test cases, scores, review queues and automatic scoring from Codiedev → Traces
47
+
48
+ codiedev traces agents Agents you maintain, with saved case counts
49
+ codiedev traces cases <agent> [--dataset name [--version n]] [--case id[,id]] [--model id] [--out dir] [--json]
50
+ Write an agent's cases (one dataset, or just
51
+ the cases named) into this repo, default
52
+ .codiedev/traces/<agent>[/<dataset>[/v<n>]]/, then
53
+ ask your coding agent to run them.
54
+ --model runs them on another model, e.g.
55
+ the replacement for a retiring one
56
+ codiedev traces report <results.json> [--harness name]
57
+ Send the filled-in results back, so
58
+ Traces shows the pass rate for that model
59
+
60
+ codiedev traces overview [--days n] [--json]
61
+ Every agent you can see: runs, failures,
62
+ spend, and what's going wrong most
63
+ codiedev traces runs <agent> [--failed] [--flag name] [--model id] [--verdict pass|fail] [--days n] [--limit n] [--json]
64
+ An agent's runs, newest first
65
+ codiedev traces run <run> [--agent name] [--json]
66
+ One run: steps, what went wrong and the fix,
67
+ scores, prompts and replies (maintainers)
68
+ codiedev traces score-kinds [add <name> --type number|categories|boolean [--min n --max n] [--categories a,b]]
69
+ List or add the kinds of score your team uses
70
+ codiedev traces queue create <name> [--scores a,b] [--description text]
71
+ codiedev traces score <run> <score> <value> [--agent name] [--comment text] [--step n]
72
+ Score a run (a portal run id agent~run, or
73
+ the agent's own run id with --agent)
74
+ codiedev traces scores <agent> [--days n] [--json]
75
+ Each score's average or mix, and the score kinds
76
+ codiedev traces queue list Review queues and how many are left
77
+ codiedev traces queue add <queue> --agent <name> [--failed] [--days n] [--run id ...]
78
+ File runs into a queue for people to review
79
+ codiedev traces judge <agent> [--on | --off] [--scores a,b] [--instructions text]
80
+ [--model id] [--sample percent] [--daily n] [--budget usd | --key cdvm_…]
81
+ Show or set automatic scoring (a judge model
82
+ scores a sample of runs, billed to your key)
83
+ codiedev traces import <agent> <file.csv|file.jsonl> --dataset <name>
84
+ Add examples from a file (input, expected, name)
85
+ codiedev traces add-example <agent> --dataset <name> --input <text> [--expected <text>] [--name <text>]
86
+ codiedev traces versions <dataset> A dataset's saved versions and what changed
87
+ codiedev traces save-version <dataset> [--note text]
88
+ Save the dataset as its next version
89
+
90
+ <agent> is the agent's name (its API key name) or id. Only an agent's
91
+ maintainers can pull its cases or report on them.
92
+ `.trim();
93
+ const FLAG_LABEL = {
94
+ budget_block: "refused for budget",
95
+ errors: "model call failed",
96
+ tool_loop: "repeated the same tool call",
97
+ truncated: "reply cut off at max_tokens",
98
+ context_overflow: "prompt over 70% of the context window",
99
+ };
100
+ const TRIES = 3;
101
+ const plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
102
+ const recordedModel = (res) => res.cases.flatMap((c) => c.steps.map((s) => s.model)).filter(Boolean)[0] ?? "the agent's current model";
103
+ function slugify(name) {
104
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
105
+ }
106
+ function casesBrief(res, casesFile, opts = {}) {
107
+ const fix = res.cases.filter((c) => c.kind === "fix");
108
+ const keep = res.cases.filter((c) => c.kind === "keep");
109
+ const withBodies = res.cases.filter((c) => c.steps.some((s) => s.request)).length;
110
+ const target = opts.model;
111
+ const results = opts.resultsFile ? path.basename(opts.resultsFile) : "results.json";
112
+ const lines = [
113
+ `# Test cases for ${res.agent.name}${res.suite ? ` · ${res.suite}` : ""}${res.version ? ` v${res.version}` : ""}${target ? ` on ${target}` : ""}`,
114
+ "",
115
+ res.agent.description ? `${res.agent.description}\n` : "",
116
+ `Saved from Codiedev → Traces. ${plural(res.cases.length, "case")} in \`${path.basename(casesFile)}\` (one JSON object per line):`,
117
+ `- **${fix.length} to fix**: production runs that failed. The fix should make them pass.`,
118
+ `- **${keep.length} to keep passing**: good runs. They should still pass after any change.`,
119
+ "",
120
+ ];
121
+ if (target) {
122
+ lines.push("## This is a model check", "", `Run every case on **${target}** instead of ${recordedModel(res)} (the model the cases were recorded on). Change only the model the agent asks the gateway for; keep its prompts and tools as they are, so the result says how ${target} does on the same work.`, "");
123
+ }
124
+ lines.push("## How to run them", "", "1. Find where this agent builds its model requests and calls the Codiedev gateway.", `2. For each case, replay \`steps[0].request\` (the first prompt the agent sent) through the agent's own code path, so tools and prompts are the current version, not the recorded one${target ? `, with the model set to ${target}` : ""}.`, "3. Judge each try against the case:", " - A case's `expected`, when present, is what a passing answer looks like (a reference reply or criteria). It wins over everything below.", " - `fix` cases: the run must not reproduce its `flags` (listed below), and must finish (no failed call, no `finish_reason: \"length\"`, no repeated identical tool call).", " - `keep` cases: the final reply must still do what the recorded final reply did. Compare meaning, not wording.", " - A case's `note`, when present, is the engineer's extra context.", " - Cases whose `runId` starts with `manual:` or `import:` were written by hand, not recorded: `steps[0].request` is the input and there's no recorded reply, so judge them on `expected`.");
125
+ if (res.judge?.model || res.judge?.rubric) {
126
+ lines.push(` - Where passing needs judgement, judge with **${res.judge.model ?? "a strong model"}** through the gateway${res.judge.rubric ? `, using this rubric: "${res.judge.rubric}"` : ""}. Use the same judge for every model so results compare.`);
127
+ }
128
+ lines.push(`4. Run each case ${TRIES} times: agents are stochastic, so report a pass rate per case, not a single result.`, `5. Fill in \`${results}\`: for each case set \`passes\` (out of \`tries\`), \`output\` (the agent's final reply on one try, so it can be compared side by side with other models) and a one-line \`note\` on any failure. Set \`harness\` to the coding agent you are (claude-code, codex, cursor, copilot, …).`, `6. Send it back: \`codiedev traces report ${opts.resultsFile ? path.relative(process.cwd(), opts.resultsFile) || results : results}\`. Then show a table: case, kind, passes out of ${TRIES}, and the failure note.`, "", "Send real model calls through the gateway with the agent's usual key and `X-Codiedev-Run-Id: case-<id>-<try>`, so the replays show up in Traces too.", "");
129
+ if (withBodies < res.cases.length) {
130
+ lines.push(`Note: ${plural(res.cases.length - withBodies, "case")} ${res.cases.length - withBodies === 1 ? "has" : "have"} no recorded prompt (the agent wasn't keeping prompts then). For those, rebuild the input from the case's \`expected\` or \`note\`, or skip them and say so.`, "");
131
+ }
132
+ lines.push("## Cases", "");
133
+ for (const c of res.cases) {
134
+ const flags = c.flags.length ? c.flags.map((f) => FLAG_LABEL[f] ?? f).join(", ") : "no flags";
135
+ lines.push(`- \`${c.id}\` · ${c.name} · ${c.kind} · ${flags} · ${plural(c.steps.length, "model call")}${c.expected ? ` · expected: "${c.expected.replace(/\s+/g, " ").slice(0, 200)}"` : ""}${c.note ? ` · note: "${c.note}"` : ""}`);
136
+ }
137
+ return lines.filter((line, i, all) => !(line === "" && all[i - 1] === "")).join("\n") + "\n";
138
+ }
139
+ function resultsTemplate(res, model) {
140
+ return {
141
+ agent: res.agent.name,
142
+ suite: res.suite,
143
+ ...(res.version ? { version: res.version } : {}),
144
+ model: model ?? recordedModel(res),
145
+ judgeModel: res.judge?.model ?? null,
146
+ harness: null,
147
+ results: res.cases.map((c) => ({ caseId: c.id, name: c.name, passes: null, tries: TRIES, note: null, output: null })),
148
+ };
149
+ }
150
+ function flag(args, i, name) {
151
+ const a = args[i];
152
+ if (a === name && i + 1 < args.length)
153
+ return { value: args[i + 1], skip: 1 };
154
+ if (a.startsWith(`${name}=`))
155
+ return { value: a.slice(name.length + 1), skip: 0 };
156
+ return { skip: -1 };
157
+ }
158
+ function parseCasesArgs(args) {
159
+ const parsed = { json: false };
160
+ for (let i = 0; i < args.length; i++) {
161
+ const a = args[i];
162
+ let matched = false;
163
+ for (const [name, key] of [["--out", "out"], ["-o", "out"], ["--dataset", "suite"], ["--suite", "suite"], ["--model", "model"], ["--case", "caseIds"], ["--version", "version"]]) {
164
+ const f = flag(args, i, name);
165
+ if (f.skip >= 0) {
166
+ parsed[key] = f.value;
167
+ i += f.skip;
168
+ matched = true;
169
+ break;
170
+ }
171
+ }
172
+ if (matched)
173
+ continue;
174
+ if (a === "--json")
175
+ parsed.json = true;
176
+ else if (!a.startsWith("-") && !parsed.agent)
177
+ parsed.agent = a;
178
+ }
179
+ return parsed;
180
+ }
181
+ async function runAgents(config) {
182
+ const start = Date.now();
183
+ let res;
184
+ try {
185
+ res = await (0, shared_1.apiRequest)("GET", "/api/cli/traces/agents", { config });
186
+ }
187
+ catch (err) {
188
+ const e = err;
189
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_agents", ok: false, latencyMs: Date.now() - start, error: e.message });
190
+ console.error(`Couldn't list agents: ${e.message}`);
191
+ process.exit(1);
192
+ }
193
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_agents", ok: true, latencyMs: Date.now() - start });
194
+ if (!res.agents.length) {
195
+ console.log("You don't maintain any agents yet. Connect one in Codiedev → Traces → How it works.");
196
+ return;
197
+ }
198
+ for (const agent of res.agents) {
199
+ const capture = agent.promptDays ? `prompts kept ${agent.promptDays} days` : "metadata only";
200
+ console.log(`${agent.name.padEnd(28)} ${plural(agent.cases, "case").padStart(9)} ${capture}`);
201
+ }
202
+ console.log("\nPull one: codiedev traces cases <agent>");
203
+ }
204
+ async function runCases(args, config) {
205
+ const { agent, suite, model, caseIds, version, out, json } = parseCasesArgs(args);
206
+ if (!agent) {
207
+ console.error("Usage: codiedev traces cases <agent> [--dataset name [--version n]] [--model id] [--out dir] [--json]");
208
+ process.exit(1);
209
+ }
210
+ if (version !== undefined && (!suite || !/^[1-9]\d*$/.test(version))) {
211
+ console.error("--version takes a whole number and needs --dataset: codiedev traces cases <agent> --dataset <name> --version <n>");
212
+ process.exit(1);
213
+ }
214
+ const start = Date.now();
215
+ let res;
216
+ try {
217
+ res = await (0, shared_1.apiRequest)("GET", "/api/cli/traces/cases", { config, query: { agent, ...(suite ? { suite } : {}), ...(version ? { version } : {}), ...(caseIds ? { case: caseIds } : {}) } });
218
+ }
219
+ catch (err) {
220
+ const e = err;
221
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_cases", ok: false, latencyMs: Date.now() - start, error: e.message });
222
+ if (e.status === 404 && version && /No version/.test(e.message))
223
+ console.error(`No version ${version} of "${suite}". See its versions in Codiedev → Traces → Test cases.`);
224
+ else if (e.status === 404)
225
+ console.error(`No agent called "${agent}". See your agents with: codiedev traces agents`);
226
+ else if (e.status === 403)
227
+ console.error(`Only ${agent}'s maintainers can pull its test cases.`);
228
+ else
229
+ console.error(`Couldn't pull cases: ${e.message}`);
230
+ process.exit(1);
231
+ }
232
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_cases", ok: true, latencyMs: Date.now() - start });
233
+ if (json) {
234
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
235
+ return;
236
+ }
237
+ if (!res.cases.length) {
238
+ console.log(suite
239
+ ? `${res.agent.name} has no test cases in "${suite}". See your datasets in Codiedev → Traces → Test cases.`
240
+ : `${res.agent.name} has no saved test cases. Open a run in Codiedev → Traces and click "Save as test case".`);
241
+ return;
242
+ }
243
+ const dir = path.resolve(process.cwd(), out ?? path.join(".codiedev", "traces", slugify(res.agent.name), ...(res.suite ? [slugify(res.suite)] : []), ...(res.version ? [`v${res.version}`] : []), ...(caseIds && res.cases.length === 1 ? [slugify(res.cases[0].name)] : []), ...(model ? [slugify(model)] : [])));
244
+ fs.mkdirSync(dir, { recursive: true });
245
+ const casesFile = path.join(dir, "cases.jsonl");
246
+ fs.writeFileSync(casesFile, res.cases.map((c) => JSON.stringify(c)).join("\n") + "\n", "utf8");
247
+ const resultsFile = path.join(dir, "results.json");
248
+ fs.writeFileSync(resultsFile, JSON.stringify(resultsTemplate(res, model), null, 2) + "\n", "utf8");
249
+ const briefFile = path.join(dir, "RUN_CASES.md");
250
+ fs.writeFileSync(briefFile, casesBrief(res, casesFile, { model, resultsFile }), "utf8");
251
+ const fix = res.cases.filter((c) => c.kind === "fix").length;
252
+ const rel = (file) => path.relative(process.cwd(), file) || file;
253
+ console.log(`✓ ${plural(res.cases.length, "case")} for ${res.agent.name}${res.suite ? ` · ${res.suite}` : ""}${res.version ? ` v${res.version}` : ""}${model ? ` on ${model}` : ""} (${fix} to fix, ${res.cases.length - fix} to keep passing)`);
254
+ if (res.missing)
255
+ console.log(` ${plural(res.missing, "case")} in v${res.version} were deleted since and can't be pulled.`);
256
+ console.log(` ${rel(casesFile)}`);
257
+ console.log(` ${rel(briefFile)}`);
258
+ console.log(` ${rel(resultsFile)} (filled in by your coding agent, then: codiedev traces report ${rel(resultsFile)})`);
259
+ console.log(`\nNext: ask your coding agent to "run the test cases in ${rel(briefFile)}"`);
260
+ }
261
+ async function runReport(args, config) {
262
+ let file;
263
+ let harness;
264
+ for (let i = 0; i < args.length; i++) {
265
+ const f = flag(args, i, "--harness");
266
+ if (f.skip >= 0) {
267
+ harness = f.value;
268
+ i += f.skip;
269
+ continue;
270
+ }
271
+ if (!args[i].startsWith("-") && !file)
272
+ file = args[i];
273
+ }
274
+ if (!file) {
275
+ console.error("Usage: codiedev traces report <results.json> [--harness name]");
276
+ process.exit(1);
277
+ }
278
+ let body;
279
+ try {
280
+ body = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), file), "utf8"));
281
+ }
282
+ catch (err) {
283
+ console.error(`Couldn't read ${file}: ${err.message}`);
284
+ process.exit(1);
285
+ }
286
+ const missing = body.results.filter((r) => typeof r.passes !== "number");
287
+ if (missing.length) {
288
+ console.error(`${plural(missing.length, "case")} in ${file} ${missing.length === 1 ? "has" : "have"} no "passes" yet: ${missing.slice(0, 5).map((r) => r.name).join(", ")}. Run them first.`);
289
+ process.exit(1);
290
+ }
291
+ const start = Date.now();
292
+ try {
293
+ const res = await (0, shared_1.apiRequest)("POST", "/api/cli/traces/results", {
294
+ config,
295
+ body: { ...body, harness: harness ?? body.harness ?? undefined },
296
+ });
297
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_report", ok: true, latencyMs: Date.now() - start });
298
+ const passed = body.results.filter((r) => r.passes === r.tries).length;
299
+ console.log(`✓ Reported ${body.agent}${body.suite ? ` · ${body.suite}` : ""} on ${body.model}: ${Math.round(res.passRate * 100)}% of tries passed, ${passed}/${body.results.length} cases passed every try.`);
300
+ console.log(" See it next to other models in Codiedev → Traces → Test cases.");
301
+ }
302
+ catch (err) {
303
+ const e = err;
304
+ (0, shared_1.recordAgentEvent)(config, { tool: "codiedev_traces_report", ok: false, latencyMs: Date.now() - start, error: e.message });
305
+ console.error(e.status === 403 ? `Only ${body.agent}'s maintainers can report its results.` : `Couldn't report: ${e.message}`);
306
+ process.exit(1);
307
+ }
308
+ }
309
+ async function runTraces(args, configOverride) {
310
+ const [sub, ...rest] = args;
311
+ if (sub === "agents")
312
+ return runAgents(configOverride ?? (0, shared_1.requireConfig)());
313
+ if (sub === "cases")
314
+ return runCases(rest, configOverride ?? (0, shared_1.requireConfig)());
315
+ if (sub === "report")
316
+ return runReport(rest, configOverride ?? (0, shared_1.requireConfig)());
317
+ if (sub === "overview")
318
+ return (0, tracesLabel_1.runOverview)(rest, configOverride ?? (0, shared_1.requireConfig)());
319
+ if (sub === "runs")
320
+ return (0, tracesLabel_1.runRuns)(rest, configOverride ?? (0, shared_1.requireConfig)());
321
+ if (sub === "run")
322
+ return (0, tracesLabel_1.runRun)(rest, configOverride ?? (0, shared_1.requireConfig)());
323
+ if (sub === "score-kinds")
324
+ return (0, tracesLabel_1.runScoreKinds)(rest, configOverride ?? (0, shared_1.requireConfig)());
325
+ if (sub === "score")
326
+ return (0, tracesLabel_1.runScore)(rest, configOverride ?? (0, shared_1.requireConfig)());
327
+ if (sub === "scores")
328
+ return (0, tracesLabel_1.runScores)(rest, configOverride ?? (0, shared_1.requireConfig)());
329
+ if (sub === "queue")
330
+ return (0, tracesLabel_1.runQueue)(rest, configOverride ?? (0, shared_1.requireConfig)());
331
+ if (sub === "judge")
332
+ return (0, tracesLabel_1.runJudge)(rest, configOverride ?? (0, shared_1.requireConfig)());
333
+ if (sub === "import")
334
+ return (0, tracesLabel_1.runImport)(rest, configOverride ?? (0, shared_1.requireConfig)());
335
+ if (sub === "add-example")
336
+ return (0, tracesLabel_1.runAddExample)(rest, configOverride ?? (0, shared_1.requireConfig)());
337
+ if (sub === "versions")
338
+ return (0, tracesLabel_1.runVersions)(rest, configOverride ?? (0, shared_1.requireConfig)());
339
+ if (sub === "save-version")
340
+ return (0, tracesLabel_1.runSaveVersion)(rest, configOverride ?? (0, shared_1.requireConfig)());
341
+ console.log(exports.TRACES_HELP);
342
+ if (sub && sub !== "help")
343
+ process.exit(1);
344
+ }