@erdoai/cli 0.48.0 → 0.49.1

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 +73 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -547,6 +547,7 @@ var ErdoClient = class {
547
547
  const q = new URLSearchParams();
548
548
  for (const s of params?.statuses ?? []) q.append("statuses", s);
549
549
  if (params?.engine_actions_only) q.set("engine_actions_only", "true");
550
+ if (params?.item_id) q.set("item_id", params.item_id);
550
551
  if (params?.limit) q.set("limit", String(params.limit));
551
552
  if (params?.offset) q.set("offset", String(params.offset));
552
553
  const qs = q.toString();
@@ -901,6 +902,13 @@ var ErdoClient = class {
901
902
  `/v1/approvals${qs ? `?${qs}` : ""}`
902
903
  );
903
904
  }
905
+ // One request in full — the itemized projection, the recorded reason, and the
906
+ // scope options a decision is made against, where the list is sized for
907
+ // scanning. A request belonging to another organization reads as 404, so an id
908
+ // cannot be probed for existence.
909
+ getApproval(id) {
910
+ return this.request("GET", `/v1/approvals/${encodeURIComponent(id)}`);
911
+ }
904
912
  decideApproval(id, input) {
905
913
  return this.request(
906
914
  "POST",
@@ -1257,6 +1265,7 @@ function awaitingApprovalMessage(threadID) {
1257
1265
  return [
1258
1266
  "the run paused for approval.",
1259
1267
  " erdo approvals list --status pending",
1268
+ " erdo approvals show <id>",
1260
1269
  " erdo approvals decide <id> --approve",
1261
1270
  ` erdo agent wait ${threadID}`
1262
1271
  ].join("\n");
@@ -1713,7 +1722,7 @@ wsCmd.command("arm <slug>").description("Arm the recurring reconciliation loop (
1713
1722
  }
1714
1723
  );
1715
1724
  wsCmd.command("ledger <slug>").description(
1716
- "Read the allocator's single ledger view \u2014 budget, experiments + observations, judge calibration, attention items, allocator recommendation"
1725
+ "Read the allocator's single ledger view \u2014 budget, experiments + observations, judge calibration, the decisions currently in force, attention items, allocator recommendation"
1717
1726
  ).option("--observations <n>", "observations to include per experiment", (v) => parseInt(v, 10)).action(async (slug, opts) => {
1718
1727
  try {
1719
1728
  print(await new ErdoClient().readWorkstreamLedger(slug, opts.observations));
@@ -2457,6 +2466,67 @@ approvalsCmd.command("list").description("List approval requests, optionally fil
2457
2466
  }
2458
2467
  }
2459
2468
  );
2469
+ function renderApproval(r) {
2470
+ console.log(r.action_headline || r.action_display);
2471
+ const facts = [["status", r.status]];
2472
+ if (r.decision_class) facts.push(["decision", r.decision_class]);
2473
+ if (r.subject_display_name) {
2474
+ facts.push(["subject", r.subject_display_name]);
2475
+ } else if (r.subject_resource_type && r.subject_resource_id) {
2476
+ facts.push(["subject", `${r.subject_resource_type} ${r.subject_resource_id}`]);
2477
+ }
2478
+ if (r.occurrence_count && r.occurrence_count > 1) {
2479
+ facts.push([
2480
+ "proposed",
2481
+ `${r.occurrence_count}\xD7 since ${r.first_proposed_at ?? r.created_at}`
2482
+ ]);
2483
+ }
2484
+ facts.push(["created", r.created_at]);
2485
+ if (r.decided_at) facts.push(["decided", r.decided_at]);
2486
+ if (r.expires_at) facts.push(["expires", r.expires_at]);
2487
+ for (const [label, value] of facts) {
2488
+ console.log(` ${label.padEnd(9)} ${value}`);
2489
+ }
2490
+ if (r.action_context) {
2491
+ console.log("");
2492
+ console.log(`Reason: ${r.action_context}`);
2493
+ }
2494
+ const items = r.action_items ?? [];
2495
+ if (items.length) {
2496
+ console.log("");
2497
+ console.log(items.length === 1 ? "Action:" : `Actions (${items.length}):`);
2498
+ items.forEach((item, i) => {
2499
+ console.log(` ${i + 1}. ${item.what}`);
2500
+ if (item.why) console.log(` why: ${item.why}`);
2501
+ for (const [key, value] of Object.entries(item.params_compact ?? {})) {
2502
+ console.log(` ${key}: ${value}`);
2503
+ }
2504
+ });
2505
+ }
2506
+ if (r.omitted_items && r.omitted_items > 0) {
2507
+ console.log(` \u2026 and ${r.omitted_items} more actions`);
2508
+ }
2509
+ const options = r.scope_options ?? [];
2510
+ if (options.length) {
2511
+ console.log("");
2512
+ console.log("Scope options (`erdo approvals decide --option N`):");
2513
+ options.forEach((o, i) => console.log(` ${i + 1}. ${o.label}`));
2514
+ }
2515
+ }
2516
+ approvalsCmd.command("show <id>").description(
2517
+ "Show one approval request in full: the outcome headline, the actions it covers with the reason each was proposed, the subject it acts on, and the scope options a standing decision can use"
2518
+ ).option("--json", "output raw JSON").action(async (id, opts) => {
2519
+ try {
2520
+ const req = await new ErdoClient().getApproval(id);
2521
+ if (opts.json) {
2522
+ print(req);
2523
+ return;
2524
+ }
2525
+ renderApproval(req);
2526
+ } catch (e) {
2527
+ fail(e);
2528
+ }
2529
+ });
2460
2530
  approvalsCmd.command("decide <id>").description("Approve or reject a pending approval request").option("--approve", "approve the request").option("--reject", "reject the request").option(
2461
2531
  "--scope <scope>",
2462
2532
  "once (default) | always_this_job | always_this_workstream | always_org | always_user",
@@ -2513,7 +2583,7 @@ ${listing}`);
2513
2583
  }
2514
2584
  );
2515
2585
  var attnCmd = program.command("attention").description("The attention feed \u2014 digests, choices, escalations awaiting a human");
2516
- 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("-n, --limit <n>", "max items", (v) => parseInt(v, 10)).option("--offset <n>", "pagination offset", (v) => parseInt(v, 10)).action(
2586
+ 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(
2517
2587
  async (opts) => {
2518
2588
  try {
2519
2589
  const statuses = opts.status?.length ? opts.status : opts.open ? ["open"] : void 0;
@@ -2521,6 +2591,7 @@ attnCmd.command("list").description("List attention items").option("--status <st
2521
2591
  await new ErdoClient().listAttentionItems({
2522
2592
  statuses,
2523
2593
  engine_actions_only: opts.engineActions,
2594
+ item_id: opts.item,
2524
2595
  limit: opts.limit,
2525
2596
  offset: opts.offset
2526
2597
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erdoai/cli",
3
- "version": "0.48.0",
3
+ "version": "0.49.1",
4
4
  "description": "Erdo CLI — drive datasets, pages, and evals from the terminal or CI",
5
5
  "type": "module",
6
6
  "bin": {