@erdoai/cli 0.62.0 → 0.64.0

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 (2) hide show
  1. package/dist/index.js +101 -4
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -269,6 +269,15 @@ var ErdoClient = class {
269
269
  setAutonomyMode(mode) {
270
270
  return this.request("PUT", "/v1/autonomy-mode", { mode });
271
271
  }
272
+ // Personal approval settings — which risk classes of the caller's OWN agent
273
+ // runs still raise a card in the active org. gates null = no personal
274
+ // setting (org default); [] = nothing asks; otherwise the listed classes ask.
275
+ getApprovalSettings() {
276
+ return this.request("GET", "/v1/approval-settings");
277
+ }
278
+ setApprovalSettings(gates) {
279
+ return this.request("PUT", "/v1/approval-settings", { gates });
280
+ }
272
281
  // --- Manager accounts: operate many client (managed) orgs with ONE manager key ---
273
282
  // The manager is your active org; you must be an admin/owner of it. A managed org
274
283
  // is a client tenant you provision and operate. The manager key (createManagerKey)
@@ -409,7 +418,7 @@ var ErdoClient = class {
409
418
  `/v1/evals/suites/${encodeURIComponent(slug)}/cases/${encodeURIComponent(caseName)}`
410
419
  );
411
420
  }
412
- runEvalSuite(slug, concurrency, commitSha, frontendCommitSha, backendCommitSha, source) {
421
+ runEvalSuite(slug, concurrency, commitSha, frontendCommitSha, backendCommitSha, source, modelOverride) {
413
422
  return this.request(
414
423
  "POST",
415
424
  `/v1/evals/suites/${encodeURIComponent(slug)}/run`,
@@ -418,10 +427,15 @@ var ErdoClient = class {
418
427
  commit_sha: commitSha,
419
428
  frontend_commit_sha: frontendCommitSha,
420
429
  backend_commit_sha: backendCommitSha,
421
- source
430
+ source,
431
+ model_override: modelOverride
422
432
  }
423
433
  );
424
434
  }
435
+ getEvalLeaderboard(slug, days) {
436
+ const q = days && days > 0 ? `?days=${days}` : "";
437
+ return this.request("GET", `/v1/evals/leaderboard/${encodeURIComponent(slug)}${q}`);
438
+ }
425
439
  getEvalRun(runID) {
426
440
  return this.request(
427
441
  "GET",
@@ -2424,7 +2438,7 @@ evalCmd.command("create <name>").description("Create a suite (in the active org)
2424
2438
  }
2425
2439
  }
2426
2440
  );
2427
- evalCmd.command("run <slug>").description("Run a suite; --watch polls until it completes").option("-w, --watch", "poll until the run finishes and print results").option("-c, --concurrency <n>", "parallel cases", (v) => parseInt(v, 10)).option("--commit-sha <sha>", "full 40-character Git commit SHA to associate with the run").option("--frontend-commit-sha <sha>", "frontend revision in the evaluated production snapshot").option("--backend-commit-sha <sha>", "backend revision in the evaluated production snapshot").option("--source <source>", "staff-only run source: post_deploy, nightly, or rollback").action(async (slug, opts) => {
2441
+ evalCmd.command("run <slug>").description("Run a suite; --watch polls until it completes").option("-w, --watch", "poll until the run finishes and print results").option("-c, --concurrency <n>", "parallel cases", (v) => parseInt(v, 10)).option("--commit-sha <sha>", "full 40-character Git commit SHA to associate with the run").option("--frontend-commit-sha <sha>", "frontend revision in the evaluated production snapshot").option("--backend-commit-sha <sha>", "backend revision in the evaluated production snapshot").option("--source <source>", "staff-only run source: post_deploy, nightly, or rollback").option("--model <model>", "pin the suite's agent to a model for this run (e.g. glm-5.3) \u2014 for model comparisons").action(async (slug, opts) => {
2428
2442
  try {
2429
2443
  const api = new ErdoClient();
2430
2444
  const { suite } = await api.getEvalSuite(slug);
@@ -2446,7 +2460,8 @@ evalCmd.command("run <slug>").description("Run a suite; --watch polls until it c
2446
2460
  opts.commitSha,
2447
2461
  opts.frontendCommitSha,
2448
2462
  opts.backendCommitSha,
2449
- opts.source
2463
+ opts.source,
2464
+ opts.model
2450
2465
  );
2451
2466
  console.log(`run_id: ${run_id}`);
2452
2467
  if (!opts.watch) return;
@@ -2472,6 +2487,44 @@ ${run.status}: ${run.passed_cases}/${run.total_cases} passed, avg ${run.avg_scor
2472
2487
  fail(e);
2473
2488
  }
2474
2489
  });
2490
+ evalCmd.command("leaderboard <slug>").description("Model-comparison table for a suite: cases as rows, models as columns").option("-d, --days <n>", "window in days (default: all time)", (v) => parseInt(v, 10)).action(async (slug, opts) => {
2491
+ try {
2492
+ const res = await new ErdoClient().getEvalLeaderboard(slug, opts.days);
2493
+ if (res.models.length === 0) {
2494
+ console.log(`No completed runs found for "${slug}"${opts.days ? ` in the last ${opts.days} days` : ""}.`);
2495
+ return;
2496
+ }
2497
+ const modelCol = (m) => m.padEnd(18);
2498
+ console.log(`
2499
+ ${"Case".padEnd(34)}${res.models.map(modelCol).join("")}`);
2500
+ console.log("-".repeat(34 + 18 * res.models.length));
2501
+ for (const row of res.rows) {
2502
+ const byModel = new Map(row.cells.map((c) => [c.model, c]));
2503
+ let line = row.case_name.slice(0, 33).padEnd(34);
2504
+ for (const m of res.models) {
2505
+ const c = byModel.get(m);
2506
+ line += c ? `${c.avg_score.toFixed(1)} (${Math.round(c.pass_rate * 100)}%)\xD7${c.n}`.padEnd(18) : "\xB7".padEnd(18);
2507
+ }
2508
+ console.log(line);
2509
+ }
2510
+ console.log(`
2511
+ ${"Summary (avg of all cases)".padEnd(34)}${res.models.map(modelCol).join("")}`);
2512
+ for (const stat of ["score", "pass", "cost", "secs"]) {
2513
+ let line = `${" " + stat}`.padEnd(34);
2514
+ for (const s of res.summary) {
2515
+ const v = stat === "score" ? s.avg_score.toFixed(2) : stat === "pass" ? `${Math.round(s.pass_rate * 100)}%` : stat === "cost" ? `$${(s.avg_cost_millicents / 1e5).toFixed(3)}/case` : `${(s.avg_duration_ms / 1e3).toFixed(0)}s`;
2516
+ line += v.padEnd(18);
2517
+ }
2518
+ console.log(line);
2519
+ }
2520
+ console.log(
2521
+ `
2522
+ Cell = avg score (pass rate) \xD7 runs. Cost is recorded judge cost per case; agent cost rides the run's tokens. "(unrec.)" = rows predating per-model capture.`
2523
+ );
2524
+ } catch (e) {
2525
+ fail(e);
2526
+ }
2527
+ });
2475
2528
  evalCmd.command("results <runId>").description("Show a run's results").option("--json", "print the full JSON").action(async (runId, opts) => {
2476
2529
  try {
2477
2530
  const data = await new ErdoClient().getEvalRun(runId);
@@ -3109,6 +3162,50 @@ ${listing}`);
3109
3162
  }
3110
3163
  }
3111
3164
  );
3165
+ approvalsCmd.command("settings [mode]").description(
3166
+ "Show or set YOUR approval settings: which classes of your agents' actions still ask. mode: safe (auto-approve page work + bookkeeping; spend and destructive still ask) | all (approve everything) | reset (back to the org default)"
3167
+ ).option(
3168
+ "--gates <classes>",
3169
+ "explicit comma-separated gate list, e.g. spend,destructive (overrides <mode>)"
3170
+ ).action(async (mode, opts = {}) => {
3171
+ try {
3172
+ const client = new ErdoClient();
3173
+ let gates;
3174
+ if (opts.gates !== void 0) {
3175
+ gates = opts.gates.split(",").map((g) => g.trim()).filter(Boolean);
3176
+ } else {
3177
+ switch (mode) {
3178
+ case void 0:
3179
+ break;
3180
+ // show
3181
+ case "safe":
3182
+ gates = ["spend", "destructive"];
3183
+ break;
3184
+ case "all":
3185
+ gates = [];
3186
+ break;
3187
+ case "reset":
3188
+ gates = null;
3189
+ break;
3190
+ default:
3191
+ throw new Error(`unknown mode ${mode} \u2014 use safe | all | reset, or --gates spend,destructive`);
3192
+ }
3193
+ }
3194
+ if (gates !== void 0) {
3195
+ await client.setApprovalSettings(gates);
3196
+ }
3197
+ const { gates: current } = await client.getApprovalSettings();
3198
+ if (current === null) {
3199
+ console.log("Approval settings: org default (every gated action asks, subject to the org's own gates and standing policies)");
3200
+ } else if (current.length === 0) {
3201
+ console.log("Approval settings: approve everything \u2014 no class of your agents' actions asks (a standing always-require policy still applies)");
3202
+ } else {
3203
+ console.log(`Approval settings: ${current.join(", ")} still ask; the rest of your agents' actions auto-approve`);
3204
+ }
3205
+ } catch (e) {
3206
+ fail(e);
3207
+ }
3208
+ });
3112
3209
  var attnCmd = program.command("attention").description("The attention feed \u2014 digests, choices, escalations awaiting a human");
3113
3210
  attnCmd.command("list").description("List attention items").option("--status <status...>", "open | answered | dismissed | expired").option("--open", "shorthand for --status open").option("--engine-actions", "only engine-generated items").option("--item <idOrSlug>", "read one item: its slug or its uuid").option("-n, --limit <n>", "max items", (v) => parseInt(v, 10)).option("--offset <n>", "pagination offset", (v) => parseInt(v, 10)).action(
3114
3211
  async (opts) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.62.0",
4
- "description": "Erdo CLI \u2014 drive datasets, pages, and evals from the terminal or CI",
3
+ "version": "0.64.0",
4
+ "description": "Erdo CLI drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "erdo": "dist/index.js"
@@ -52,4 +52,4 @@
52
52
  "overrides": {
53
53
  "esbuild": "^0.28.1"
54
54
  }
55
- }
55
+ }