@datarails-ai/dr-cli 1.6.180 → 1.6.182

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 CHANGED
@@ -8,7 +8,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@datarails-ai/dr-cli",
11
- version: "1.6.180",
11
+ version: "1.6.182",
12
12
  description: "Datarails CLI",
13
13
  type: "module",
14
14
  engines: {
@@ -40,7 +40,7 @@ var package_default = {
40
40
  postinstall: "node scripts/postinstall.mjs"
41
41
  },
42
42
  dependencies: {
43
- "@datarails-ai/dr-appspace-cli": "0.12.57",
43
+ "@datarails-ai/dr-appspace-cli": "0.12.58",
44
44
  "@modelcontextprotocol/sdk": "^1.29.0",
45
45
  "@napi-rs/keyring": "^1.3.0",
46
46
  commander: "^12.1.0",
@@ -69,7 +69,7 @@ var package_default = {
69
69
  };
70
70
 
71
71
  // src/buildInfo.ts
72
- var BUILD_TIME = "2026-11-01T08:20:54.123Z";
72
+ var BUILD_TIME = "2026-11-01T16:01:03.304Z";
73
73
  function formatBuildTime(iso) {
74
74
  if (iso === "") return "";
75
75
  const d = new Date(iso);
@@ -1410,11 +1410,11 @@ function exchangeForSession(store, serverKey, email, session, host, opts) {
1410
1410
  if (err.throttled && cachedIsUsable) return session;
1411
1411
  if (err.transient) {
1412
1412
  if (cachedIsUsable) return session;
1413
- const delay = API_KEY_EXCHANGE_RETRY_DELAYS_MS[attempt];
1414
- if (delay !== void 0) {
1413
+ const delay2 = API_KEY_EXCHANGE_RETRY_DELAYS_MS[attempt];
1414
+ if (delay2 !== void 0) {
1415
1415
  attempt += 1;
1416
1416
  try {
1417
- await sleep(delay, void 0, { signal });
1417
+ await sleep(delay2, void 0, { signal });
1418
1418
  } catch {
1419
1419
  throw new SessionExpiredError(
1420
1420
  `${identity2} (api-key exchange ended before its retry)`
@@ -4438,6 +4438,13 @@ var PROD_GATE_TIER_A = /* @__PURE__ */ new Set([
4438
4438
  "category|delete",
4439
4439
  // calc-models
4440
4440
  "calcmodel|delete",
4441
+ // dr calcmodels agent approve — activates an AGENT model's newest version and starts its
4442
+ // first production run, which writes new rows into a table that reports read. Unlike
4443
+ // `set-flow` / `recalculate` (Tier B), which re-run a model already approved, this puts
4444
+ // numbers nobody has run before into production, so a person confirms it. The plan
4445
+ // prints the version and its impact (rows, pool, allocated, coverage); the token binds
4446
+ // that version.
4447
+ "calcmodel|approve",
4441
4448
  // filebox
4442
4449
  "filebox|archive",
4443
4450
  "filebox-data-query|clear",
@@ -7421,8 +7428,8 @@ async function retryAsync(fn, opts) {
7421
7428
  const kind = classifyFailure(err);
7422
7429
  const retryable = kind === "transient" || kind !== "abort" && opts.alsoRetry?.(err) === true;
7423
7430
  if (!retryable || attempt > retries) throw err;
7424
- const delay = opts.delayMs ?? defaultBackoffMs;
7425
- const waitMs = typeof delay === "function" ? delay(attempt) : delay;
7431
+ const delay2 = opts.delayMs ?? defaultBackoffMs;
7432
+ const waitMs = typeof delay2 === "function" ? delay2(attempt) : delay2;
7426
7433
  opts.onRetry?.(attempt, err, waitMs);
7427
7434
  await sleep2(waitMs, opts.signal);
7428
7435
  }
@@ -35556,7 +35563,7 @@ function registerDatamappersCommand(root) {
35556
35563
  });
35557
35564
  addServerFlag(customFnsCmd);
35558
35565
  addAccountFlag(customFnsCmd);
35559
- const previewCmd = dm.command("preview").description(
35566
+ const previewCmd2 = dm.command("preview").description(
35560
35567
  "Render a mapper config's projected output for a sample input. Posts to `POST /api/templates/preview-data` with the operator-supplied JSON (typically built from a saved mapper config + template_id + document_version + datamapper_id). Output is the server's `{output: {header, projected_config, \u2026}, err}` envelope, emitted as JSON."
35561
35568
  ).requiredOption("--payload-file <path>", "Path to a JSON body for the preview request").option(
35562
35569
  "--json",
@@ -35576,8 +35583,8 @@ function registerDatamappersCommand(root) {
35576
35583
  setup.cleanup();
35577
35584
  }
35578
35585
  });
35579
- addServerFlag(previewCmd);
35580
- addAccountFlag(previewCmd);
35586
+ addServerFlag(previewCmd2);
35587
+ addAccountFlag(previewCmd2);
35581
35588
  const bindCmd = dm.command("bind").description(
35582
35589
  "Update which document IDs a mapper is bound to. The --doc list replaces the mapper's current documents; repeat every filebox you want to keep (dr warns first and names any it drops). Posts to `POST /api/templates/mappers/<id>/binding` with `{selected_document_ids, rescan?}`. The legacy webclient's \"Mapping table with documents\" modal calls this when the operator checks/unchecks docs in the binding picker. Warns first when another mapper of the table on the same ordinal is bound to one of those docs: mappers that share an ordinal are versions of one mapper, so the bind unbinds the other."
35583
35590
  ).argument("<mapper_id>", "mapper id (positive integer)").option("--doc <id>", "Document id to bind (positive integer; repeatable)", collectInts, []).option(
@@ -43482,7 +43489,7 @@ function registerFileboxCommand(root) {
43482
43489
  });
43483
43490
  addServerFlag(sheetsCmd);
43484
43491
  addAccountFlag(sheetsCmd);
43485
- const previewCmd = fb.command("preview").description("Preview raw cell data of a filebox version (row 1 is headers)").argument("<version_id>", "version id (positive integer)").option("--sheet <name>", "Sheet name. Defaults to first sheet from /desc.", "").option("--sheet-ind <n>", "Sheet index (0-based). Defaults to 0.", "0").option("--start <n>", "First row to read (1-based)", "1").option("--rows <n>", "Number of rows to return (start..start+rows-1)", "100").option("--data-only", "Return evaluated values only; omit raw formulas", false).option("--json", "Output raw JSON instead of a table", false).action(
43492
+ const previewCmd2 = fb.command("preview").description("Preview raw cell data of a filebox version (row 1 is headers)").argument("<version_id>", "version id (positive integer)").option("--sheet <name>", "Sheet name. Defaults to first sheet from /desc.", "").option("--sheet-ind <n>", "Sheet index (0-based). Defaults to 0.", "0").option("--start <n>", "First row to read (1-based)", "1").option("--rows <n>", "Number of rows to return (start..start+rows-1)", "100").option("--data-only", "Return evaluated values only; omit raw formulas", false).option("--json", "Output raw JSON instead of a table", false).action(
43486
43493
  async (vidStr, opts) => {
43487
43494
  const versionId = parseVersionIdArg2(vidStr);
43488
43495
  const sheetInd = parsePositiveIntFlag2(opts.sheetInd, "--sheet-ind", 0);
@@ -43507,8 +43514,8 @@ function registerFileboxCommand(root) {
43507
43514
  }
43508
43515
  }
43509
43516
  );
43510
- addServerFlag(previewCmd);
43511
- addAccountFlag(previewCmd);
43517
+ addServerFlag(previewCmd2);
43518
+ addAccountFlag(previewCmd2);
43512
43519
  const createCmd = fb.command("create").description(
43513
43520
  "Create an empty filebox (no file yet). Resolves the date tag config from /versions/tags. Pass --folder to create a folder filebox instead (no date tag, no version, no data \u2014 used to mirror the org-bootstrap hierarchy of Actuals / COA / FX Rates / Configuration)."
43514
43521
  ).option("--name <name>", "Filebox display name (required)", "").option("--scenario <s>", `Scenario: ${VALID_SCENARIOS_HELP}`, "Actuals").option(
@@ -47006,10 +47013,10 @@ function toControlPlaneError(method, path13, err) {
47006
47013
  }
47007
47014
 
47008
47015
  // src/api/awsConnections.ts
47009
- async function call(method, path13, send, what) {
47016
+ async function call(method, path13, send2, what) {
47010
47017
  let out;
47011
47018
  try {
47012
- out = await send();
47019
+ out = await send2();
47013
47020
  } catch (err) {
47014
47021
  throw toControlPlaneError(method, path13, err);
47015
47022
  }
@@ -48184,10 +48191,10 @@ import { readFileSync as readFileSync3 } from "fs";
48184
48191
 
48185
48192
  // src/api/scheduledTasks.ts
48186
48193
  var BASE2 = "/scheduled-tasks";
48187
- async function call2(method, path13, send, what) {
48194
+ async function call2(method, path13, send2, what) {
48188
48195
  let out;
48189
48196
  try {
48190
- out = await send();
48197
+ out = await send2();
48191
48198
  } catch (err) {
48192
48199
  throw toControlPlaneError(method, path13, err);
48193
48200
  }
@@ -64827,7 +64834,7 @@ function registerCashCommand(root) {
64827
64834
 
64828
64835
  // src/commands/update.ts
64829
64836
  import { spawn as spawn2 } from "child_process";
64830
- var REGISTRY = "https://datarails.jfrog.io/artifactory/api/npm/dr-cli-virtual";
64837
+ var REGISTRY = "https://registry.npmjs.org";
64831
64838
  var PACKAGE = "@datarails-ai/dr-cli";
64832
64839
  function spawnInherit(command, args) {
64833
64840
  return new Promise((resolve3) => {
@@ -65487,6 +65494,757 @@ async function remove(client, id, options) {
65487
65494
  await client.deleteJSON(`/api/templates/${id}/calcmodels`, options);
65488
65495
  }
65489
65496
 
65497
+ // src/commands/calcmodelsAgent.ts
65498
+ import { setTimeout as delay } from "timers/promises";
65499
+
65500
+ // src/types/calcmodelsAgent.ts
65501
+ import { z as z3 } from "zod";
65502
+ var optionalText = z3.string().nullish();
65503
+ var amount = z3.number().nullish();
65504
+ var calcAgentOperationStatusSchema = z3.enum([
65505
+ "PENDING",
65506
+ "RUNNING",
65507
+ "SUCCEEDED",
65508
+ "NO_PROPOSAL",
65509
+ "FAILED"
65510
+ ]);
65511
+ var calcAgentGateErrorSchema = z3.object({
65512
+ code: z3.string(),
65513
+ phase: optionalText,
65514
+ segment: optionalText,
65515
+ suggestion: optionalText,
65516
+ detail: optionalText
65517
+ }).passthrough();
65518
+ var calcAgentTurnAcceptedSchema = z3.object({ operation_id: z3.string().uuid(), conversation_id: z3.string().optional() }).passthrough();
65519
+ var coverageSchema = z3.object({
65520
+ pct: amount,
65521
+ pool_total: amount,
65522
+ allocated_total: amount,
65523
+ unallocated_amount: amount,
65524
+ uncovered_group_count: z3.number().nullish()
65525
+ }).passthrough();
65526
+ var balanceCheckSchema = z3.object({ group: z3.string(), net: z3.number(), ok: z3.boolean() }).passthrough();
65527
+ var warningSchema = z3.object({ code: optionalText, message: optionalText }).passthrough();
65528
+ var calcAgentPreviewResultSchema = z3.object({
65529
+ total_count: z3.number().nullish(),
65530
+ coverage: coverageSchema.nullish(),
65531
+ balance_checks: z3.array(balanceCheckSchema).nullish(),
65532
+ warnings: z3.array(warningSchema).nullish()
65533
+ }).passthrough();
65534
+ var calcAgentDefinitionSchema = z3.object({
65535
+ model_type: optionalText,
65536
+ name: optionalText,
65537
+ destination_template_id: z3.number().nullish()
65538
+ }).passthrough();
65539
+ var calcAgentPreviewSchema = z3.object({
65540
+ status: calcAgentOperationStatusSchema,
65541
+ phase: optionalText,
65542
+ conversation_id: optionalText,
65543
+ answer_text: optionalText,
65544
+ changes_summary: optionalText,
65545
+ definition: calcAgentDefinitionSchema.nullish(),
65546
+ error: calcAgentGateErrorSchema.nullish(),
65547
+ result: calcAgentPreviewResultSchema.nullish()
65548
+ }).passthrough();
65549
+ var calcAgentSaveResultSchema = z3.object({ id: z3.number(), name: z3.string(), version_id: z3.number() }).passthrough();
65550
+ var calcAgentImpactSchema = z3.object({
65551
+ total_rows: amount,
65552
+ pool_total: amount,
65553
+ allocated_total: amount,
65554
+ coverage_pct: amount
65555
+ }).passthrough();
65556
+ var calcAgentApprovalPlanSchema = z3.object({ impact: calcAgentImpactSchema, version_id: z3.number() }).passthrough();
65557
+ var calcAgentApproveResultSchema = z3.object({
65558
+ id: z3.number(),
65559
+ name: z3.string(),
65560
+ impact: calcAgentImpactSchema.nullish(),
65561
+ run_id: z3.string().nullish()
65562
+ }).passthrough();
65563
+
65564
+ // src/api/_htmlEntities.ts
65565
+ var ENTITIES2 = {
65566
+ "&amp;": "&",
65567
+ "&lt;": "<",
65568
+ "&gt;": ">",
65569
+ "&quot;": '"',
65570
+ "&#x27;": "'",
65571
+ "&#39;": "'"
65572
+ };
65573
+ var ENTITY_RE2 = /&(?:amp|lt|gt|quot|#x27|#39);/g;
65574
+ function decodeHtmlDeep(value) {
65575
+ if (typeof value === "string") return value.replace(ENTITY_RE2, (m) => ENTITIES2[m] ?? m);
65576
+ if (Array.isArray(value)) return value.map(decodeHtmlDeep);
65577
+ if (value !== null && typeof value === "object") {
65578
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, decodeHtmlDeep(v)]));
65579
+ }
65580
+ return value;
65581
+ }
65582
+
65583
+ // src/api/calcmodelsAgent.ts
65584
+ var BASE3 = "/api/templates/calcmodels/agent";
65585
+ var APPROVAL_ACK_REQUIRED = "CALC_APPROVAL_ACK_REQUIRED";
65586
+ var CalcAgentHttpError = class extends Error {
65587
+ status;
65588
+ body;
65589
+ code;
65590
+ constructor(status2, body, message) {
65591
+ super(message);
65592
+ this.name = "CalcAgentHttpError";
65593
+ this.status = status2;
65594
+ this.body = body;
65595
+ const code = isRecord(body) ? body["code"] : void 0;
65596
+ this.code = typeof code === "string" ? code : void 0;
65597
+ }
65598
+ /** A numeric field of the body (`calc_model_id`, `version_id`), or undefined. */
65599
+ numberField(key) {
65600
+ const v = isRecord(this.body) ? this.body[key] : void 0;
65601
+ return typeof v === "number" ? v : void 0;
65602
+ }
65603
+ };
65604
+ var CONTROL_CHARS2 = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
65605
+ function escapeControlChars(text2) {
65606
+ return text2.replace(
65607
+ CONTROL_CHARS2,
65608
+ (c) => c === "\r" ? "\\r" : `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`
65609
+ );
65610
+ }
65611
+ function isRecord(v) {
65612
+ return typeof v === "object" && v !== null && !Array.isArray(v);
65613
+ }
65614
+ function textField(body, key) {
65615
+ if (!isRecord(body)) return void 0;
65616
+ const v = body[key];
65617
+ return typeof v === "string" && v !== "" ? v : void 0;
65618
+ }
65619
+ async function send(client, method, path13, payload, options) {
65620
+ const res = await client.do(
65621
+ method,
65622
+ path13,
65623
+ payload === void 0 ? void 0 : JSON.stringify(payload),
65624
+ options
65625
+ );
65626
+ const text2 = await res.text();
65627
+ let body = text2;
65628
+ if (text2 !== "") {
65629
+ try {
65630
+ body = JSON.parse(text2);
65631
+ } catch {
65632
+ body = text2;
65633
+ }
65634
+ }
65635
+ return { status: res.status, body: decodeHtmlDeep(body) };
65636
+ }
65637
+ function describeServerError(body) {
65638
+ if (!isRecord(body)) {
65639
+ const raw2 = typeof body === "string" ? body.trim() : "";
65640
+ return raw2.length > 200 ? `${raw2.slice(0, 200)}\u2026` : raw2;
65641
+ }
65642
+ const code = textField(body, "code");
65643
+ const phase = textField(body, "phase");
65644
+ const parts = [
65645
+ textField(body, "detail"),
65646
+ textField(body, "suggestion"),
65647
+ textField(body, "segment") !== void 0 ? `[${textField(body, "segment")}]` : void 0
65648
+ ].filter((p) => p !== void 0);
65649
+ const head = code !== void 0 ? `${code}${phase !== void 0 ? ` (${phase})` : ""}` : "";
65650
+ if (head === "") return parts.join(" \u2014 ");
65651
+ return parts.length > 0 ? `${head}: ${parts.join(" \u2014 ")}` : head;
65652
+ }
65653
+ function httpError(method, path13, answer, hint) {
65654
+ const detail = escapeControlChars(hint ?? describeServerError(answer.body));
65655
+ const tail = detail !== "" ? `: ${detail}` : "";
65656
+ return new CalcAgentHttpError(
65657
+ answer.status,
65658
+ answer.body,
65659
+ `${method} ${path13}: HTTP ${answer.status}${tail}`
65660
+ );
65661
+ }
65662
+ function parse2(schema, method, path13, body) {
65663
+ const out = schema.safeParse(body);
65664
+ if (!out.success) {
65665
+ const issues = out.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
65666
+ throw new Error(`${method} ${path13}: unexpected response from the server (${issues})`);
65667
+ }
65668
+ return out.data;
65669
+ }
65670
+ async function postTurn(client, input, options) {
65671
+ const path13 = `${BASE3}/turns`;
65672
+ const payload = { message: input.message };
65673
+ if (input.conversationId !== void 0) payload["conversation_id"] = input.conversationId;
65674
+ const answer = await send(client, "POST", path13, payload, options);
65675
+ if (answer.status === 202) return parse2(calcAgentTurnAcceptedSchema, "POST", path13, answer.body);
65676
+ if (answer.status === 404 && input.conversationId !== void 0) {
65677
+ throw httpError(
65678
+ "POST",
65679
+ path13,
65680
+ answer,
65681
+ `conversation ${input.conversationId} not found (only the user who started it can continue it)`
65682
+ );
65683
+ }
65684
+ throw httpError("POST", path13, answer);
65685
+ }
65686
+ async function getPreview2(client, operationId, options) {
65687
+ const path13 = `${BASE3}/preview/${encodeURIComponent(operationId)}`;
65688
+ const answer = await send(client, "GET", path13, void 0, options);
65689
+ if (answer.status === 200) return parse2(calcAgentPreviewSchema, "GET", path13, answer.body);
65690
+ if (answer.status === 404) {
65691
+ throw httpError(
65692
+ "GET",
65693
+ path13,
65694
+ answer,
65695
+ `operation ${operationId} not found (only the user who started the turn can read it)`
65696
+ );
65697
+ }
65698
+ throw httpError("GET", path13, answer);
65699
+ }
65700
+ async function save2(client, input, options) {
65701
+ const payload = {
65702
+ preview_operation_id: input.operationId,
65703
+ name: input.name
65704
+ };
65705
+ if (input.calcModelId !== void 0) payload["calc_model_id"] = input.calcModelId;
65706
+ const answer = await send(client, "POST", BASE3, payload, options);
65707
+ if (answer.status === 201) return parse2(calcAgentSaveResultSchema, "POST", BASE3, answer.body);
65708
+ throw httpError("POST", BASE3, answer);
65709
+ }
65710
+ async function requestApprovalImpact(client, calcModelId, options) {
65711
+ const path13 = `${BASE3}/${calcModelId}/approve`;
65712
+ const answer = await send(client, "POST", path13, {}, options);
65713
+ if (answer.status >= 200 && answer.status < 300) {
65714
+ throw new Error(
65715
+ `POST ${path13}: HTTP ${answer.status} to a request without an acknowledgment; expected ${APPROVAL_ACK_REQUIRED}. Check the model with \`dr calcmodels get ${calcModelId}\`.`
65716
+ );
65717
+ }
65718
+ if (answer.status === 400 && textField(answer.body, "code") === APPROVAL_ACK_REQUIRED) {
65719
+ return parse2(calcAgentApprovalPlanSchema, "POST", path13, answer.body);
65720
+ }
65721
+ throw httpError("POST", path13, answer);
65722
+ }
65723
+ async function confirmApproval(client, calcModelId, versionId, options) {
65724
+ const path13 = `${BASE3}/${calcModelId}/approve`;
65725
+ const answer = await send(
65726
+ client,
65727
+ "POST",
65728
+ path13,
65729
+ { acknowledged: true, version_id: versionId },
65730
+ options
65731
+ );
65732
+ if (answer.status === 200) return parse2(calcAgentApproveResultSchema, "POST", path13, answer.body);
65733
+ throw httpError("POST", path13, answer);
65734
+ }
65735
+
65736
+ // src/commands/_agentCli.ts
65737
+ import { access } from "fs/promises";
65738
+ var JSON_HELP = "Emit raw JSON to stdout instead of a pretty render.";
65739
+ var CONFIRM_HELP = "Token from a prior plan run \u2014 required to actually write";
65740
+ function withTarget(cmd) {
65741
+ addServerFlag(cmd);
65742
+ addAccountFlag(cmd);
65743
+ return cmd;
65744
+ }
65745
+ function std() {
65746
+ return { out: process.stdout, err: process.stderr };
65747
+ }
65748
+ function requireId(value, placeholder) {
65749
+ const id = (value ?? "").trim();
65750
+ if (id === "") {
65751
+ throw new Error(`missing required option: --id ${placeholder}`);
65752
+ }
65753
+ return id;
65754
+ }
65755
+ function requirePositiveInt(value, flag) {
65756
+ const n = /^\d+$/.test(value) ? Number(value) : NaN;
65757
+ if (!Number.isSafeInteger(n) || n <= 0) {
65758
+ throw new Error(`${flag} ${JSON.stringify(value)}: expected a positive integer`);
65759
+ }
65760
+ return n;
65761
+ }
65762
+ function requireBool(value, flag) {
65763
+ if (value === "true") return true;
65764
+ if (value === "false") return false;
65765
+ throw new Error(`${flag} ${JSON.stringify(value ?? "")}: expected true or false`);
65766
+ }
65767
+ function splitList(value) {
65768
+ return [
65769
+ ...new Set(
65770
+ (value ?? "").split(",").map((part) => part.trim()).filter((part) => part !== "")
65771
+ )
65772
+ ];
65773
+ }
65774
+ function isNoneSentinel(parts, flag, value, what) {
65775
+ if (!parts.includes("none")) return false;
65776
+ if (parts.length === 1) return true;
65777
+ throw new Error(`${flag} ${JSON.stringify(value)}: "none" cannot be combined with ${what}`);
65778
+ }
65779
+ function shellArg(value) {
65780
+ return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value) ? value : shellQuote(value);
65781
+ }
65782
+ function proseStream(cfg) {
65783
+ return cfg.asJson ? cfg.err : cfg.out;
65784
+ }
65785
+ async function assertNoOverwrite(paths, force) {
65786
+ if (force) return;
65787
+ const existing = [];
65788
+ for (const path13 of paths) {
65789
+ try {
65790
+ await access(path13);
65791
+ existing.push(path13);
65792
+ } catch {
65793
+ }
65794
+ }
65795
+ if (existing.length > 0) {
65796
+ throw new Error(
65797
+ `refusing to overwrite existing file(s): ${existing.join(", ")}. Pull into another --dir, or pass --force to replace them.`
65798
+ );
65799
+ }
65800
+ }
65801
+
65802
+ // src/commands/calcmodelsAgent.ts
65803
+ var AGENT_POLL_INTERVAL_MS = 3e3;
65804
+ var AGENT_DEFAULT_TIMEOUT_S = 900;
65805
+ var MAX_TRANSIENT_READ_FAILURES = 5;
65806
+ var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
65807
+ function parseOperationIdArg(raw2) {
65808
+ if (!UUID_RE2.test(raw2)) throw new Error(`invalid operation id: "${raw2}" (expected a UUID)`);
65809
+ return raw2.toLowerCase();
65810
+ }
65811
+ function isLive(p) {
65812
+ return p.status === "PENDING" || p.status === "RUNNING";
65813
+ }
65814
+ function formatNumber(n) {
65815
+ return n === null || n === void 0 ? "n/a" : n.toLocaleString("en-US", { maximumFractionDigits: 2 });
65816
+ }
65817
+ function previewLine(result) {
65818
+ const parts = [`${formatNumber(result.total_count)} rows`];
65819
+ const cov = result.coverage;
65820
+ if (cov) {
65821
+ const pct2 = cov.pct === null || cov.pct === void 0 ? "n/a" : `${formatNumber(cov.pct)}%`;
65822
+ parts.push(
65823
+ `coverage ${pct2} (allocated ${formatNumber(cov.allocated_total)} of pool ${formatNumber(cov.pool_total)})`
65824
+ );
65825
+ }
65826
+ const checks = result.balance_checks ?? [];
65827
+ if (checks.length > 0) {
65828
+ const ok = checks.filter((c) => c.ok).length;
65829
+ parts.push(`balance: ${ok} of ${checks.length} groups net to zero`);
65830
+ }
65831
+ return `preview: ${parts.join(" \xB7 ")}`;
65832
+ }
65833
+ function targetFlags(serverFlag, accountFlag) {
65834
+ return accountFlag === void 0 ? `--server ${serverFlag}` : `--server ${serverFlag} --account ${shellQuote(accountFlag)}`;
65835
+ }
65836
+ function previewCmd(operationId, target) {
65837
+ return `dr calcmodels agent preview ${operationId} ${target}`;
65838
+ }
65839
+ function renderPreview(out, p, operationId, target) {
65840
+ out.write(`status: ${p.status}
65841
+ `);
65842
+ if (p.conversation_id) out.write(`conversation: ${escapeControlChars(p.conversation_id)}
65843
+ `);
65844
+ if (isLive(p)) {
65845
+ out.write(
65846
+ `
65847
+ The turn is still running. Check again with:
65848
+ ${previewCmd(operationId, target)}
65849
+ `
65850
+ );
65851
+ return;
65852
+ }
65853
+ if (p.answer_text) out.write(`
65854
+ ${escapeControlChars(p.answer_text.trim())}
65855
+ `);
65856
+ if (p.changes_summary) {
65857
+ out.write("\nchanges:\n");
65858
+ for (const line of p.changes_summary.trim().split("\n"))
65859
+ out.write(` ${escapeControlChars(line)}
65860
+ `);
65861
+ }
65862
+ const savable = p.status === "SUCCEEDED" && p.result !== null && p.result !== void 0;
65863
+ if (p.status === "SUCCEEDED") {
65864
+ const d = p.definition;
65865
+ if (d) {
65866
+ out.write(
65867
+ `
65868
+ proposal: ${escapeControlChars(JSON.stringify(d.name ?? ""))} (${escapeControlChars(d.model_type ?? "unknown")}) \u2192 destination table ${d.destination_template_id ?? "n/a"}
65869
+ `
65870
+ );
65871
+ }
65872
+ if (p.result) {
65873
+ out.write(`${previewLine(p.result)}
65874
+ `);
65875
+ for (const w of p.result.warnings ?? []) {
65876
+ const label = [w.code, w.message].filter((s) => !!s).join(": ");
65877
+ if (label !== "") out.write(`warning: ${escapeControlChars(label)}
65878
+ `);
65879
+ }
65880
+ } else {
65881
+ out.write(
65882
+ "preview: none ran. The server saves only a turn whose preview ran (CALC_PREVIEW_NOT_READY).\n"
65883
+ );
65884
+ }
65885
+ }
65886
+ const next = [];
65887
+ if (savable) {
65888
+ next.push(`save the draft: dr calcmodels agent save ${operationId} ${target}`);
65889
+ }
65890
+ if (p.conversation_id) {
65891
+ next.push(
65892
+ `reply: dr calcmodels agent ask '<reply>' --conversation ${shellQuote(p.conversation_id)} ${target}`
65893
+ );
65894
+ }
65895
+ if (next.length > 0) out.write(`
65896
+ next:
65897
+ ${next.map((l) => ` ${l}
65898
+ `).join("")}`);
65899
+ }
65900
+ function writeOutcome(out, p, operationId, target, asJson) {
65901
+ if (asJson) writeJSONIndented(out, { operation_id: operationId, ...p });
65902
+ else renderPreview(out, p, operationId, target);
65903
+ if (p.status === "FAILED") {
65904
+ const why = p.error ? escapeControlChars(describeServerError(p.error)) : "the server gave no error detail";
65905
+ throw new Error(`turn ${operationId} failed: ${why}`);
65906
+ }
65907
+ }
65908
+ var ReadTimeoutError = class extends Error {
65909
+ constructor(operationId, ms) {
65910
+ super(`reading operation ${operationId} took longer than ${ms} ms`);
65911
+ this.name = "ReadTimeoutError";
65912
+ }
65913
+ };
65914
+ function isTransient(err) {
65915
+ if (err instanceof ReadTimeoutError) return true;
65916
+ if (err instanceof CalcAgentHttpError) return err.status >= 500;
65917
+ return err instanceof TypeError;
65918
+ }
65919
+ var AGENT_READ_TIMEOUT_MS = 3e4;
65920
+ var AGENT_READ_TIMEOUT_FLOOR_MS = 5e3;
65921
+ var defaultSleep8 = (ms, signal) => delay(ms, void 0, { signal });
65922
+ async function runAgentAsk(cfg) {
65923
+ const accepted = await postTurn(
65924
+ cfg.client,
65925
+ {
65926
+ message: cfg.message,
65927
+ ...cfg.conversationId !== void 0 && { conversationId: cfg.conversationId }
65928
+ },
65929
+ { signal: cfg.signal }
65930
+ );
65931
+ const op = accepted.operation_id;
65932
+ const conv = accepted.conversation_id;
65933
+ const target = targetFlags(cfg.serverFlag, cfg.accountFlag);
65934
+ cfg.err.write(
65935
+ `turn started: operation ${op}${conv ? `, conversation ${escapeControlChars(conv)}` : ""}
65936
+ `
65937
+ );
65938
+ if (!cfg.wait) {
65939
+ if (cfg.asJson) {
65940
+ writeJSONIndented(cfg.out, accepted);
65941
+ return;
65942
+ }
65943
+ cfg.out.write(`operation: ${op}
65944
+ Read it with:
65945
+ ${previewCmd(op, target)}
65946
+ `);
65947
+ return;
65948
+ }
65949
+ cfg.err.write(
65950
+ `Waiting for the agent. Ctrl-C stops the wait, not the turn; resume with:
65951
+ ${previewCmd(op, target)}
65952
+ `
65953
+ );
65954
+ const preview2 = await pollPreview(cfg, op);
65955
+ writeOutcome(cfg.out, preview2, op, target, cfg.asJson);
65956
+ }
65957
+ async function pollPreview(cfg, operationId) {
65958
+ const interval = cfg.pollIntervalMs ?? AGENT_POLL_INTERVAL_MS;
65959
+ const sleep3 = cfg.sleep ?? defaultSleep8;
65960
+ const now = cfg.now ?? Date.now;
65961
+ const deadline = now() + cfg.timeoutMs;
65962
+ const readMax = cfg.readTimeoutMs ?? AGENT_READ_TIMEOUT_MS;
65963
+ const readFloor = cfg.readTimeoutFloorMs ?? AGENT_READ_TIMEOUT_FLOOR_MS;
65964
+ let failures = 0;
65965
+ for (; ; ) {
65966
+ await sleep3(Math.max(0, Math.min(interval, deadline - now())), cfg.signal);
65967
+ try {
65968
+ const budget = Math.min(readMax, Math.max(deadline - now(), readFloor));
65969
+ const p = await readWithin(cfg, operationId, budget);
65970
+ failures = 0;
65971
+ if (!isLive(p)) return p;
65972
+ } catch (err) {
65973
+ failures += 1;
65974
+ if (!isTransient(err)) throw err;
65975
+ if (failures > MAX_TRANSIENT_READ_FAILURES && now() < deadline) throw err;
65976
+ }
65977
+ if (now() >= deadline) {
65978
+ throw new Error(
65979
+ `turn ${operationId} is still running after ${Math.round(cfg.timeoutMs / 1e3)}s. It keeps running on the server; read it with: ${previewCmd(operationId, targetFlags(cfg.serverFlag, cfg.accountFlag))}`
65980
+ );
65981
+ }
65982
+ }
65983
+ }
65984
+ async function readWithin(cfg, operationId, budgetMs) {
65985
+ const ctl = new AbortController();
65986
+ const relay = () => ctl.abort(cfg.signal.reason);
65987
+ if (cfg.signal.aborted) relay();
65988
+ else cfg.signal.addEventListener("abort", relay, { once: true });
65989
+ const timer = setTimeout(() => ctl.abort(), budgetMs);
65990
+ try {
65991
+ return await getPreview2(cfg.client, operationId, { signal: ctl.signal });
65992
+ } catch (err) {
65993
+ if (ctl.signal.aborted && !cfg.signal.aborted)
65994
+ throw new ReadTimeoutError(operationId, budgetMs);
65995
+ throw err;
65996
+ } finally {
65997
+ clearTimeout(timer);
65998
+ cfg.signal.removeEventListener("abort", relay);
65999
+ }
66000
+ }
66001
+ async function runAgentPreview(cfg) {
66002
+ const p = await getPreview2(cfg.client, cfg.operationId, { signal: cfg.signal });
66003
+ writeOutcome(
66004
+ cfg.out,
66005
+ p,
66006
+ cfg.operationId,
66007
+ targetFlags(cfg.serverFlag, cfg.accountFlag),
66008
+ cfg.asJson
66009
+ );
66010
+ }
66011
+ var PREVIEW_ALREADY_SAVED = "CALC_PREVIEW_ALREADY_SAVED";
66012
+ var VERSION_CHANGED = "CALC_APPROVAL_VERSION_CHANGED";
66013
+ async function runAgentSave(cfg) {
66014
+ let name = cfg.name;
66015
+ if (name !== void 0 && name.trim() === "") throw new Error("--name must not be empty");
66016
+ if (name === void 0) {
66017
+ const p = await getPreview2(cfg.client, cfg.operationId, { signal: cfg.signal });
66018
+ name = p.definition?.name ?? void 0;
66019
+ if (name === void 0 || name.trim() === "") {
66020
+ throw new Error(
66021
+ `--name is required: operation ${cfg.operationId} has no proposed name (status ${p.status})`
66022
+ );
66023
+ }
66024
+ }
66025
+ let saved;
66026
+ try {
66027
+ saved = await save2(
66028
+ cfg.client,
66029
+ {
66030
+ operationId: cfg.operationId,
66031
+ name,
66032
+ ...cfg.calcModelId !== void 0 && { calcModelId: cfg.calcModelId }
66033
+ },
66034
+ { signal: cfg.signal }
66035
+ );
66036
+ } catch (err) {
66037
+ if (err instanceof CalcAgentHttpError && err.code === PREVIEW_ALREADY_SAVED) {
66038
+ const modelId = err.numberField("calc_model_id");
66039
+ if (modelId !== void 0) {
66040
+ throw new Error(
66041
+ `${err.message}. To add this turn as a new version of model ${modelId}: dr calcmodels agent save ${cfg.operationId} --model ${modelId} ${targetFlags(cfg.serverFlag, cfg.accountFlag)}`,
66042
+ { cause: err }
66043
+ );
66044
+ }
66045
+ }
66046
+ throw err;
66047
+ }
66048
+ if (cfg.asJson) {
66049
+ writeJSONIndented(cfg.out, saved);
66050
+ return;
66051
+ }
66052
+ cfg.out.write(
66053
+ `Saved draft calc model ${saved.id} ${escapeControlChars(JSON.stringify(saved.name))} (version ${saved.version_id}). This version does not run until it is approved.
66054
+
66055
+ next:
66056
+ dr calcmodels agent approve ${saved.id} ${targetFlags(cfg.serverFlag, cfg.accountFlag)}
66057
+ `
66058
+ );
66059
+ }
66060
+ function approveAction(calcModelId, versionId) {
66061
+ return { resource: "calcmodel", id: `${calcModelId}@v${versionId}`, verb: "approve" };
66062
+ }
66063
+ function versionChanged(calcModelId, planned, current, cause) {
66064
+ const newer = current !== void 0 ? ` (${current})` : "";
66065
+ return new Error(
66066
+ `calc model ${calcModelId}: a newer version${newer} was saved after the plan for version ${planned}. Review it: re-run without --confirm-token. Nothing was activated.`,
66067
+ cause === void 0 ? void 0 : { cause }
66068
+ );
66069
+ }
66070
+ function impactLines(calcModelId, plan) {
66071
+ const i = plan.impact;
66072
+ const pct2 = i.coverage_pct === null || i.coverage_pct === void 0 ? "n/a" : `${formatNumber(i.coverage_pct)}%`;
66073
+ return [
66074
+ `calc model: ${calcModelId}`,
66075
+ `version: ${plan.version_id}`,
66076
+ `rows the first run writes: ${formatNumber(i.total_rows)}`,
66077
+ `allocated total: ${formatNumber(i.allocated_total)} of pool total ${formatNumber(i.pool_total)} (coverage ${pct2})`,
66078
+ "Approving activates this version and starts its first production run at once."
66079
+ ];
66080
+ }
66081
+ async function runAgentApprove(cfg) {
66082
+ const executing = cfg.token !== void 0 && cfg.token.trim() !== "";
66083
+ if (executing && cfg.versionId === void 0) {
66084
+ throw new Error(
66085
+ "--version-id is required with --confirm-token: copy the command the plan printed"
66086
+ );
66087
+ }
66088
+ if (executing) await preflightConfirmToken(approveAction(cfg.id, cfg.versionId), cfg.token);
66089
+ const plan = await requestApprovalImpact(cfg.client, cfg.id, { signal: cfg.signal });
66090
+ if (executing && plan.version_id !== cfg.versionId) {
66091
+ throw versionChanged(cfg.id, cfg.versionId, plan.version_id);
66092
+ }
66093
+ const versionId = executing ? cfg.versionId : plan.version_id;
66094
+ const target = targetFlags(cfg.serverFlag, cfg.accountFlag);
66095
+ await twoStepConfirm({
66096
+ out: cfg.out,
66097
+ action: approveAction(cfg.id, versionId),
66098
+ token: cfg.token,
66099
+ server: cfg.serverFlag,
66100
+ confirmCmd: `dr calcmodels agent approve ${cfg.id} --version-id ${versionId} ${target}${cfg.asJson ? " --json" : ""}`,
66101
+ describe: () => Promise.resolve(impactLines(cfg.id, plan)),
66102
+ execute: async () => {
66103
+ let result;
66104
+ try {
66105
+ result = await confirmApproval(cfg.client, cfg.id, versionId, {
66106
+ signal: cfg.signal
66107
+ });
66108
+ } catch (err) {
66109
+ if (err instanceof CalcAgentHttpError && err.code === VERSION_CHANGED) {
66110
+ throw versionChanged(cfg.id, versionId, err.numberField("version_id"), err);
66111
+ }
66112
+ throw err;
66113
+ }
66114
+ if (cfg.asJson) {
66115
+ writeJSONIndented(cfg.out, result);
66116
+ return;
66117
+ }
66118
+ const run2 = result.run_id ? `First run: ${escapeControlChars(result.run_id)}.` : `No run was started: the model is not runnable now. Check it with dr calcmodels get ${cfg.id} ${target}.`;
66119
+ cfg.out.write(`Activated calc model ${cfg.id} (version ${versionId}). ${run2}
66120
+ `);
66121
+ }
66122
+ });
66123
+ }
66124
+ var ASK_SETUP_HEADROOM_MS = 6e4;
66125
+ function registerCalcmodelsAgentCommand(cm) {
66126
+ const agent = cm.command("agent").description(
66127
+ "Build an AGENT (allocation) calc model with the builder agent \u2014 the web builder endpoints. Super Admin + the calc_model_agent_builder flag."
66128
+ );
66129
+ const askCmd = agent.command("ask").description(
66130
+ "Send one message to the builder agent and wait for its answer. Ctrl-C stops the wait, not the turn."
66131
+ ).argument("<message>", "what to build, or a reply to the agent").option("--conversation <id>", "continue this conversation (from a previous answer)").option("--no-wait", "return after the server accepts the turn; read it with `preview`").option(
66132
+ "--timeout <seconds>",
66133
+ `stop waiting after this long (default ${AGENT_DEFAULT_TIMEOUT_S})`
66134
+ ).option("--json", "Output raw JSON", false).action(
66135
+ async (message, opts) => {
66136
+ if (message.trim() === "") throw new Error("<message> must not be empty");
66137
+ const timeoutMs = parsePositiveSecondsFlag(
66138
+ opts.timeout,
66139
+ "--timeout",
66140
+ AGENT_DEFAULT_TIMEOUT_S * 1e3
66141
+ );
66142
+ const serverKey = resolveServer(opts.server);
66143
+ const setup = await setupCall(opts.server, opts.account, {
66144
+ timeoutMs: timeoutMs + ASK_SETUP_HEADROOM_MS
66145
+ });
66146
+ try {
66147
+ await runAgentAsk({
66148
+ client: setup.client,
66149
+ message,
66150
+ ...opts.conversation !== void 0 && { conversationId: opts.conversation },
66151
+ wait: opts.wait !== false,
66152
+ timeoutMs,
66153
+ asJson: opts.json === true,
66154
+ serverFlag: serverKey,
66155
+ accountFlag: normaliseAccount(opts.account),
66156
+ signal: setup.signal,
66157
+ out: process.stdout,
66158
+ err: process.stderr
66159
+ });
66160
+ } finally {
66161
+ setup.cleanup();
66162
+ }
66163
+ }
66164
+ );
66165
+ addServerFlag(askCmd);
66166
+ addAccountFlag(askCmd);
66167
+ const previewCmdDef = agent.command("preview").description("Read one turn: the agent's answer, its proposal, and the preview figures").argument("<operation_id>", "the operation id `ask` printed").option("--json", "Output raw JSON", false).action(async (opArg, opts) => {
66168
+ const operationId = parseOperationIdArg(opArg);
66169
+ const serverKey = resolveServer(opts.server);
66170
+ const setup = await setupCall(opts.server, opts.account);
66171
+ try {
66172
+ await runAgentPreview({
66173
+ client: setup.client,
66174
+ operationId,
66175
+ asJson: opts.json === true,
66176
+ serverFlag: serverKey,
66177
+ accountFlag: normaliseAccount(opts.account),
66178
+ signal: setup.signal,
66179
+ out: process.stdout
66180
+ });
66181
+ } finally {
66182
+ setup.cleanup();
66183
+ }
66184
+ });
66185
+ addServerFlag(previewCmdDef);
66186
+ addAccountFlag(previewCmdDef);
66187
+ const saveCmd = agent.command("save").description("Save a succeeded turn as a DRAFT calc model. Nothing runs until `approve`.").argument("<operation_id>", "the operation id of a SUCCEEDED turn").option("--name <name>", "model name (default: the agent's proposed name)").option("--model <calc_model_id>", "add this turn as a new version of an existing AGENT model").option("--json", "Output raw JSON", false).action(async (opArg, opts) => {
66188
+ const operationId = parseOperationIdArg(opArg);
66189
+ const calcModelId = opts.model === void 0 ? void 0 : requirePositiveInt(opts.model, "--model");
66190
+ const serverKey = resolveServer(opts.server);
66191
+ const setup = await setupCall(opts.server, opts.account);
66192
+ try {
66193
+ await runAgentSave({
66194
+ client: setup.client,
66195
+ operationId,
66196
+ ...opts.name !== void 0 && { name: opts.name },
66197
+ ...calcModelId !== void 0 && { calcModelId },
66198
+ asJson: opts.json === true,
66199
+ serverFlag: serverKey,
66200
+ accountFlag: normaliseAccount(opts.account),
66201
+ signal: setup.signal,
66202
+ out: process.stdout
66203
+ });
66204
+ } finally {
66205
+ setup.cleanup();
66206
+ }
66207
+ });
66208
+ addServerFlag(saveCmd);
66209
+ addAccountFlag(saveCmd);
66210
+ const approveCmd = agent.command("approve").description(
66211
+ "Activate an AGENT model's newest version and start its first production run (two-step confirm; a person confirms on production)."
66212
+ ).argument("<calc_model_id>", "the model id `save` printed").option("--version-id <n>", "the version the plan showed (required with --confirm-token)").option("--confirm-token <token>", "Token from a prior plan run \u2014 required to activate", "").option("--json", "Output raw JSON of the activation", false).action(
66213
+ async (idArg, opts) => {
66214
+ const id = requirePositiveInt(idArg, "<calc_model_id>");
66215
+ const versionId = opts.versionId === void 0 ? void 0 : requirePositiveInt(opts.versionId, "--version-id");
66216
+ const token = opts.confirmToken;
66217
+ if (token !== void 0 && token.trim() !== "") {
66218
+ if (versionId === void 0) {
66219
+ throw new Error(
66220
+ "--version-id is required with --confirm-token: copy the command the plan printed"
66221
+ );
66222
+ }
66223
+ await preflightConfirmToken(approveAction(id, versionId), token);
66224
+ }
66225
+ const serverKey = resolveServer(opts.server);
66226
+ const setup = await setupCall(opts.server, opts.account);
66227
+ try {
66228
+ await runAgentApprove({
66229
+ client: setup.client,
66230
+ id,
66231
+ ...versionId !== void 0 && { versionId },
66232
+ token,
66233
+ asJson: opts.json === true,
66234
+ serverFlag: serverKey,
66235
+ accountFlag: normaliseAccount(opts.account),
66236
+ signal: setup.signal,
66237
+ out: process.stdout
66238
+ });
66239
+ } finally {
66240
+ setup.cleanup();
66241
+ }
66242
+ }
66243
+ );
66244
+ addServerFlag(approveCmd);
66245
+ addAccountFlag(approveCmd);
66246
+ }
66247
+
65490
66248
  // src/commands/calcmodels.ts
65491
66249
  async function runCalcmodelsList(cfg) {
65492
66250
  const models = await list25(cfg.client, { signal: cfg.signal });
@@ -65891,6 +66649,7 @@ function registerCalcmodelsCommand(root) {
65891
66649
  });
65892
66650
  addServerFlag(deleteCmd);
65893
66651
  addAccountFlag(deleteCmd);
66652
+ registerCalcmodelsAgentCommand(cm);
65894
66653
  }
65895
66654
 
65896
66655
  // src/commands/calcVals.ts
@@ -68875,13 +69634,13 @@ import { promises as fsPromises3 } from "fs";
68875
69634
  import * as nodePath3 from "path";
68876
69635
 
68877
69636
  // src/api/spendControl.ts
68878
- var BASE3 = "/api/spend-control/v1";
69637
+ var BASE4 = "/api/spend-control/v1";
68879
69638
  var BASE_V2 = "/api/spend-control/v2";
68880
69639
  var MAX_BULK_STATUS_IDS = 50;
68881
69640
  var MAX_PAGE_SIZE = 100;
68882
69641
  async function listBillingFrequencies(client, options) {
68883
69642
  const out = await client.getJSON(
68884
- `${BASE3}/catalogs/billing-frequencies/`,
69643
+ `${BASE4}/catalogs/billing-frequencies/`,
68885
69644
  options
68886
69645
  );
68887
69646
  return out ?? [];
@@ -68915,7 +69674,7 @@ function buildContractListQuery(params) {
68915
69674
  }
68916
69675
  async function listContracts(client, params = {}, options) {
68917
69676
  const qs = buildContractListQuery(params);
68918
- const path13 = qs === "" ? `${BASE3}/contracts/` : `${BASE3}/contracts/?${qs}`;
69677
+ const path13 = qs === "" ? `${BASE4}/contracts/` : `${BASE4}/contracts/?${qs}`;
68919
69678
  const out = await client.getJSON(path13, options);
68920
69679
  if (out === null) {
68921
69680
  return { items: [], total: 0, page: null, size: null, pages: null };
@@ -68943,10 +69702,10 @@ async function getContract(client, contractId, params = {}, options) {
68943
69702
  qs.set("currency_code", params.convertTo);
68944
69703
  }
68945
69704
  const suffix = qs.toString() === "" ? "" : `?${qs.toString()}`;
68946
- return client.getJSON(`${BASE3}/contracts/${contractId}${suffix}`, options);
69705
+ return client.getJSON(`${BASE4}/contracts/${contractId}${suffix}`, options);
68947
69706
  }
68948
69707
  async function deleteContract(client, contractId, options) {
68949
- await client.deleteJSON(`${BASE3}/contracts/${contractId}`, options);
69708
+ await client.deleteJSON(`${BASE4}/contracts/${contractId}`, options);
68950
69709
  }
68951
69710
  async function uploadFilesWithAi(client, files, options = {}) {
68952
69711
  if (files.length === 0) return [];
@@ -68954,7 +69713,7 @@ async function uploadFilesWithAi(client, files, options = {}) {
68954
69713
  throw new Error(`uploadFilesWithAi: max 10 files per call, got ${files.length}`);
68955
69714
  }
68956
69715
  const out = await client.postMultipartFiles(
68957
- `${BASE3}/contracts/files-with-ai`,
69716
+ `${BASE4}/contracts/files-with-ai`,
68958
69717
  { is_additional: options.isAdditional === true ? "true" : "false" },
68959
69718
  files,
68960
69719
  "files",
@@ -68964,7 +69723,7 @@ async function uploadFilesWithAi(client, files, options = {}) {
68964
69723
  }
68965
69724
  async function uploadContractFile(client, file, options = {}) {
68966
69725
  return client.postMultipartFiles(
68967
- `${BASE3}/contracts/file`,
69726
+ `${BASE4}/contracts/file`,
68968
69727
  { is_additional: options.isAdditional === true ? "true" : "false" },
68969
69728
  [file],
68970
69729
  "file",
@@ -68977,7 +69736,7 @@ async function listContractFiles(client, contractId, params = {}, options) {
68977
69736
  if (params.size !== void 0) qs.set("size", String(params.size));
68978
69737
  const suffix = qs.toString() === "" ? "" : `?${qs.toString()}`;
68979
69738
  const out = await client.getJSON(
68980
- `${BASE3}/contracts/${contractId}/files${suffix}`,
69739
+ `${BASE4}/contracts/${contractId}/files${suffix}`,
68981
69740
  options
68982
69741
  );
68983
69742
  if (out === null) {
@@ -69003,13 +69762,13 @@ async function listAllContractFiles(client, contractId, options) {
69003
69762
  }
69004
69763
  async function getContractFileDownload(client, fileId, options) {
69005
69764
  return client.postJSON(
69006
- `${BASE3}/contracts/files/${fileId}/download`,
69765
+ `${BASE4}/contracts/files/${fileId}/download`,
69007
69766
  {},
69008
69767
  options
69009
69768
  );
69010
69769
  }
69011
69770
  async function deleteContractFile(client, fileId, options) {
69012
- await client.deleteJSON(`${BASE3}/contracts/files/${fileId}`, options);
69771
+ await client.deleteJSON(`${BASE4}/contracts/files/${fileId}`, options);
69013
69772
  }
69014
69773
  async function uploadFileWithAiAsync(client, file, options = {}) {
69015
69774
  return client.postMultipartFiles(
@@ -69045,7 +69804,7 @@ var EXTRACT_POLL_TIMEOUT_MS = 10 * 60 * 1e3;
69045
69804
  function isTerminalAiStatus(status2) {
69046
69805
  return status2 === "PROCESSED" || status2 === "FAILED";
69047
69806
  }
69048
- async function defaultSleep8(ms, signal) {
69807
+ async function defaultSleep9(ms, signal) {
69049
69808
  if (signal?.aborted === true) return;
69050
69809
  await new Promise((resolve3) => {
69051
69810
  const timer = setTimeout(resolve3, ms);
@@ -69062,7 +69821,7 @@ async function defaultSleep8(ms, signal) {
69062
69821
  async function pollExtractionStatus(client, contractFileIds, options = {}) {
69063
69822
  const interval = options.pollIntervalMs ?? EXTRACT_POLL_INTERVAL_MS;
69064
69823
  const timeout = options.timeoutMs ?? EXTRACT_POLL_TIMEOUT_MS;
69065
- const sleep3 = options.sleep ?? defaultSleep8;
69824
+ const sleep3 = options.sleep ?? defaultSleep9;
69066
69825
  const now = options.now ?? Date.now;
69067
69826
  const resolved = /* @__PURE__ */ new Map();
69068
69827
  if (contractFileIds.length === 0) return { resolved, pending: [] };
@@ -69129,14 +69888,14 @@ async function bulkCreateContracts(client, body, options) {
69129
69888
  throw new Error(`bulkCreateContracts: max 10 contracts per call, got ${body.contracts.length}`);
69130
69889
  }
69131
69890
  const out = await client.postJSON(
69132
- `${BASE3}/contracts/bulk-create`,
69891
+ `${BASE4}/contracts/bulk-create`,
69133
69892
  body,
69134
69893
  options
69135
69894
  );
69136
69895
  return out ?? { contracts: [] };
69137
69896
  }
69138
69897
  async function partialUpdateContract(client, contractId, body, options) {
69139
- return client.patchJSON(`${BASE3}/contracts/${contractId}`, body, options);
69898
+ return client.patchJSON(`${BASE4}/contracts/${contractId}`, body, options);
69140
69899
  }
69141
69900
 
69142
69901
  // src/types/spendControl.ts
@@ -69556,7 +70315,7 @@ function chunkContracts(contracts, size = 10) {
69556
70315
  }
69557
70316
 
69558
70317
  // src/api/spendControlVendors.ts
69559
- var BASE4 = "/api/spend-control/v1/vendors";
70318
+ var BASE5 = "/api/spend-control/v1/vendors";
69560
70319
  var MAX_PAGE_SIZE2 = 100;
69561
70320
  function buildVendorListQuery(params) {
69562
70321
  const qs = new URLSearchParams();
@@ -69587,19 +70346,19 @@ function emptyPage() {
69587
70346
  return { items: [], total: 0, page: null, size: null, pages: null };
69588
70347
  }
69589
70348
  async function listVendors(client, params = {}, options) {
69590
- const out = await client.getJSON(withQuery(`${BASE4}/`, params), options);
70349
+ const out = await client.getJSON(withQuery(`${BASE5}/`, params), options);
69591
70350
  return out ?? emptyPage();
69592
70351
  }
69593
70352
  async function listAppStoreVendors(client, params = {}, options) {
69594
70353
  const out = await client.getJSON(
69595
- withQuery(`${BASE4}/app-store`, params),
70354
+ withQuery(`${BASE5}/app-store`, params),
69596
70355
  options
69597
70356
  );
69598
70357
  return out ?? emptyPage();
69599
70358
  }
69600
70359
  async function listVendorsWithContracts(client, params = {}, options) {
69601
70360
  const out = await client.getJSON(
69602
- withQuery(`${BASE4}/with-contracts`, params),
70361
+ withQuery(`${BASE5}/with-contracts`, params),
69603
70362
  options
69604
70363
  );
69605
70364
  return out ?? emptyPage();
@@ -69616,24 +70375,24 @@ async function listAllVendors(fetchPage, client, params = {}, options) {
69616
70375
  return collected;
69617
70376
  }
69618
70377
  async function listVendorCategories(client, options) {
69619
- const out = await client.getJSON(`${BASE4}/categories`, options);
70378
+ const out = await client.getJSON(`${BASE5}/categories`, options);
69620
70379
  return out ?? [];
69621
70380
  }
69622
70381
  async function listVendorsWithMultipleContracts(client, options) {
69623
- const out = await client.getJSON(`${BASE4}/with-multiple-contracts`, options);
70382
+ const out = await client.getJSON(`${BASE5}/with-multiple-contracts`, options);
69624
70383
  return out ?? [];
69625
70384
  }
69626
70385
  async function getVendorOwners(client, vendorId, options) {
69627
- return client.getJSON(`${BASE4}/${encodeURIComponent(vendorId)}/owners/`, options);
70386
+ return client.getJSON(`${BASE5}/${encodeURIComponent(vendorId)}/owners/`, options);
69628
70387
  }
69629
70388
  async function createVendor(client, name, options) {
69630
- return client.postJSON(`${BASE4}/`, { name }, options);
70389
+ return client.postJSON(`${BASE5}/`, { name }, options);
69631
70390
  }
69632
70391
  async function bulkUpdateVendorVisibility(client, vendors, options) {
69633
70392
  if (vendors.length === 0) {
69634
70393
  throw new Error("bulkUpdateVendorVisibility: at least one vendor is required");
69635
70394
  }
69636
- const out = await client.patchJSON(`${BASE4}/visibility`, { vendors }, options);
70395
+ const out = await client.patchJSON(`${BASE5}/visibility`, { vendors }, options);
69637
70396
  return out ?? [];
69638
70397
  }
69639
70398
 
@@ -74746,103 +75505,37 @@ import { promises as fs36 } from "fs";
74746
75505
  import { Option as Option4 } from "commander";
74747
75506
 
74748
75507
  // src/api/templateLibrary.ts
74749
- var BASE5 = "/api/report_library/management";
75508
+ var BASE6 = "/api/report_library/management";
74750
75509
  async function list28(client, options) {
74751
- return await client.getJSON(BASE5, options) ?? [];
75510
+ return await client.getJSON(BASE6, options) ?? [];
74752
75511
  }
74753
75512
  async function create19(client, body, options) {
74754
- const out = await client.postJSON(BASE5, body, options);
75513
+ const out = await client.postJSON(BASE6, body, options);
74755
75514
  if (out === null) {
74756
- throw new Error(`unexpected empty response from POST ${BASE5}`);
75515
+ throw new Error(`unexpected empty response from POST ${BASE6}`);
74757
75516
  }
74758
75517
  return out;
74759
75518
  }
74760
75519
  async function update12(client, id, body, options) {
74761
- const out = await client.putJSON(`${BASE5}/${id}`, body, options);
75520
+ const out = await client.putJSON(`${BASE6}/${id}`, body, options);
74762
75521
  if (out === null) {
74763
- throw new Error(`unexpected empty response from PUT ${BASE5}/${id}`);
75522
+ throw new Error(`unexpected empty response from PUT ${BASE6}/${id}`);
74764
75523
  }
74765
75524
  return out;
74766
75525
  }
74767
75526
  async function uploadImage(client, id, png, filename, options) {
74768
75527
  const out = await client.putMultipart(
74769
- `${BASE5}/${id}`,
75528
+ `${BASE6}/${id}`,
74770
75529
  {},
74771
75530
  new Blob([png], { type: "image/png" }),
74772
75531
  { ...options, fileFieldName: "image", filename }
74773
75532
  );
74774
75533
  if (out === null) {
74775
- throw new Error(`unexpected empty response from PUT ${BASE5}/${id} (image)`);
75534
+ throw new Error(`unexpected empty response from PUT ${BASE6}/${id} (image)`);
74776
75535
  }
74777
75536
  return out;
74778
75537
  }
74779
75538
 
74780
- // src/commands/_agentCli.ts
74781
- import { access } from "fs/promises";
74782
- var JSON_HELP = "Emit raw JSON to stdout instead of a pretty render.";
74783
- var CONFIRM_HELP = "Token from a prior plan run \u2014 required to actually write";
74784
- function withTarget(cmd) {
74785
- addServerFlag(cmd);
74786
- addAccountFlag(cmd);
74787
- return cmd;
74788
- }
74789
- function std() {
74790
- return { out: process.stdout, err: process.stderr };
74791
- }
74792
- function requireId(value, placeholder) {
74793
- const id = (value ?? "").trim();
74794
- if (id === "") {
74795
- throw new Error(`missing required option: --id ${placeholder}`);
74796
- }
74797
- return id;
74798
- }
74799
- function requirePositiveInt(value, flag) {
74800
- const n = /^\d+$/.test(value) ? Number(value) : NaN;
74801
- if (!Number.isSafeInteger(n) || n <= 0) {
74802
- throw new Error(`${flag} ${JSON.stringify(value)}: expected a positive integer`);
74803
- }
74804
- return n;
74805
- }
74806
- function requireBool(value, flag) {
74807
- if (value === "true") return true;
74808
- if (value === "false") return false;
74809
- throw new Error(`${flag} ${JSON.stringify(value ?? "")}: expected true or false`);
74810
- }
74811
- function splitList(value) {
74812
- return [
74813
- ...new Set(
74814
- (value ?? "").split(",").map((part) => part.trim()).filter((part) => part !== "")
74815
- )
74816
- ];
74817
- }
74818
- function isNoneSentinel(parts, flag, value, what) {
74819
- if (!parts.includes("none")) return false;
74820
- if (parts.length === 1) return true;
74821
- throw new Error(`${flag} ${JSON.stringify(value)}: "none" cannot be combined with ${what}`);
74822
- }
74823
- function shellArg(value) {
74824
- return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value) ? value : shellQuote(value);
74825
- }
74826
- function proseStream(cfg) {
74827
- return cfg.asJson ? cfg.err : cfg.out;
74828
- }
74829
- async function assertNoOverwrite(paths, force) {
74830
- if (force) return;
74831
- const existing = [];
74832
- for (const path13 of paths) {
74833
- try {
74834
- await access(path13);
74835
- existing.push(path13);
74836
- } catch {
74837
- }
74838
- }
74839
- if (existing.length > 0) {
74840
- throw new Error(
74841
- `refusing to overwrite existing file(s): ${existing.join(", ")}. Pull into another --dir, or pass --force to replace them.`
74842
- );
74843
- }
74844
- }
74845
-
74846
75539
  // src/commands/_templateLibraryImages.ts
74847
75540
  var TEMPLATE_LIBRARY_IMAGE_COLORS = ["pink", "purple", "yellow"];
74848
75541
  var TEMPLATE_LIBRARY_IMAGE_FILENAMES = {
@@ -75699,11 +76392,11 @@ import { mkdir as mkdir5, writeFile as writeFile8 } from "fs/promises";
75699
76392
  import { join as join18 } from "path";
75700
76393
 
75701
76394
  // src/api/aiService.ts
75702
- import { z as z3 } from "zod";
76395
+ import { z as z4 } from "zod";
75703
76396
  var AI_SERVICE_MINT_PATH = "/api/ai-service/v1/Authentication/authenticate";
75704
76397
  var ERROR_BODY_MAX_CHARS = 1e3;
75705
- var MintResponseSchema = z3.object({ token: z3.string().min(1) });
75706
- var ErrorEnvelopeSchema = z3.object({ code: z3.string(), message: z3.string() });
76398
+ var MintResponseSchema = z4.object({ token: z4.string().min(1) });
76399
+ var ErrorEnvelopeSchema = z4.object({ code: z4.string(), message: z4.string() });
75707
76400
  function parseErrorEnvelope(text2) {
75708
76401
  let parsed2;
75709
76402
  try {