@delegance/cli 0.2.1 → 0.3.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.
package/dist/index.js CHANGED
@@ -64,10 +64,10 @@ module.exports = __toCommonJS(index_exports);
64
64
 
65
65
  // src/commands/auth.ts
66
66
  var os4 = __toESM(require("os"));
67
- var import_commander2 = require("commander");
68
- var import_inquirer2 = __toESM(require("inquirer"));
67
+ var import_commander3 = require("commander");
68
+ var import_inquirer3 = __toESM(require("inquirer"));
69
69
  var import_ora2 = __toESM(require("ora"));
70
- var import_sdk3 = require("@delegance/sdk");
70
+ var import_sdk4 = require("@delegance/sdk");
71
71
 
72
72
  // src/utils/config.ts
73
73
  var import_conf = __toESM(require("conf"));
@@ -76,7 +76,7 @@ var path = __toESM(require("path"));
76
76
  var os = __toESM(require("os"));
77
77
 
78
78
  // src/version.ts
79
- var CLI_VERSION = "0.2.1";
79
+ var CLI_VERSION = "0.3.0";
80
80
 
81
81
  // src/utils/config.ts
82
82
  var CONFIG_DIR = path.join(os.homedir(), ".delegance");
@@ -229,6 +229,7 @@ __export(output_exports, {
229
229
  error: () => error,
230
230
  formatCurrency: () => formatCurrency,
231
231
  formatDate: () => formatDate,
232
+ formatDateOnly: () => formatDateOnly,
232
233
  formatFileSize: () => formatFileSize,
233
234
  formatStatus: () => formatStatus,
234
235
  header: () => header,
@@ -236,6 +237,7 @@ __export(output_exports, {
236
237
  json: () => json,
237
238
  keyValue: () => keyValue,
238
239
  output: () => output,
240
+ renderCompactTable: () => renderCompactTable,
239
241
  success: () => success,
240
242
  table: () => table,
241
243
  warn: () => warn
@@ -298,12 +300,28 @@ function formatValue(value) {
298
300
  }
299
301
  return String(value);
300
302
  }
303
+ function visibleWidth(s) {
304
+ return s.replace(/\x1b\[[0-9;]*m/g, "").length;
305
+ }
306
+ function renderCompactTable(headers, rows) {
307
+ const cells = rows.map((r) => headers.map((_, i) => r[i] === null || r[i] === void 0 ? "-" : String(r[i])));
308
+ const widths = headers.map((h, i) => Math.max(visibleWidth(h), ...cells.map((r) => visibleWidth(r[i]))));
309
+ const line = (parts) => ` ${parts.map((p, i) => p + " ".repeat(widths[i] - visibleWidth(p))).join(" ")}`.replace(/\s+$/, "");
310
+ return [
311
+ line(headers.map((h) => import_chalk.default.bold(h))),
312
+ import_chalk.default.dim(line(widths.map((w) => "\u2500".repeat(w)))),
313
+ ...cells.map(line)
314
+ ].join("\n");
315
+ }
301
316
  function table(headers, rows, options = {}) {
317
+ if (options.compact) {
318
+ console.log(renderCompactTable(headers, rows));
319
+ return;
320
+ }
302
321
  const tbl = new import_cli_table3.default({
303
322
  head: headers.map((h) => import_chalk.default.bold(h)),
304
323
  style: {
305
- head: ["cyan"],
306
- compact: options.compact
324
+ head: ["cyan"]
307
325
  }
308
326
  });
309
327
  for (const row of rows) {
@@ -340,6 +358,15 @@ function formatDate(dateStr) {
340
358
  minute: "2-digit"
341
359
  });
342
360
  }
361
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
362
+ function formatDateOnly(iso) {
363
+ if (!iso) return "";
364
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso);
365
+ if (!m) return iso;
366
+ const month = MONTHS[Number(m[2]) - 1];
367
+ if (!month) return iso;
368
+ return `${month} ${Number(m[3])}, ${m[1]}`;
369
+ }
343
370
  function formatFileSize(bytes) {
344
371
  if (bytes === void 0) return import_chalk.default.gray("(unknown)");
345
372
  const units = ["B", "KB", "MB", "GB"];
@@ -409,14 +436,26 @@ function noteTraceId(traceId) {
409
436
  if (current && typeof traceId === "string" && TRACE_RE.test(traceId)) current.traceId = traceId;
410
437
  }
411
438
 
439
+ // src/utils/invocation.ts
440
+ var NPX_INVOCATION = "npx -y @delegance/cli";
441
+ function cliInvocation(env = process.env, argv = process.argv) {
442
+ const entry = (argv[1] ?? "").replace(/\\/g, "/");
443
+ if (entry.includes("/_npx/")) return NPX_INVOCATION;
444
+ if (env.npm_command === "exec" && /(^|\/)delegance(\.[cm]?js)?$/.test(entry)) return NPX_INVOCATION;
445
+ return "delegance";
446
+ }
447
+ function cliCommand(rest) {
448
+ return `${cliInvocation()} ${rest}`;
449
+ }
450
+
412
451
  // src/utils/client.ts
413
452
  var PORTAL_URL = "https://portal.delegancebrokerage.com";
414
453
  function getClient() {
415
454
  const apiKey = getApiKey();
416
455
  if (!apiKey) {
417
456
  error("Not authenticated");
418
- info('New to Delegance? Run "delegance signup" to create an account.');
419
- info('Have an API key? Run "delegance auth login", or set DELEGANCE_API_KEY.');
457
+ info(`New to Delegance? Run "${cliInvocation()} signup" to create an account.`);
458
+ info(`Have an API key? Run "${cliInvocation()} auth login", or set DELEGANCE_API_KEY.`);
420
459
  process.exit(1);
421
460
  }
422
461
  return new import_sdk.DeleganceClient({
@@ -428,7 +467,7 @@ function getCompanyId(options) {
428
467
  const companyId = options.company || getConfigValue("defaultCompanyId");
429
468
  if (!companyId) {
430
469
  error("No company specified");
431
- info('Use --company <id> or set a default with "delegance company use <id>"');
470
+ info(`Use --company <id> or set a default with "${cliInvocation()} company use <id>"`);
432
471
  process.exit(1);
433
472
  }
434
473
  return companyId;
@@ -440,9 +479,9 @@ function describeApiError(err) {
440
479
  }
441
480
  if (err instanceof import_sdk.AuthenticationError) {
442
481
  if (err.reason === "key_expired" || err.reason === "key_membership_revoked") {
443
- return { message: `${err.message}${traceSuffix}`, hint: 'Run "delegance auth login" to sign in again.' };
482
+ return { message: `${err.message}${traceSuffix}`, hint: `Run "${cliInvocation()} auth login" to sign in again.` };
444
483
  }
445
- return { message: `${err.message}${traceSuffix}`, hint: 'Check your key with "delegance auth status", or log in again.' };
484
+ return { message: `${err.message}${traceSuffix}`, hint: `Check your key with "${cliInvocation()} auth status", or log in again.` };
446
485
  }
447
486
  if (err instanceof import_sdk.ForbiddenError) {
448
487
  return { message: `${err.message}${traceSuffix}`, hint: "Your API key lacks the scope for this command. Create a key with the right scope in the portal." };
@@ -503,10 +542,10 @@ function openInBrowser(url, platform = process.platform) {
503
542
 
504
543
  // src/commands/signup.ts
505
544
  var import_crypto = require("crypto");
506
- var import_commander = require("commander");
507
- var import_inquirer = __toESM(require("inquirer"));
545
+ var import_commander2 = require("commander");
546
+ var import_inquirer2 = __toESM(require("inquirer"));
508
547
  var import_ora = __toESM(require("ora"));
509
- var import_sdk2 = require("@delegance/sdk");
548
+ var import_sdk3 = require("@delegance/sdk");
510
549
 
511
550
  // src/utils/pending-signup.ts
512
551
  var fs3 = __toESM(require("fs"));
@@ -547,6 +586,82 @@ function clearPendingSignup(home) {
547
586
  }
548
587
  }
549
588
 
589
+ // src/commands/terms.ts
590
+ var import_commander = require("commander");
591
+ var import_inquirer = __toESM(require("inquirer"));
592
+ var import_sdk2 = require("@delegance/sdk");
593
+ function termsAcceptRefusal(prompted) {
594
+ if (!prompted) {
595
+ return { kind: "error", message: `No prompt to answer. Read the Terms, then run "${cliCommand("terms accept --yes")}".` };
596
+ }
597
+ return { kind: "warn", message: "Not accepted. You can still quote; binding needs the current Terms." };
598
+ }
599
+ function termsLines(t) {
600
+ return [
601
+ `Delegance Terms of Service (version ${t.version}): ${t.termsUrl}`,
602
+ `Privacy Policy: ${t.privacyUrl}`,
603
+ ...t.summaries
604
+ ];
605
+ }
606
+ async function confirmTerms(t, opts) {
607
+ termsLines(t).forEach((l) => (opts.print ?? info)(l));
608
+ if (opts.flag) return true;
609
+ if (!opts.interactive) return false;
610
+ const ask = opts.ask ?? (async () => {
611
+ const a = await import_inquirer.default.prompt([{
612
+ type: "confirm",
613
+ name: "ok",
614
+ message: "Do you accept the Terms of Service and Privacy Policy?",
615
+ default: false
616
+ }]);
617
+ return a.ok === true;
618
+ });
619
+ return ask();
620
+ }
621
+ function createTermsCommand() {
622
+ const cmd = new import_commander.Command("terms").description("Show the Delegance Terms of Service, or accept the current version").option("--json", "Output as JSON").action(async (options) => {
623
+ try {
624
+ const t = await (0, import_sdk2.createSignup)({ baseUrl: getBaseUrl() }).getTerms();
625
+ if (options.json) {
626
+ json(t);
627
+ return;
628
+ }
629
+ termsLines(t).forEach((l) => info(l));
630
+ info(`Broker review before you bind: ${t.brokerReview.command}, or email ${t.brokerReview.email}`);
631
+ } catch (err) {
632
+ failWith("Could not load the Terms", err);
633
+ }
634
+ });
635
+ cmd.command("accept").description("Accept the current Terms of Service for your account (a bind can require it)").option("-y, --yes", "Accept without the prompt (you have read the Terms)").option("--json", "Output as JSON").action(async (options) => {
636
+ const client = getClient();
637
+ try {
638
+ const t = await client.terms.get();
639
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json;
640
+ const ok = await confirmTerms(t, {
641
+ flag: options.yes === true,
642
+ interactive,
643
+ // --json keeps stdout to one JSON document; the Terms still print, on stderr.
644
+ ...options.json ? { print: (l) => console.error(l) } : {}
645
+ });
646
+ if (!ok) {
647
+ const refusal = termsAcceptRefusal(interactive);
648
+ if (refusal.kind === "error") error(refusal.message);
649
+ else warn(refusal.message);
650
+ process.exit(1);
651
+ }
652
+ const r = await client.terms.accept(t.version);
653
+ if (options.json) {
654
+ json(r);
655
+ return;
656
+ }
657
+ success(`Accepted the Terms of Service, version ${r.version}.`);
658
+ } catch (err) {
659
+ failWith("Could not record your acceptance", err);
660
+ }
661
+ });
662
+ return cmd;
663
+ }
664
+
550
665
  // src/commands/signup.ts
551
666
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
552
667
  var COMPANY_SIZES = ["0", "1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"];
@@ -571,34 +686,72 @@ function addressProblem(a) {
571
686
  if (!/^\d{5}(-\d{4})?$/.test(a.zip.trim())) return "ZIP must be 5 digits (or ZIP+4).";
572
687
  return null;
573
688
  }
689
+ var TERMS_REASONS = /* @__PURE__ */ new Set(["terms_not_accepted", "terms_version_outdated"]);
690
+ function isTermsRefusal(err) {
691
+ return err instanceof import_sdk3.DeleganceError && TERMS_REASONS.has(String(err.reason ?? ""));
692
+ }
693
+ async function loadSignupTerms(get) {
694
+ try {
695
+ return await get();
696
+ } catch (err) {
697
+ if (err instanceof import_sdk3.DeleganceError && err.statusCode === 404) return null;
698
+ throw err;
699
+ }
700
+ }
701
+ async function loadSignupTermsOrExit(baseUrl) {
702
+ try {
703
+ return await loadSignupTerms(() => (0, import_sdk3.createSignup)({ baseUrl }).getTerms());
704
+ } catch (err) {
705
+ failWith("Could not load the Terms of Service", err);
706
+ }
707
+ }
708
+ function nonInteractiveMissing(options, terms) {
709
+ const missing = missingSignupFields(options);
710
+ if (terms && options.acceptTerms !== true) missing.push("--accept-terms");
711
+ return missing;
712
+ }
713
+ async function acceptTermsOrExit(baseUrl, flag, preloaded) {
714
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
715
+ const terms = preloaded === void 0 ? await loadSignupTermsOrExit(baseUrl) : preloaded;
716
+ if (!terms) return "";
717
+ const ok = await confirmTerms(terms, { flag, interactive });
718
+ if (!ok) {
719
+ if (interactive) warn("Not signed up. Delegance needs your acceptance of the Terms and Privacy Policy to open an account.");
720
+ else error("No terminal to ask in. Read the Terms and Privacy Policy above, then pass --accept-terms.");
721
+ process.exit(1);
722
+ }
723
+ return terms.version;
724
+ }
574
725
  function exchangeRefusal(err) {
575
- if (!(err instanceof import_sdk2.DeleganceError)) return null;
726
+ if (!(err instanceof import_sdk3.DeleganceError)) return null;
576
727
  switch (err.reason) {
577
728
  case "account_exists":
578
729
  return `This email already has a Delegance account, so signup did not attach it to a new one. Sign in and create a key at ${PORTAL_URL}/portal/settings/api-keys`;
579
730
  case "already_collected":
580
731
  return `The key for this signup was already collected. If you lost it, create a new key at ${PORTAL_URL}/portal/settings/api-keys`;
581
732
  case "expired":
582
- return 'This signup expired (24 hours). Run "delegance signup" again.';
733
+ return `This signup expired (24 hours). Run "${cliInvocation()} signup" again.`;
583
734
  default:
584
735
  return null;
585
736
  }
586
737
  }
587
738
  async function ensureEnrolled(pending) {
588
739
  if (pending.enrollmentId) return pending;
589
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
740
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
590
741
  const hash = (0, import_crypto.createHash)("sha256").update(pending.deviceSecret).digest("hex");
591
742
  const enrollment = await signup.enroll(pending.bootstrapKey, {
592
743
  deviceSecretHash: hash,
593
744
  firstName: pending.firstName ?? "",
594
- lastName: pending.lastName ?? ""
745
+ lastName: pending.lastName ?? "",
746
+ termsAccepted: true,
747
+ termsVersion: pending.termsVersion ?? ""
595
748
  });
596
749
  const next = { ...pending, enrollmentId: enrollment.enrollmentId, verificationSent: false };
597
750
  savePendingSignup(next);
598
751
  return sendVerification(next);
599
752
  }
600
753
  async function sendVerification(pending) {
601
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
754
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
602
755
  const next = { ...pending, verificationSent: true };
603
756
  savePendingSignup(next);
604
757
  return next;
@@ -609,14 +762,14 @@ function storeOrPrintKey(apiKey, store = storeApiKey) {
609
762
  return true;
610
763
  } catch (err) {
611
764
  error(`Could not save the key to ~/.delegance/credentials: ${err.message}`);
612
- warn('Your key is below. It is shown once. Save it now, then run "delegance auth login --key <key>".');
765
+ warn(`Your key is below. It is shown once. Save it now, then run "${cliInvocation()} auth login --key <key>".`);
613
766
  console.log(apiKey);
614
767
  return false;
615
768
  }
616
769
  }
617
770
  async function waitAndStore(pending, timeoutMs) {
618
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
619
- const spinner = (0, import_ora.default)(`Waiting for you to click the link sent to ${pending.email} (Ctrl-C is safe: resume with "delegance verify")`).start();
771
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
772
+ const spinner = (0, import_ora.default)(`Waiting for you to click the link sent to ${pending.email} (Ctrl-C is safe: resume with "${cliInvocation()} verify")`).start();
620
773
  const started = Date.now();
621
774
  try {
622
775
  const result = await signup.waitForKey(pending.enrollmentId, pending.deviceSecret, {
@@ -628,7 +781,7 @@ async function waitAndStore(pending, timeoutMs) {
628
781
  });
629
782
  if (result.status !== "ready") {
630
783
  spinner.warn("Still waiting on the email confirmation.");
631
- info('Run "delegance verify" after you click the link.');
784
+ info(`Run "${cliInvocation()} verify" after you click the link.`);
632
785
  return;
633
786
  }
634
787
  spinner.stop();
@@ -636,7 +789,7 @@ async function waitAndStore(pending, timeoutMs) {
636
789
  setConfig("defaultCompanyId", result.companyId);
637
790
  clearPendingSignup();
638
791
  if (stored) success(`Verified. API key ${maskApiKey(result.apiKey)} saved to ~/.delegance/credentials`);
639
- success("You can quote now: delegance quote start --coverage gl");
792
+ success(`You can quote now: ${cliInvocation()} quote start --coverage gl`);
640
793
  } catch (err) {
641
794
  spinner.stop();
642
795
  const why = exchangeRefusal(err);
@@ -666,21 +819,24 @@ function signupPrompts(options, interactive) {
666
819
  return all.filter((q) => q.when !== false).map(({ when: _when, ...q }) => q);
667
820
  }
668
821
  function createSignupCommand() {
669
- return new import_commander.Command("signup").description("Create a Delegance account and get an API key, from the terminal").option("-e, --email <email>", "Your work email (the confirm link goes here)").option("-b, --business <name>", "Business name").option("--first <name>", "Your first name").option("--last <name>", "Your last name").option("-i, --industry <industry>", 'What the business does, e.g. "commercial bakery"').option("--size <size>", `Employees: ${COMPANY_SIZES.join(", ")}`).option("-w, --website <url>", "Website (full URL)").option("--street <street>", "Business street address").option("--city <city>", "City").option("--state <state>", "State, 2-letter code (carriers quote by state)").option("--zip <zip>", "ZIP code").option("-d, --description <text>", "A sentence on what the business does (helps carriers classify it)").option("--timeout <minutes>", "How long to wait for the email click", "15").option("--no-wait", 'Send the email and exit; collect later with "delegance verify"').action(async (options) => {
822
+ return new import_commander2.Command("signup").description("Create a Delegance account and get an API key, from the terminal").option("-e, --email <email>", "Your work email (the confirm link goes here)").option("-b, --business <name>", "Business name").option("--first <name>", "Your first name").option("--last <name>", "Your last name").option("-i, --industry <industry>", 'What the business does, e.g. "commercial bakery"').option("--size <size>", `Employees: ${COMPANY_SIZES.join(", ")}`).option("-w, --website <url>", "Website (full URL)").option("--street <street>", "Business street address").option("--city <city>", "City").option("--state <state>", "State, 2-letter code (carriers quote by state)").option("--zip <zip>", "ZIP code").option("-d, --description <text>", "A sentence on what the business does (helps carriers classify it)").option("--accept-terms", "Accept the Terms of Service and Privacy Policy (shown before the account is created)").option("--timeout <minutes>", "How long to wait for the email click", "15").option("--no-wait", 'Send the email and exit; collect later with "delegance verify"').action(async (options) => {
670
823
  const existing = loadPendingSignup();
671
824
  if (existing) {
672
825
  warn(`A signup for ${existing.email} is already waiting for its email confirmation.`);
673
- info('Run "delegance verify" to finish it, or "delegance verify --cancel" to start over.');
826
+ info(`Run "${cliInvocation()} verify" to finish it, or "${cliInvocation()} verify --cancel" to start over.`);
674
827
  process.exit(1);
675
828
  }
829
+ const baseUrl = getBaseUrl();
830
+ let preloadedTerms;
676
831
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
677
- const missing = missingSignupFields(options);
832
+ preloadedTerms = await loadSignupTermsOrExit(baseUrl);
833
+ const missing = nonInteractiveMissing(options, preloadedTerms);
678
834
  if (missing.length) {
679
835
  error(`No terminal to ask in. Missing: ${missing.join(" ")}`);
680
836
  process.exit(1);
681
837
  }
682
838
  }
683
- const answers = await import_inquirer.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
839
+ const answers = await import_inquirer2.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
684
840
  const address = {
685
841
  street: String(options.street ?? answers.street).trim(),
686
842
  city: String(options.city ?? answers.city).trim(),
@@ -703,8 +859,8 @@ function createSignupCommand() {
703
859
  error(`--size must be one of: ${COMPANY_SIZES.join(", ")}`);
704
860
  process.exit(1);
705
861
  }
706
- const baseUrl = getBaseUrl();
707
- const signup = (0, import_sdk2.createSignup)({ baseUrl });
862
+ const termsVersion = await acceptTermsOrExit(baseUrl, options.acceptTerms === true, preloadedTerms);
863
+ const signup = (0, import_sdk3.createSignup)({ baseUrl });
708
864
  const spinner = (0, import_ora.default)("Creating your account...").start();
709
865
  try {
710
866
  const account = await signup.createAccount({
@@ -716,7 +872,7 @@ function createSignupCommand() {
716
872
  ...description ? { description } : {},
717
873
  ...options.website ? { website: options.website } : {}
718
874
  });
719
- const device = (0, import_sdk2.newDeviceSecret)();
875
+ const device = (0, import_sdk3.newDeviceSecret)();
720
876
  let pending = {
721
877
  enrollmentId: "",
722
878
  deviceSecret: device.secret,
@@ -725,6 +881,7 @@ function createSignupCommand() {
725
881
  email,
726
882
  firstName: String(options.first ?? answers.first).trim(),
727
883
  lastName: String(options.last ?? answers.last).trim(),
884
+ termsVersion,
728
885
  baseUrl,
729
886
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
730
887
  };
@@ -735,7 +892,7 @@ function createSignupCommand() {
735
892
  warn("We could not save your business address. Add it in the portal before quoting, or carriers cannot price you.");
736
893
  }
737
894
  if (options.wait === false) {
738
- info('After you click it, run "delegance verify" to collect your API key.');
895
+ info(`After you click it, run "${cliInvocation()} verify" to collect your API key.`);
739
896
  return;
740
897
  }
741
898
  await waitAndStore(pending, Number(options.timeout) * 6e4 || 15 * 6e4);
@@ -746,17 +903,17 @@ function createSignupCommand() {
746
903
  });
747
904
  }
748
905
  function resendFailureMessage(err) {
749
- if (err instanceof import_sdk2.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
906
+ if (err instanceof import_sdk3.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
750
907
  return "Your email is already confirmed, so there is nothing to re-send. Collecting your key now.";
751
908
  }
752
909
  const why = err instanceof Error ? err.message : String(err);
753
910
  return `Could not re-send the email (${why}). Still waiting for the link you already have.`;
754
911
  }
755
912
  function createVerifyCommand() {
756
- return new import_commander.Command("verify").description("Finish a signup: wait for the email click and store your API key").option("--resend", "Send the confirm email again").option("--cancel", "Forget the in-progress signup on this machine").option("--timeout <minutes>", "How long to wait", "15").action(async (options) => {
913
+ return new import_commander2.Command("verify").description("Finish a signup: wait for the email click and store your API key").option("--resend", "Send the confirm email again").option("--cancel", "Forget the in-progress signup on this machine").option("--accept-terms", "Accept the Terms of Service, if this signup has not recorded an acceptance yet").option("--timeout <minutes>", "How long to wait", "15").action(async (options) => {
757
914
  const pending = loadPendingSignup();
758
915
  if (!pending) {
759
- info('No signup is waiting on this machine. Start one with "delegance signup".');
916
+ info(`No signup is waiting on this machine. Start one with "${cliInvocation()} signup".`);
760
917
  return;
761
918
  }
762
919
  if (options.cancel) {
@@ -773,8 +930,21 @@ function createVerifyCommand() {
773
930
  failWith("Could not send the confirm email", err);
774
931
  }
775
932
  } else if (!pending.enrollmentId) {
933
+ let toEnroll = pending;
934
+ if (!pending.termsVersion) {
935
+ toEnroll = { ...pending, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
936
+ savePendingSignup(toEnroll);
937
+ }
776
938
  try {
777
- resumed = await ensureEnrolled(pending);
939
+ try {
940
+ resumed = await ensureEnrolled(toEnroll);
941
+ } catch (err) {
942
+ if (!isTermsRefusal(err)) throw err;
943
+ warn("The Terms of Service changed since this signup started. Review them again.");
944
+ toEnroll = { ...toEnroll, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
945
+ savePendingSignup(toEnroll);
946
+ resumed = await ensureEnrolled(toEnroll);
947
+ }
778
948
  success(`Finished setting up the signup. We emailed a confirm link to ${pending.email}.`);
779
949
  } catch (err) {
780
950
  failWith("Could not finish the signup", err);
@@ -782,7 +952,7 @@ function createVerifyCommand() {
782
952
  }
783
953
  if (options.resend && resumed === pending) {
784
954
  try {
785
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
955
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
786
956
  success(`Sent the confirm link to ${pending.email} again.`);
787
957
  } catch (err) {
788
958
  info(resendFailureMessage(err));
@@ -813,27 +983,27 @@ function describeExpiry(expiresAt, now = /* @__PURE__ */ new Date()) {
813
983
  return `${date} (in ${days} day${days === 1 ? "" : "s"})`;
814
984
  }
815
985
  function deviceLoginRefusal(err) {
816
- if (!(err instanceof import_sdk3.DeleganceError)) return null;
986
+ if (!(err instanceof import_sdk4.DeleganceError)) return null;
817
987
  switch (err.reason) {
818
988
  case "access_denied":
819
989
  return "The request was denied in the portal. Nothing was stored.";
820
990
  case "expired":
821
- return 'The code expired before it was approved. Run "delegance auth login" again.';
991
+ return `The code expired before it was approved. Run "${cliInvocation()} auth login" again.`;
822
992
  case "already_collected":
823
- return 'This login was already used. Run "delegance auth login" again.';
993
+ return `This login was already used. Run "${cliInvocation()} auth login" again.`;
824
994
  default:
825
995
  return null;
826
996
  }
827
997
  }
828
998
  function notAvailable(err) {
829
- return err instanceof import_sdk3.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
999
+ return err instanceof import_sdk4.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
830
1000
  }
831
1001
  function pasteFallbackHint() {
832
- info(`Create a key at ${PORTAL_URL}/portal/settings/api-keys, then run "delegance auth login --key <key>".`);
1002
+ info(`Create a key at ${PORTAL_URL}/portal/settings/api-keys, then run "${cliInvocation()} auth login --key <key>".`);
833
1003
  }
834
1004
  async function readKeyInfo(apiKey, timeoutMs = 5e3) {
835
1005
  try {
836
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
1006
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
837
1007
  return await client.auth.keyInfo();
838
1008
  } catch {
839
1009
  return null;
@@ -854,7 +1024,7 @@ async function loginWithKey(apiKey, skipVerify) {
854
1024
  }
855
1025
  const spinner = (0, import_ora2.default)("Verifying API key...").start();
856
1026
  try {
857
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1027
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
858
1028
  const isValid = await client.verifyApiKey();
859
1029
  if (!isValid) {
860
1030
  spinner.fail("API key verification failed");
@@ -875,8 +1045,8 @@ async function loginWithKey(apiKey, skipVerify) {
875
1045
  }
876
1046
  }
877
1047
  async function loginWithBrowser(openBrowser) {
878
- const login = (0, import_sdk3.createDeviceLogin)({ baseUrl: getBaseUrl() });
879
- const device = (0, import_sdk3.newDeviceSecret)();
1048
+ const login = (0, import_sdk4.createDeviceLogin)({ baseUrl: getBaseUrl() });
1049
+ const device = (0, import_sdk4.newDeviceSecret)();
880
1050
  let start;
881
1051
  try {
882
1052
  start = await login.start({ deviceSecretHash: device.hash, deviceName: defaultDeviceName() });
@@ -906,7 +1076,7 @@ async function loginWithBrowser(openBrowser) {
906
1076
  });
907
1077
  if (result.status !== "ready") {
908
1078
  spinner.fail("The code expired before it was approved.");
909
- info('Run "delegance auth login" again.');
1079
+ info(`Run "${cliInvocation()} auth login" again.`);
910
1080
  process.exit(1);
911
1081
  }
912
1082
  spinner.stop();
@@ -930,7 +1100,7 @@ async function loginWithBrowser(openBrowser) {
930
1100
  }
931
1101
  }
932
1102
  function createAuthCommand() {
933
- const auth = new import_commander2.Command("auth").description("Manage authentication");
1103
+ const auth = new import_commander3.Command("auth").description("Manage authentication");
934
1104
  auth.command("login").description("Sign in: approve this terminal in the portal, or store an API key").option("-k, --key <apiKey>", "Store this API key instead of signing in with the browser").option("--paste", "Prompt for an API key instead of signing in with the browser").option("--no-browser", "Print the approval link without opening a browser").option("--skip-verify", "With --key or --paste: store without verification (useful when API is not reachable)").action(async (options) => {
935
1105
  try {
936
1106
  if (options.key) {
@@ -938,7 +1108,7 @@ function createAuthCommand() {
938
1108
  return;
939
1109
  }
940
1110
  if (options.paste) {
941
- const answers = await import_inquirer2.default.prompt([
1111
+ const answers = await import_inquirer3.default.prompt([
942
1112
  {
943
1113
  type: "password",
944
1114
  name: "apiKey",
@@ -963,7 +1133,7 @@ function createAuthCommand() {
963
1133
  header("Authentication Status");
964
1134
  if (!isAuthenticated()) {
965
1135
  warn("Not authenticated");
966
- info('Run "delegance auth login" to sign in, or "delegance signup" to create an account');
1136
+ info(`Run "${cliInvocation()} auth login" to sign in, or "${cliInvocation()} signup" to create an account`);
967
1137
  return;
968
1138
  }
969
1139
  const apiKey = getApiKey() || "";
@@ -973,20 +1143,20 @@ function createAuthCommand() {
973
1143
  let origin = null;
974
1144
  let refused = null;
975
1145
  try {
976
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
1146
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
977
1147
  const keyInfo = await client.auth.keyInfo();
978
1148
  origin = keyInfo.origin;
979
1149
  expiryLine = describeExpiry(keyInfo.expiresAt);
980
1150
  if (!fromEnv) setStoredKeyExpiry(keyInfo.expiresAt);
981
1151
  } catch (err) {
982
- if (err instanceof import_sdk3.DeleganceError && err.statusCode === 401) {
1152
+ if (err instanceof import_sdk4.DeleganceError && err.statusCode === 401) {
983
1153
  refused = err.reason === "key_expired" ? "Your API key expired" : err.reason === "key_membership_revoked" ? "Your API key was revoked: its user is no longer an active member of the company" : "Your API key was rejected by the server";
984
1154
  expiryLine = err.reason === "key_expired" ? "Expired" : "Not valid";
985
1155
  }
986
1156
  }
987
1157
  if (refused) {
988
1158
  warn(refused);
989
- info('Run "delegance auth login" to sign in again.');
1159
+ info(`Run "${cliInvocation()} auth login" to sign in again.`);
990
1160
  } else {
991
1161
  success("Authenticated");
992
1162
  }
@@ -1004,18 +1174,18 @@ function createAuthCommand() {
1004
1174
  const apiKey = getApiKey();
1005
1175
  if (!apiKey) {
1006
1176
  error("Not authenticated");
1007
- info('Run "delegance auth login" to sign in');
1177
+ info(`Run "${cliInvocation()} auth login" to sign in`);
1008
1178
  process.exit(1);
1009
1179
  }
1010
1180
  const spinner = (0, import_ora2.default)("Refreshing your key...").start();
1011
1181
  try {
1012
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1182
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1013
1183
  const { expiresAt } = await client.auth.refresh();
1014
1184
  if (!process.env.DELEGANCE_API_KEY) setStoredKeyExpiry(expiresAt);
1015
1185
  spinner.succeed(`Key refreshed. Expires ${describeExpiry(expiresAt)}.`);
1016
1186
  } catch (err) {
1017
1187
  spinner.stop();
1018
- if (err instanceof import_sdk3.DeleganceError && err.reason === "not_refreshable") {
1188
+ if (err instanceof import_sdk4.DeleganceError && err.reason === "not_refreshable") {
1019
1189
  info("This key came from the portal and keeps the expiry it was created with. Nothing changed.");
1020
1190
  return;
1021
1191
  }
@@ -1032,7 +1202,7 @@ function createAuthCommand() {
1032
1202
  return;
1033
1203
  }
1034
1204
  if (!options.force) {
1035
- const { confirm } = await import_inquirer2.default.prompt([
1205
+ const { confirm } = await import_inquirer3.default.prompt([
1036
1206
  {
1037
1207
  type: "confirm",
1038
1208
  name: "confirm",
@@ -1052,7 +1222,7 @@ function createAuthCommand() {
1052
1222
  auth.command("whoami").description("Show current authenticated identity").action(async () => {
1053
1223
  if (!isAuthenticated()) {
1054
1224
  error("Not authenticated");
1055
- info('Run "delegance auth login" to authenticate');
1225
+ info(`Run "${cliInvocation()} auth login" to authenticate`);
1056
1226
  process.exit(1);
1057
1227
  }
1058
1228
  const apiKey = getApiKey();
@@ -1062,7 +1232,7 @@ function createAuthCommand() {
1062
1232
  }
1063
1233
  const spinner = (0, import_ora2.default)("Fetching account info...").start();
1064
1234
  try {
1065
- const client = new import_sdk3.DeleganceClient({
1235
+ const client = new import_sdk4.DeleganceClient({
1066
1236
  apiKey,
1067
1237
  baseUrl: getBaseUrl()
1068
1238
  });
@@ -1090,11 +1260,11 @@ function createAuthCommand() {
1090
1260
  }
1091
1261
 
1092
1262
  // src/commands/company.ts
1093
- var import_commander3 = require("commander");
1094
- var import_inquirer3 = __toESM(require("inquirer"));
1263
+ var import_commander4 = require("commander");
1264
+ var import_inquirer4 = __toESM(require("inquirer"));
1095
1265
  var import_ora3 = __toESM(require("ora"));
1096
1266
  function createCompanyCommand() {
1097
- const company = new import_commander3.Command("company").alias("companies").description("Manage companies");
1267
+ const company = new import_commander4.Command("company").alias("companies").description("Manage companies");
1098
1268
  company.command("list").description("List companies").option("--include-created", "Include companies created via this API key").option("--json", "Output as JSON").action(async (options) => {
1099
1269
  const client = getClient();
1100
1270
  const spinner = (0, import_ora3.default)("Fetching companies...").start();
@@ -1130,7 +1300,7 @@ function createCompanyCommand() {
1130
1300
  company.command("create").description("Create a new company").option("-n, --name <name>", "Company name").option("-i, --industry <industry>", "Industry").option("-s, --size <size>", "Company size (1, 2-10, 11-25, 26-50, 51-100, 100-499, 500+)").option("-e, --email <email>", "Contact email").option("--fein <fein>", "FEIN (XX-XXXXXXX)").option("--website <url>", "Website URL").option("--external-id <id>", "External ID for deduplication").option("--interactive", "Interactive mode with prompts").option("--json", "Output as JSON").action(async (options) => {
1131
1301
  let companyData;
1132
1302
  if (options.interactive || !options.name && !options.industry) {
1133
- const answers = await import_inquirer3.default.prompt([
1303
+ const answers = await import_inquirer4.default.prompt([
1134
1304
  {
1135
1305
  type: "input",
1136
1306
  name: "name",
@@ -1248,7 +1418,7 @@ function createCompanyCommand() {
1248
1418
  const companyId = getConfigValue("defaultCompanyId");
1249
1419
  if (!companyId) {
1250
1420
  info("No default company set");
1251
- info('Use "delegance company use <id>" to set one');
1421
+ info(`Use "${cliInvocation()} company use <id>" to set one`);
1252
1422
  return;
1253
1423
  }
1254
1424
  const client = getClient();
@@ -1276,7 +1446,7 @@ function createCompanyCommand() {
1276
1446
  }
1277
1447
 
1278
1448
  // src/commands/document.ts
1279
- var import_commander4 = require("commander");
1449
+ var import_commander5 = require("commander");
1280
1450
  var import_ora4 = __toESM(require("ora"));
1281
1451
  var fs4 = __toESM(require("fs"));
1282
1452
  var path4 = __toESM(require("path"));
@@ -1287,7 +1457,7 @@ function extractionOutcome(status) {
1287
1457
  return "pending";
1288
1458
  }
1289
1459
  function createDocumentCommand() {
1290
- const doc = new import_commander4.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1460
+ const doc = new import_commander5.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1291
1461
  doc.command("upload <files...>").description("Upload one or more documents").option("-c, --company <id>", "Company ID (or use default)").option("-t, --type <type>", "Document type (policy, loss_run, financial_statement, sov, application, certificate, endorsement, bor, other)").option("--external-id <id>", "External ID for reference").option("-w, --wait", "Wait for extraction to complete").option("--timeout <ms>", "Timeout for waiting (default: 120000)", "120000").option("--json", "Output as JSON").action(async (filePatterns, options) => {
1292
1462
  const companyId = getCompanyId(options);
1293
1463
  const client = getClient();
@@ -1522,7 +1692,7 @@ function createDocumentCommand() {
1522
1692
  process.exit(1);
1523
1693
  } else {
1524
1694
  waitSpinner.warn(`Extraction still ${finished.status}`);
1525
- if (!options.json) info(`Run "delegance doc wait ${documentId}" to keep following it`);
1695
+ if (!options.json) info(`Run "${cliInvocation()} doc wait ${documentId}" to keep following it`);
1526
1696
  }
1527
1697
  return;
1528
1698
  }
@@ -1530,7 +1700,7 @@ function createDocumentCommand() {
1530
1700
  json(result);
1531
1701
  } else {
1532
1702
  info(`${result.reprocessesRemaining} reprocess attempts left today`);
1533
- info(`Run "delegance doc wait ${documentId}" to follow it`);
1703
+ info(`Run "${cliInvocation()} doc wait ${documentId}" to follow it`);
1534
1704
  }
1535
1705
  } catch (err) {
1536
1706
  spinner.fail("Failed to reprocess document");
@@ -1565,11 +1735,11 @@ function createDocumentCommand() {
1565
1735
  }
1566
1736
 
1567
1737
  // src/commands/chat.ts
1568
- var import_commander5 = require("commander");
1738
+ var import_commander6 = require("commander");
1569
1739
  var import_ora5 = __toESM(require("ora"));
1570
- var import_inquirer4 = __toESM(require("inquirer"));
1740
+ var import_inquirer5 = __toESM(require("inquirer"));
1571
1741
  function createChatCommand() {
1572
- const chat = new import_commander5.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1742
+ const chat = new import_commander6.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1573
1743
  chat.command("query <question...>").alias("q").description("Ask a single question").option("-c, --conversation <id>", "Continue a previous conversation").option("--json", "Output as JSON").action(async (questionParts, options) => {
1574
1744
  const question = questionParts.join(" ");
1575
1745
  const client = getClient();
@@ -1605,7 +1775,7 @@ function createChatCommand() {
1605
1775
  console.log('Type your questions. Enter "exit" or "quit" to end the session.');
1606
1776
  console.log();
1607
1777
  while (true) {
1608
- const { question } = await import_inquirer4.default.prompt([
1778
+ const { question } = await import_inquirer5.default.prompt([
1609
1779
  {
1610
1780
  type: "input",
1611
1781
  name: "question",
@@ -1665,18 +1835,102 @@ function createChatCommand() {
1665
1835
  }
1666
1836
 
1667
1837
  // src/commands/quote.ts
1668
- var import_commander6 = require("commander");
1838
+ var import_commander7 = require("commander");
1669
1839
  var import_ora7 = __toESM(require("ora"));
1670
- var import_inquirer6 = __toESM(require("inquirer"));
1671
- var import_sdk5 = require("@delegance/sdk");
1840
+ var import_inquirer7 = __toESM(require("inquirer"));
1841
+ var import_sdk6 = require("@delegance/sdk");
1672
1842
 
1673
1843
  // src/commands/instant-quote.ts
1674
1844
  var fs5 = __toESM(require("fs"));
1675
1845
  var import_crypto2 = require("crypto");
1676
1846
  var import_chalk2 = __toESM(require("chalk"));
1677
- var import_inquirer5 = __toESM(require("inquirer"));
1847
+ var import_inquirer6 = __toESM(require("inquirer"));
1678
1848
  var import_ora6 = __toESM(require("ora"));
1679
- var import_sdk4 = require("@delegance/sdk");
1849
+ var import_sdk5 = require("@delegance/sdk");
1850
+
1851
+ // src/utils/coverage-names.ts
1852
+ var NAMES = {
1853
+ // General liability
1854
+ cgl: "General Liability",
1855
+ gl: "General Liability",
1856
+ general_liability: "General Liability",
1857
+ // Workers' comp
1858
+ wc: "Workers' Comp",
1859
+ workers_comp: "Workers' Comp",
1860
+ workers_compensation: "Workers' Comp",
1861
+ // Business owner's policy
1862
+ bop: "Business Owner's Policy",
1863
+ business_owners: "Business Owner's Policy",
1864
+ business_owners_policy: "Business Owner's Policy",
1865
+ // Cyber
1866
+ cyber: "Cyber",
1867
+ cyber_liability: "Cyber",
1868
+ // Professional liability (E&O)
1869
+ mpl: "Professional Liability (E&O)",
1870
+ pl: "Professional Liability (E&O)",
1871
+ pro_liab: "Professional Liability (E&O)",
1872
+ professional_liability: "Professional Liability (E&O)",
1873
+ eo: "Professional Liability (E&O)",
1874
+ e_o: "Professional Liability (E&O)",
1875
+ tech_eo: "Tech E&O",
1876
+ errors_omissions: "Tech E&O",
1877
+ // Auto
1878
+ ca: "Commercial Auto",
1879
+ auto: "Commercial Auto",
1880
+ commercial_auto: "Commercial Auto",
1881
+ // Property
1882
+ cp: "Commercial Property",
1883
+ property: "Commercial Property",
1884
+ commercial_property: "Commercial Property",
1885
+ // Umbrella
1886
+ umbrella: "Umbrella",
1887
+ excess: "Umbrella",
1888
+ commercial_umbrella: "Umbrella",
1889
+ // Builders risk
1890
+ br: "Builders' Risk",
1891
+ builders_risk: "Builders' Risk",
1892
+ // Inland marine and marine
1893
+ im: "Inland Marine",
1894
+ inland_marine: "Inland Marine",
1895
+ marine: "Marine",
1896
+ // Management liability family
1897
+ ml: "Management Liability",
1898
+ management_liability: "Management Liability",
1899
+ do: "Directors and Officers (D&O)",
1900
+ d_o: "Directors and Officers (D&O)",
1901
+ directors_officers: "Directors and Officers (D&O)",
1902
+ epli: "Employment Practices Liability",
1903
+ employment_practices: "Employment Practices Liability",
1904
+ crime: "Crime",
1905
+ fiduciary: "Fiduciary Liability",
1906
+ fiduciary_liability: "Fiduciary Liability",
1907
+ // Everything else on the canonical list
1908
+ product_liability: "Product Liability",
1909
+ liquor_liability: "Liquor Liability",
1910
+ contractors_liability: "Contractors' Liability",
1911
+ equipment_breakdown: "Equipment Breakdown",
1912
+ environmental_liability: "Environmental Liability",
1913
+ healthcare_medical: "Healthcare Medical Liability",
1914
+ life_sciences: "Life Sciences",
1915
+ hospitality_programs: "Hospitality Program",
1916
+ commercial_flood: "Commercial Flood",
1917
+ home_based_business: "Home-Based Business",
1918
+ foreign_package: "Foreign Package",
1919
+ multinational_package: "Multinational Package",
1920
+ political_risk: "Political Risk",
1921
+ trade_credit: "Trade Credit",
1922
+ kidnap_ransom: "Kidnap and Ransom",
1923
+ product_recall: "Product Recall",
1924
+ railroad_liability: "Railroad Liability"
1925
+ };
1926
+ function coverageName(code) {
1927
+ if (code === null || code === void 0) return "";
1928
+ const key = code.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1929
+ return NAMES[key] ?? code;
1930
+ }
1931
+ function coverageNames(codes) {
1932
+ return codes.map(coverageName).filter(Boolean).join(", ");
1933
+ }
1680
1934
 
1681
1935
  // src/commerce/questions.ts
1682
1936
  var COVERAGE_ALIASES = {
@@ -1756,14 +2010,23 @@ function validateAnswers(questions, provided) {
1756
2010
  }
1757
2011
  return { answers, problems };
1758
2012
  }
2013
+ function rowStatus(q) {
2014
+ if (String(q.state).toUpperCase() === "REFERRED") {
2015
+ return q.resultStatus === "needs_info" ? "needs_info" : "referred";
2016
+ }
2017
+ return q.marketStatus || q.state;
2018
+ }
1759
2019
  function sortQuoteRows(quotes) {
1760
2020
  return quotes.map((q) => ({
1761
2021
  carrier: q.carrierName || q.carrierId,
1762
2022
  coverage: q.coverage ?? "",
1763
2023
  premium: q.premium,
1764
- status: q.marketStatus || q.state,
2024
+ status: rowStatus(q),
1765
2025
  bindable: q.bindable === true && q.state === "QUOTED",
1766
- opportunityId: q.opportunityId
2026
+ opportunityId: q.opportunityId,
2027
+ limits: typeof q.limits === "string" && q.limits.trim() ? q.limits : null,
2028
+ deductible: typeof q.deductible === "number" && Number.isFinite(q.deductible) ? q.deductible : null,
2029
+ message: typeof q.message === "string" && q.message.trim() ? q.message.trim() : null
1767
2030
  })).sort((a, b) => {
1768
2031
  if (a.bindable !== b.bindable) return a.bindable ? -1 : 1;
1769
2032
  if (a.premium === null && b.premium === null) return 0;
@@ -1772,8 +2035,50 @@ function sortQuoteRows(quotes) {
1772
2035
  return a.premium - b.premium;
1773
2036
  });
1774
2037
  }
1775
- function cheapestBindable(rows) {
1776
- return rows.find((r) => r.bindable && r.premium !== null) ?? null;
2038
+ function bestPerCoverage(rows) {
2039
+ const best = /* @__PURE__ */ new Map();
2040
+ for (const r of rows) {
2041
+ if (!r.bindable || r.premium === null) continue;
2042
+ const key = coverageName(r.coverage);
2043
+ const cur = best.get(key);
2044
+ if (!cur || r.premium < cur.premium) best.set(key, r);
2045
+ }
2046
+ return [...best.values()].sort((a, b) => a.premium - b.premium);
2047
+ }
2048
+ function groupRowsByCoverage(rows) {
2049
+ const order = /* @__PURE__ */ new Map();
2050
+ rows.forEach((r) => {
2051
+ const key = coverageName(r.coverage);
2052
+ if (!order.has(key)) order.set(key, order.size);
2053
+ });
2054
+ const rank = (r) => order.get(coverageName(r.coverage));
2055
+ return rows.map((r, i) => ({ r, i })).sort((a, b) => rank(a.r) - rank(b.r) || a.i - b.i).map((x) => x.r);
2056
+ }
2057
+ var STATUS_WORDS = {
2058
+ quote: "Quoted",
2059
+ quoted: "Quoted",
2060
+ declined: "Declined",
2061
+ decline: "Declined",
2062
+ quoting: "Pricing",
2063
+ pending: "Pricing",
2064
+ submitted: "Pricing",
2065
+ in_progress: "Pricing",
2066
+ referred: "Referred to an underwriter",
2067
+ refer: "Referred to an underwriter",
2068
+ needs_info: "Needs more info",
2069
+ awaiting_broker_review: "With a broker",
2070
+ broker_review: "With a broker",
2071
+ bind_requested: "Bind requested",
2072
+ bound: "Bound",
2073
+ expired: "Expired",
2074
+ error: "Failed",
2075
+ failed: "Failed"
2076
+ };
2077
+ function quoteStatusWord(status) {
2078
+ const key = status.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_");
2079
+ if (STATUS_WORDS[key]) return STATUS_WORDS[key];
2080
+ const words = key.replace(/_/g, " ").trim();
2081
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : status;
1777
2082
  }
1778
2083
  function summarizeStatus(s) {
1779
2084
  const quoted = s.carrierQuotes.filter((q) => q.premium !== null).length;
@@ -1823,7 +2128,14 @@ function formatKnown(q, value) {
1823
2128
  }
1824
2129
 
1825
2130
  // src/commerce/demo.ts
1826
- var DEMO_BUSINESS = "Riverbend Bakery (demo), Austin TX, 6 employees";
2131
+ var DEMO_BUSINESS = "Riverbend Bakery (demo), Austin TX";
2132
+ var DEMO_SHORT_LABELS = {
2133
+ annual_revenue: "Annual revenue",
2134
+ employees: "Full-time employees",
2135
+ delivery: "Delivers orders",
2136
+ delivery_vehicles: "Delivery vehicles",
2137
+ claims_5y: "Claims in last 5 years"
2138
+ };
1827
2139
  var DEMO_QUESTIONS = [
1828
2140
  { id: "annual_revenue", label: "Annual revenue (USD)", type: "currency", required: true, prefill: 85e4 },
1829
2141
  { id: "employees", label: "Full-time employees", type: "number", required: true, prefill: 6 },
@@ -1857,6 +2169,7 @@ var DEMO_QUESTIONS = [
1857
2169
  ];
1858
2170
  var DEMO_STATUS = {
1859
2171
  submissionId: "demo-submission",
2172
+ effectiveDate: "2026-11-01",
1860
2173
  coverages: ["general_liability", "workers_comp"],
1861
2174
  expiresAt: null,
1862
2175
  submitted: true,
@@ -1864,19 +2177,19 @@ var DEMO_STATUS = {
1864
2177
  allCarriersResolved: true,
1865
2178
  awaitingBrokerReviewCount: 0,
1866
2179
  carrierQuotes: [
1867
- { opportunityId: "demo-1", carrierId: "CARRIER_A", carrierName: "Carrier A", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 612, quoteNumber: "DEMO-GL-1", bindable: true },
1868
- { opportunityId: "demo-2", carrierId: "CARRIER_B", carrierName: "Carrier B", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 748, quoteNumber: "DEMO-GL-2", bindable: true },
1869
- { opportunityId: "demo-3", carrierId: "CARRIER_C", carrierName: "Carrier C", coverage: "WC", state: "QUOTED", marketStatus: "quote", premium: 1184, quoteNumber: "DEMO-WC-1", bindable: true },
1870
- { opportunityId: "demo-4", carrierId: "CARRIER_D", carrierName: "Carrier D", coverage: "WC", state: "DECLINED", marketStatus: "declined", premium: null, quoteNumber: null, bindable: false }
2180
+ { opportunityId: "demo-1", carrierId: "CARRIER_A", carrierName: "Carrier A", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 612, quoteNumber: "DEMO-GL-1", bindable: true, limits: "$1M per occurrence / $2M aggregate", deductible: 500 },
2181
+ { opportunityId: "demo-2", carrierId: "CARRIER_B", carrierName: "Carrier B", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 748, quoteNumber: "DEMO-GL-2", bindable: true, limits: "$1M per occurrence / $2M aggregate", deductible: 1e3 },
2182
+ { opportunityId: "demo-3", carrierId: "CARRIER_C", carrierName: "Carrier C", coverage: "WC", state: "QUOTED", marketStatus: "quote", premium: 1184, quoteNumber: "DEMO-WC-1", bindable: true, limits: "Statutory / $1M employers liability", deductible: 0 },
2183
+ { opportunityId: "demo-4", carrierId: "CARRIER_D", carrierName: "Carrier D", coverage: "WC", state: "DECLINED", marketStatus: "declined", premium: null, quoteNumber: null, bindable: false, limits: null, deductible: null }
1871
2184
  ]
1872
2185
  };
1873
2186
 
1874
2187
  // src/commands/instant-quote.ts
1875
2188
  function activeRequestLines(err, coverageFlag) {
1876
- if (!(err instanceof import_sdk4.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
2189
+ if (!(err instanceof import_sdk5.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
1877
2190
  const { body } = err;
1878
2191
  const code = body.message;
1879
- const requote = `delegance quote start --coverage ${coverageFlag} --replace`;
2192
+ const requote = `${cliInvocation()} quote start --coverage ${coverageFlag} --replace`;
1880
2193
  if (code === "active_request_exists") {
1881
2194
  const active = Array.isArray(body.active) ? body.active : [];
1882
2195
  const first = active[0];
@@ -1884,7 +2197,7 @@ function activeRequestLines(err, coverageFlag) {
1884
2197
  const carriers = Array.isArray(first?.carriers) ? first.carriers.map((c) => `${c.carrierId}${c.state ? ` (${c.state.toLowerCase()})` : ""}`).join(", ") : "";
1885
2198
  return [
1886
2199
  `Already with carriers${id ? `: ${id}` : ""}${carriers ? `, ${carriers}` : ""}.`,
1887
- `Check it: ${id ? `delegance quote status ${id}` : "delegance quote status <id>"} Replace it: ${requote}`
2200
+ `Check it: ${id ? `${cliInvocation()} quote status ${id}` : `${cliInvocation()} quote status <id>`} Replace it: ${requote}`
1888
2201
  ];
1889
2202
  }
1890
2203
  if (code === "replace_conflict") {
@@ -1936,7 +2249,7 @@ async function askOne(q, answers, fallback) {
1936
2249
  }
1937
2250
  };
1938
2251
  }
1939
- const { v } = await import_inquirer5.default.prompt([prompt]);
2252
+ const { v } = await import_inquirer6.default.prompt([prompt]);
1940
2253
  const c = coerceAnswer(q, v);
1941
2254
  if (c.ok && c.value !== void 0) answers[q.id] = c.value;
1942
2255
  }
@@ -1947,7 +2260,7 @@ async function askQuestions(questions, answers = {}) {
1947
2260
  const round = planQuestionRound(questions, answers, handled);
1948
2261
  if (round.confirm.length + round.checklist.length + round.ask.length === 0) break;
1949
2262
  if (round.confirm.length) {
1950
- const { keep } = await import_inquirer5.default.prompt([
2263
+ const { keep } = await import_inquirer6.default.prompt([
1951
2264
  {
1952
2265
  type: "checkbox",
1953
2266
  name: "keep",
@@ -1976,7 +2289,7 @@ async function askQuestions(questions, answers = {}) {
1976
2289
  }
1977
2290
  }
1978
2291
  if (round.checklist.length) {
1979
- const { yes } = await import_inquirer5.default.prompt([
2292
+ const { yes } = await import_inquirer6.default.prompt([
1980
2293
  {
1981
2294
  type: "checkbox",
1982
2295
  name: "yes",
@@ -1987,7 +2300,7 @@ async function askQuestions(questions, answers = {}) {
1987
2300
  ]);
1988
2301
  const yn = checklistAnswers(round.checklist, yes);
1989
2302
  const yesCount = Object.values(yn).filter((v) => v === "yes").length;
1990
- const { ok } = await import_inquirer5.default.prompt([
2303
+ const { ok } = await import_inquirer6.default.prompt([
1991
2304
  { type: "confirm", name: "ok", message: `Yes to ${yesCount}, No to ${round.checklist.length - yesCount}. Correct?`, default: true }
1992
2305
  ]);
1993
2306
  if (ok) {
@@ -2011,7 +2324,7 @@ function handoffLines(r) {
2011
2324
  if (!r.alreadyHandedOff && r.unansweredRequired > 0) {
2012
2325
  lines.push(`The broker will email you for the ${r.unansweredRequired} answer(s) still missing.`);
2013
2326
  }
2014
- lines.push(`Check it: delegance quote status ${r.submissionId}`);
2327
+ lines.push(`Check it: ${cliInvocation()} quote status ${r.submissionId}`);
2015
2328
  return lines;
2016
2329
  }
2017
2330
  async function runBrokerHandoff(submissionId, instantAnswers, opts) {
@@ -2021,7 +2334,7 @@ async function runBrokerHandoff(submissionId, instantAnswers, opts) {
2021
2334
  try {
2022
2335
  plan = await client.instantQuotes.brokerHandoffQuestions(submissionId, instantAnswers);
2023
2336
  } catch (err) {
2024
- if (err instanceof import_sdk4.DeleganceError && err.statusCode === 503) {
2337
+ if (err instanceof import_sdk5.DeleganceError && err.statusCode === 503) {
2025
2338
  say("A broker can still market it: reply to the confirmation email, or start in the portal.");
2026
2339
  return;
2027
2340
  }
@@ -2052,7 +2365,7 @@ async function runBrokerHandoff(submissionId, instantAnswers, opts) {
2052
2365
  process.exit(1);
2053
2366
  }
2054
2367
  } else if (!opts.json && isInteractive() && plan.questions.length > 0) {
2055
- info(`A broker can place ${plan.coverages.join(", ")} with a market that quotes by hand. ${plan.questions.length} application question(s) left.`);
2368
+ info(`A broker can place ${coverageNames(plan.coverages)} with a market that quotes by hand. ${plan.questions.length} application question(s) left.`);
2056
2369
  info("Press Ctrl-C to stop at any point; what you have answered goes to the broker.");
2057
2370
  const onInterrupt = () => {
2058
2371
  complete = false;
@@ -2084,7 +2397,7 @@ async function sendHandoff(submissionId, input, idempotencyKey, asJson) {
2084
2397
  else handoffLines(result).forEach((l) => info(l));
2085
2398
  } catch (err) {
2086
2399
  spinner?.fail("Could not reach a broker");
2087
- console.error(`Try again: delegance quote handoff ${submissionId}`);
2400
+ console.error(`Try again: ${cliInvocation()} quote handoff ${submissionId}`);
2088
2401
  failWith("API error", err);
2089
2402
  }
2090
2403
  }
@@ -2095,8 +2408,34 @@ function printFloorDrops(failures) {
2095
2408
  floors.forEach((f) => console.log(` - ${f.carrierId}: ${f.missing}`));
2096
2409
  info("Add it to your business profile in the portal, then run the quote again.");
2097
2410
  }
2411
+ var AGENT_TIP = "Tip: your AI agent can do this for you. Open Claude Code, Codex, Gemini CLI or any coding agent in a folder with your insurance documents and ask it to get you a quote with npx -y @delegance/cli.";
2412
+ var premiumText = (n) => n === null ? "-" : formatCurrency(n);
2413
+ var deductibleText = (n) => n === null ? "-" : n === 0 ? "None" : formatCurrency(n);
2414
+ function bestPriceLines(best) {
2415
+ if (best.length === 0) return [];
2416
+ const names = best.map((r) => coverageName(r.coverage));
2417
+ const nameW = Math.max(...names.map((n) => n.length));
2418
+ const carrierW = Math.max(...best.map((r) => r.carrier.length));
2419
+ return [
2420
+ "Best price per coverage:",
2421
+ ...best.map((r, i) => ` ${names[i].padEnd(nameW)} ${r.carrier.padEnd(carrierW)} ${formatCurrency(r.premium)}/yr`)
2422
+ ];
2423
+ }
2424
+ function bindHintLines(submissionId, best) {
2425
+ if (best.length === 1) return [`Bind it: ${cliCommand(`bind ${submissionId} ${best[0].opportunityId}`)}`];
2426
+ return best.map((r) => `Bind ${coverageName(r.coverage)}: ${cliCommand(`bind ${submissionId} ${r.opportunityId}`)}`);
2427
+ }
2428
+ function demoClosingLines(best) {
2429
+ const example = best[0] ? ` (e.g. bind ... ${best[0].opportunityId})` : "";
2430
+ return [
2431
+ `Next, on a real quote: ${cliCommand("bind <quote id> <offer>")}${example}`,
2432
+ "DEMO: sample premiums, nothing went to a carrier.",
2433
+ `Get real quotes: ${cliCommand("signup")}`,
2434
+ AGENT_TIP
2435
+ ];
2436
+ }
2098
2437
  function printQuoteTable(status, opts = {}) {
2099
- const rows = sortQuoteRows(status.carrierQuotes);
2438
+ const rows = groupRowsByCoverage(sortQuoteRows(status.carrierQuotes));
2100
2439
  if (rows.length === 0) {
2101
2440
  if (status.brokerReview) {
2102
2441
  info(`A broker has this request (${status.brokerReview.status.replace(/_/g, " ")}). They place it by hand and email you with quotes or questions.`);
@@ -2106,25 +2445,67 @@ function printQuoteTable(status, opts = {}) {
2106
2445
  if (status.awaitingBrokerReviewCount > 0) info(`${status.awaitingBrokerReviewCount} quote(s) are with a broker for review.`);
2107
2446
  return;
2108
2447
  }
2109
- const best = cheapestBindable(rows);
2110
- if (best) {
2111
- console.log(import_chalk2.default.bold(`${opts.demo ? "[DEMO] " : ""}Cheapest bindable: ${best.carrier} ${best.coverage} at ${formatCurrency(best.premium)}/yr`));
2448
+ const best = bestPerCoverage(rows);
2449
+ const bestIds = new Set(best.map((r) => r.opportunityId));
2450
+ const effectiveDate = status.effectiveDate;
2451
+ console.log();
2452
+ if (effectiveDate && opts.showStartDate !== false) {
2453
+ console.log(`Coverage starts ${formatDateOnly(effectiveDate)}`);
2454
+ }
2455
+ const bestLines = bestPriceLines(best);
2456
+ if (bestLines.length) {
2457
+ console.log(import_chalk2.default.bold(bestLines[0]));
2458
+ bestLines.slice(1).forEach((l) => console.log(l));
2459
+ console.log();
2112
2460
  }
2113
2461
  table(
2114
- ["Carrier", "Coverage", "Premium/yr", "Status", "Bindable", "Offer id"],
2462
+ ["Carrier", "Coverage", "Premium/yr", "Limits", "Deductible", "Status", "Offer"],
2115
2463
  rows.map((r) => {
2116
- const cells = [r.carrier, r.coverage, r.premium === null ? "-" : formatCurrency(r.premium), r.status, r.bindable ? "yes" : "no", r.opportunityId];
2117
- return r === best ? cells.map((c) => import_chalk2.default.bold(String(c))) : cells;
2118
- })
2464
+ const cells = [
2465
+ r.carrier,
2466
+ coverageName(r.coverage),
2467
+ premiumText(r.premium),
2468
+ r.limits ?? "-",
2469
+ deductibleText(r.deductible),
2470
+ quoteStatusWord(r.status),
2471
+ r.opportunityId
2472
+ ];
2473
+ return bestIds.has(r.opportunityId) ? cells.map((c) => import_chalk2.default.bold(c)) : cells;
2474
+ }),
2475
+ { compact: true }
2119
2476
  );
2120
- console.log(import_chalk2.default.dim(summarizeStatus(status)));
2121
- if (best && !opts.demo) {
2122
- console.log(import_chalk2.default.green(`Bind it: delegance bind ${status.submissionId} ${best.opportunityId}`));
2477
+ const reasons = rows.filter((r) => r.message);
2478
+ if (reasons.length) {
2479
+ console.log();
2480
+ reasons.forEach((r) => console.log(`${r.carrier} (${quoteStatusWord(r.status)}): ${r.message}`));
2123
2481
  }
2124
- if (opts.demo) console.log(import_chalk2.default.yellow('DEMO: sample premiums, nothing was sent to a carrier. Run "delegance signup" for real quotes.'));
2482
+ console.log();
2483
+ console.log(import_chalk2.default.dim(`${summarizeStatus(status)}.`));
2484
+ if (opts.demo) {
2485
+ const [next, notice, signup, tip] = demoClosingLines(best);
2486
+ console.log(import_chalk2.default.green(next));
2487
+ console.log(import_chalk2.default.yellow(notice));
2488
+ console.log(import_chalk2.default.yellow(signup));
2489
+ console.log(import_chalk2.default.dim(tip));
2490
+ return;
2491
+ }
2492
+ bindHintLines(status.submissionId, best).forEach((l) => console.log(import_chalk2.default.green(l)));
2493
+ }
2494
+ function demoAnswerLines(answers, effectiveDate) {
2495
+ const pairs = [];
2496
+ for (const q of DEMO_QUESTIONS) {
2497
+ if (answers[q.id] === void 0) continue;
2498
+ const v = answers[q.id];
2499
+ const shown = q.type === "currency" && typeof v === "number" ? formatCurrency(v) : formatKnown(q, v);
2500
+ pairs.push([DEMO_SHORT_LABELS[q.id] ?? q.label, shown]);
2501
+ }
2502
+ if (effectiveDate) pairs.push(["Coverage starts", formatDateOnly(effectiveDate)]);
2503
+ const w = Math.max(...pairs.map(([k]) => k.length));
2504
+ return ["Sample answers (a real quote asks you these):", ...pairs.map(([k, v]) => ` ${k.padEnd(w)} ${v}`)];
2125
2505
  }
2126
2506
  async function runDemo(asJson, answersFile) {
2127
2507
  (asJson ? console.error : console.log)(import_chalk2.default.yellow(`DEMO quote for ${DEMO_BUSINESS}. Nothing leaves this machine.`));
2508
+ let printedStart = false;
2128
2509
  if (answersFile) {
2129
2510
  let provided;
2130
2511
  try {
@@ -2142,15 +2523,19 @@ async function runDemo(asJson, answersFile) {
2142
2523
  const mode = answerMode({ demo: true, hasAnswersFile: false, json: asJson, isTTY: isInteractive() });
2143
2524
  if (mode === "prompt") await askQuestions(DEMO_QUESTIONS);
2144
2525
  else {
2145
- suggestedAnswers(DEMO_QUESTIONS);
2146
- if (!asJson) info("No terminal to ask in, so the demo uses its suggested answers.");
2526
+ const assumed = suggestedAnswers(DEMO_QUESTIONS);
2527
+ if (!asJson) {
2528
+ demoAnswerLines(assumed, DEMO_STATUS.effectiveDate).forEach((l) => console.log(l));
2529
+ printedStart = true;
2530
+ }
2147
2531
  }
2148
2532
  }
2149
- const spinner = asJson ? null : (0, import_ora6.default)("Asking carriers (demo)...").start();
2533
+ const spinner = asJson ? null : (0, import_ora6.default)("Asking carriers (demo)...");
2534
+ if (spinner && process.stderr.isTTY) spinner.start();
2150
2535
  await new Promise((resolve) => setTimeout(resolve, asJson ? 0 : 1200));
2151
2536
  spinner?.succeed("4 carriers answered (demo)");
2152
2537
  if (asJson) json({ demo: true, ...DEMO_STATUS });
2153
- else printQuoteTable(DEMO_STATUS, { demo: true });
2538
+ else printQuoteTable(DEMO_STATUS, { demo: true, showStartDate: !printedStart });
2154
2539
  }
2155
2540
  function addInstantQuoteCommands(quote) {
2156
2541
  quote.command("start").description("Get instant quotes from real carriers: answers the questions, files them, waits for premiums").option("-c, --coverage <list>", "Coverages, comma-separated: gl, wc, bop, cyber, pl (E&O), auto, property, umbrella", "gl").option("-a, --answers <file>", "JSON file of answers keyed by question id (skips the prompts)").option("--demo", "Walk the flow on sample data; nothing is sent anywhere").option("--no-wait", 'File the quote and exit; check later with "quote status"').option("--timeout <minutes>", "How long to wait for premiums", "10").option("--replace", "Close the request already with carriers for this coverage and re-quote").option("--json", "Output as JSON").action(async (options) => {
@@ -2222,7 +2607,7 @@ function addInstantQuoteCommands(quote) {
2222
2607
  process.exit(1);
2223
2608
  }
2224
2609
  submitSpinner.fail("Submit failed");
2225
- console.error(`Before trying again, check whether it went through: delegance quote status ${session.submissionId}`);
2610
+ console.error(`Before trying again, check whether it went through: ${cliInvocation()} quote status ${session.submissionId}`);
2226
2611
  failWith("API error", err);
2227
2612
  }
2228
2613
  if (submitted.status === "no_carriers") {
@@ -2238,14 +2623,14 @@ function addInstantQuoteCommands(quote) {
2238
2623
  }
2239
2624
  if (submitted.status === "acord_pending") {
2240
2625
  submitSpinner.succeed("Sent to a broker: these coverages need a person, not an instant quote.");
2241
- info(`Track it with: delegance quote status ${session.submissionId}`);
2626
+ info(`Track it with: ${cliInvocation()} quote status ${session.submissionId}`);
2242
2627
  return;
2243
2628
  }
2244
2629
  submitSpinner.succeed(`Filed with ${submitted.quotes.filter((q) => q.status === "submitted").length} carrier(s).`);
2245
2630
  printFloorDrops(submitted.partialFailures);
2246
2631
  if (submitted.replaceNotice && !options.json) info(submitted.replaceNotice);
2247
2632
  if (options.wait === false) {
2248
- info(`Check premiums with: delegance quote status ${session.submissionId} --wait`);
2633
+ info(`Check premiums with: ${cliInvocation()} quote status ${session.submissionId} --wait`);
2249
2634
  return;
2250
2635
  }
2251
2636
  await waitAndPrint(session.submissionId, Number(options.timeout) * 6e4 || 6e5, !!options.json);
@@ -2274,11 +2659,11 @@ function addInstantQuoteCommands(quote) {
2274
2659
  }
2275
2660
  if (submitted.status !== "submitted") {
2276
2661
  info("Sent to a broker for these coverages.");
2277
- info(`Check it: delegance quote status ${submissionId}`);
2662
+ info(`Check it: ${cliInvocation()} quote status ${submissionId}`);
2278
2663
  return;
2279
2664
  }
2280
2665
  if (options.wait === false) {
2281
- info(`Check premiums with: delegance quote status ${submissionId} --wait`);
2666
+ info(`Check premiums with: ${cliInvocation()} quote status ${submissionId} --wait`);
2282
2667
  return;
2283
2668
  }
2284
2669
  await waitAndPrint(submissionId, Number(options.timeout) * 6e4 || 6e5, !!options.json);
@@ -2289,7 +2674,7 @@ function addInstantQuoteCommands(quote) {
2289
2674
  guardLines.forEach((l) => options.json ? console.error(l) : info(l));
2290
2675
  process.exit(1);
2291
2676
  }
2292
- console.error(`Before trying again, check whether it went through: delegance quote status ${submissionId}`);
2677
+ console.error(`Before trying again, check whether it went through: ${cliInvocation()} quote status ${submissionId}`);
2293
2678
  failWith("Submit failed", err);
2294
2679
  }
2295
2680
  });
@@ -2325,7 +2710,7 @@ async function waitAndPrint(submissionId, timeoutMs, asJson) {
2325
2710
  spinner?.stop();
2326
2711
  if (asJson) json(status);
2327
2712
  else printQuoteTable(status);
2328
- if (!status.allCarriersResolved && !asJson) info(`Some carriers are still working. Check again: delegance quote status ${submissionId} --wait`);
2713
+ if (!status.allCarriersResolved && !asJson) info(`Some carriers are still working. Check again: ${cliInvocation()} quote status ${submissionId} --wait`);
2329
2714
  } catch (err) {
2330
2715
  spinner?.fail("Could not read the quote");
2331
2716
  failWith("API error", err);
@@ -2335,7 +2720,7 @@ async function waitAndPrint(submissionId, timeoutMs, asJson) {
2335
2720
  // src/commands/quote.ts
2336
2721
  var QUOTE_SUBMISSION_UNAVAILABLE = "Quote submission via API isn't available yet";
2337
2722
  function createQuoteCommand() {
2338
- const quote = new import_commander6.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2723
+ const quote = new import_commander7.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2339
2724
  quote.command("carriers").description("List available carriers for quoting").option("--json", "Output as JSON").action(async (options) => {
2340
2725
  const client = getClient();
2341
2726
  const spinner = (0, import_ora7.default)("Fetching carriers...").start();
@@ -2382,7 +2767,7 @@ function createQuoteCommand() {
2382
2767
  process.exit(1);
2383
2768
  }
2384
2769
  if (options.interactive || carrierIds.length === 0 && !options.all) {
2385
- const { selectedCarriers } = await import_inquirer6.default.prompt([
2770
+ const { selectedCarriers } = await import_inquirer7.default.prompt([
2386
2771
  {
2387
2772
  type: "checkbox",
2388
2773
  name: "selectedCarriers",
@@ -2438,13 +2823,13 @@ function createQuoteCommand() {
2438
2823
  }
2439
2824
  console.log();
2440
2825
  info(`Queue IDs: ${result.queueIds.join(", ")}`);
2441
- info('Use "delegance quote list" to check status');
2826
+ info(`Use "${cliInvocation()} quote list" to check status`);
2442
2827
  }
2443
2828
  } catch (err) {
2444
2829
  spinner.fail("Failed to submit quote request");
2445
- if (err instanceof import_sdk5.NotImplementedError) {
2830
+ if (err instanceof import_sdk6.NotImplementedError) {
2446
2831
  error(QUOTE_SUBMISSION_UNAVAILABLE);
2447
- info("For an instant quote from the terminal: delegance quote start --coverage gl");
2832
+ info(`For an instant quote from the terminal: ${cliInvocation()} quote start --coverage gl`);
2448
2833
  info(`Or start a quote at ${PORTAL_URL}`);
2449
2834
  process.exit(1);
2450
2835
  }
@@ -2575,11 +2960,11 @@ function formatQuoteStatus(status) {
2575
2960
  }
2576
2961
 
2577
2962
  // src/commands/policy.ts
2578
- var import_commander7 = require("commander");
2579
- var import_inquirer7 = __toESM(require("inquirer"));
2963
+ var import_commander8 = require("commander");
2964
+ var import_inquirer8 = __toESM(require("inquirer"));
2580
2965
  var import_ora8 = __toESM(require("ora"));
2581
2966
  function createPolicyCommand() {
2582
- const policy = new import_commander7.Command("policy").alias("policies").description("Manage insurance policies");
2967
+ const policy = new import_commander8.Command("policy").alias("policies").description("Manage insurance policies");
2583
2968
  policy.command("list").alias("ls").description("List all policies").option("-s, --status <status>", "Filter by status (active, expired, all)", "active").option("-t, --type <type>", "Filter by policy type").option("-l, --limit <n>", "Maximum results", "50").option("--json", "Output as JSON").action(async (options) => {
2584
2969
  const client = getClient();
2585
2970
  const spinner = (0, import_ora8.default)("Fetching policies...").start();
@@ -2602,7 +2987,7 @@ function createPolicyCommand() {
2602
2987
  ["Carrier", "Type", "Policy #", "Expiry", "Status", "Premium"],
2603
2988
  policies.map((p) => [
2604
2989
  p.carrier || "Unknown",
2605
- p.policyType || p.name || "-",
2990
+ (p.policyType ? coverageName(p.policyType) : p.name) || "-",
2606
2991
  p.policyNumber || "-",
2607
2992
  p.expiryDate ? formatDate(p.expiryDate) : "-",
2608
2993
  formatPolicyStatus(p.isActive, p.daysUntilExpiry),
@@ -2636,21 +3021,21 @@ function createPolicyCommand() {
2636
3021
  if (urgent.length > 0) {
2637
3022
  warn(`\u26A0\uFE0F Expiring within 7 days (${urgent.length}):`);
2638
3023
  for (const p of urgent) {
2639
- console.log(` - ${p.carrier} ${p.policyType || p.name} - expires ${formatDate(p.expiryDate)}`);
3024
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - expires ${formatDate(p.expiryDate)}`);
2640
3025
  }
2641
3026
  console.log();
2642
3027
  }
2643
3028
  if (soon.length > 0) {
2644
3029
  info(`\u{1F4C5} Expiring within 30 days (${soon.length}):`);
2645
3030
  for (const p of soon) {
2646
- console.log(` - ${p.carrier} ${p.policyType || p.name} - expires ${formatDate(p.expiryDate)}`);
3031
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - expires ${formatDate(p.expiryDate)}`);
2647
3032
  }
2648
3033
  console.log();
2649
3034
  }
2650
3035
  if (later.length > 0) {
2651
3036
  console.log(`\u{1F4C6} Expiring later (${later.length}):`);
2652
3037
  for (const p of later) {
2653
- console.log(` - ${p.carrier} ${p.policyType || p.name} - ${p.daysUntilExpiry} days`);
3038
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - ${p.daysUntilExpiry} days`);
2654
3039
  }
2655
3040
  }
2656
3041
  }
@@ -2674,11 +3059,11 @@ function createPolicyCommand() {
2674
3059
  } else {
2675
3060
  const { policy: p, coverages } = found;
2676
3061
  console.log();
2677
- header(`${p.carrier} - ${p.policyType || p.name}`);
3062
+ header(`${p.carrier} - ${p.policyType ? coverageName(p.policyType) : p.name}`);
2678
3063
  console.log();
2679
3064
  console.log(` Policy #: ${p.policyNumber || "N/A"}`);
2680
3065
  console.log(` Carrier: ${p.carrier}`);
2681
- console.log(` Type: ${p.policyType || "N/A"}`);
3066
+ console.log(` Type: ${p.policyType ? coverageName(p.policyType) : "N/A"}`);
2682
3067
  console.log(` Effective: ${p.effectiveDate ? formatDate(p.effectiveDate) : "N/A"}`);
2683
3068
  console.log(` Expiry: ${p.expiryDate ? formatDate(p.expiryDate) : "N/A"}`);
2684
3069
  console.log(` Status: ${formatPolicyStatus(p.isActive, p.daysUntilExpiry)}`);
@@ -2729,14 +3114,14 @@ function createPolicyCommand() {
2729
3114
  return;
2730
3115
  }
2731
3116
  if (docs.length === 0) {
2732
- info("No source documents are linked to this policy yet. Upload one with: delegance document upload <file>");
3117
+ info(`No source documents are linked to this policy yet. Upload one with: ${cliInvocation()} document upload <file>`);
2733
3118
  return;
2734
3119
  }
2735
3120
  table(
2736
3121
  ["Document", "File", "Type", "Status", "Added"],
2737
3122
  docs.map((d) => [d.id, d.fileName ?? "-", d.documentType ?? "-", d.status, d.createdAt ? formatDate(d.createdAt) : "-"])
2738
3123
  );
2739
- info("Download one with: delegance document status <documentId>");
3124
+ info(`Download one with: ${cliInvocation()} document status <documentId>`);
2740
3125
  } catch (err) {
2741
3126
  failWith("API error", err);
2742
3127
  }
@@ -2769,9 +3154,9 @@ function createPolicyCommand() {
2769
3154
  await signWithStepUp(client, out.request.id, sig, void 0, void 0);
2770
3155
  } else {
2771
3156
  info(`Sign here: ${out.signatureUrl}`);
2772
- info(`Or sign from here: delegance policy sign ${out.request.id} --signer-name "..." --signer-title "..." --attest`);
3157
+ info(`Or sign from here: ${cliInvocation()} policy sign ${out.request.id} --signer-name "..." --signer-title "..." --attest`);
2773
3158
  }
2774
- info(`Check progress with "delegance policy cancellation ${out.request.id}"`);
3159
+ info(`Check progress with "${cliInvocation()} policy cancellation ${out.request.id}"`);
2775
3160
  } catch (err) {
2776
3161
  spinner.fail("Could not request the cancellation");
2777
3162
  failWith("API error", err);
@@ -2828,10 +3213,10 @@ async function signWithStepUp(client, requestId, sig, stepUpId, presetCode) {
2828
3213
  let code = presetCode;
2829
3214
  if (!code) {
2830
3215
  if (!process.stdin.isTTY) {
2831
- warn(`No terminal to type the code in. Finish with: delegance policy sign ${requestId} --signer-name "${sig.signerName}" --signer-title "${sig.signerTitle}" --attest --step-up ${id} --code <code>`);
3216
+ warn(`No terminal to type the code in. Finish with: ${cliInvocation()} policy sign ${requestId} --signer-name "${sig.signerName}" --signer-title "${sig.signerTitle}" --attest --step-up ${id} --code <code>`);
2832
3217
  return;
2833
3218
  }
2834
- const answer = await import_inquirer7.default.prompt([{
3219
+ const answer = await import_inquirer8.default.prompt([{
2835
3220
  type: "input",
2836
3221
  name: "code",
2837
3222
  message: "Code from your email:",
@@ -2858,11 +3243,11 @@ function formatPolicyStatus(isActive, daysUntilExpiry) {
2858
3243
  }
2859
3244
 
2860
3245
  // src/commands/coi.ts
2861
- var import_commander8 = require("commander");
3246
+ var import_commander9 = require("commander");
2862
3247
  var import_ora9 = __toESM(require("ora"));
2863
- var import_inquirer8 = __toESM(require("inquirer"));
3248
+ var import_inquirer9 = __toESM(require("inquirer"));
2864
3249
  function createCOICommand() {
2865
- const coi = new import_commander8.Command("coi").description("Generate and manage Certificates of Insurance");
3250
+ const coi = new import_commander9.Command("coi").description("Generate and manage Certificates of Insurance");
2866
3251
  coi.command("generate").alias("create").description("Generate a Certificate of Insurance").option("-p, --policies <ids...>", "Policy IDs to include").option("-n, --holder-name <name>", "Certificate holder name").option("-a, --holder-address <address>", "Certificate holder address").option("--city <city>", "Certificate holder city").option("--state <state>", "Certificate holder state (2-letter)").option("--zip <zip>", "Certificate holder ZIP").option("-t, --type <type>", "Certificate type (additional_insured, certificate_holder)", "certificate_holder").option("-i, --interactive", "Interactive mode").option("--json", "Output as JSON").action(async (options) => {
2867
3252
  const client = getClient();
2868
3253
  let policyIds = options.policies || [];
@@ -2878,16 +3263,16 @@ function createCOICommand() {
2878
3263
  policiesSpinner.stop();
2879
3264
  if (policies.length === 0) {
2880
3265
  error("No active policies found");
2881
- info('Upload policy documents first with "delegance doc upload"');
3266
+ info(`Upload policy documents first with "${cliInvocation()} doc upload"`);
2882
3267
  process.exit(1);
2883
3268
  }
2884
- const answers = await import_inquirer8.default.prompt([
3269
+ const answers = await import_inquirer9.default.prompt([
2885
3270
  {
2886
3271
  type: "checkbox",
2887
3272
  name: "selectedPolicies",
2888
3273
  message: "Select policies to include:",
2889
3274
  choices: policies.map((p) => ({
2890
- name: `${p.carrier} - ${p.policyType || p.name} (${p.policyNumber || "No #"})`,
3275
+ name: `${p.carrier} - ${p.policyType ? coverageName(p.policyType) : p.name} (${p.policyNumber || "No #"})`,
2891
3276
  value: p.id,
2892
3277
  checked: policyIds.includes(p.id)
2893
3278
  })),
@@ -2974,7 +3359,7 @@ function createCOICommand() {
2974
3359
  console.log();
2975
3360
  console.log("Policies included:");
2976
3361
  for (const p of result.policiesIncluded) {
2977
- console.log(` - ${p.carrier} (${p.policyType})`);
3362
+ console.log(` - ${p.carrier} (${coverageName(p.policyType)})`);
2978
3363
  }
2979
3364
  }
2980
3365
  } catch (err) {
@@ -2990,7 +3375,7 @@ function createCOICommand() {
2990
3375
  spinner.succeed(`Found ${count} COIs`);
2991
3376
  if (cois.length === 0) {
2992
3377
  info("No COIs generated yet");
2993
- info('Generate one with "delegance coi generate --interactive"');
3378
+ info(`Generate one with "${cliInvocation()} coi generate --interactive"`);
2994
3379
  return;
2995
3380
  }
2996
3381
  if (options.json) {
@@ -3017,12 +3402,12 @@ function createCOICommand() {
3017
3402
  }
3018
3403
 
3019
3404
  // src/commands/sov.ts
3020
- var import_commander9 = require("commander");
3405
+ var import_commander10 = require("commander");
3021
3406
  var import_ora10 = __toESM(require("ora"));
3022
3407
  var import_fs = __toESM(require("fs"));
3023
3408
  var import_path = __toESM(require("path"));
3024
3409
  function createSOVCommand() {
3025
- const sov = new import_commander9.Command("sov").description("Manage Schedules of Values (property schedules)");
3410
+ const sov = new import_commander10.Command("sov").description("Manage Schedules of Values (property schedules)");
3026
3411
  sov.command("upload <file>").description("Upload a Schedule of Values file").option("-l, --line <line>", "Line of business (property, inland_marine, etc)", "property").option("--effective <date>", "Effective date (YYYY-MM-DD)").option("--expiration <date>", "Expiration date (YYYY-MM-DD)").option("-w, --wait", "Wait for parsing to complete").option("--json", "Output as JSON").action(async (file, options) => {
3027
3412
  const client = getClient();
3028
3413
  const filePath = import_path.default.resolve(file);
@@ -3067,7 +3452,7 @@ function createSOVCommand() {
3067
3452
  info(`SOV ID: ${result.sovId}`);
3068
3453
  info(`Status: ${result.status}`);
3069
3454
  if (!options.wait) {
3070
- info('Use "delegance sov status <id>" to check parsing progress');
3455
+ info(`Use "${cliInvocation()} sov status <id>" to check parsing progress`);
3071
3456
  }
3072
3457
  }
3073
3458
  } catch (err) {
@@ -3086,7 +3471,7 @@ function createSOVCommand() {
3086
3471
  spinner.succeed(`Found ${count} SOVs`);
3087
3472
  if (sovs.length === 0) {
3088
3473
  info("No SOVs found");
3089
- info('Upload one with "delegance sov upload schedule.xlsx"');
3474
+ info(`Upload one with "${cliInvocation()} sov upload schedule.xlsx"`);
3090
3475
  return;
3091
3476
  }
3092
3477
  if (options.json) {
@@ -3180,7 +3565,7 @@ function showSOVDetails(s) {
3180
3565
  }
3181
3566
 
3182
3567
  // src/commands/appetite.ts
3183
- var import_commander10 = require("commander");
3568
+ var import_commander11 = require("commander");
3184
3569
  var import_ora11 = __toESM(require("ora"));
3185
3570
  function num(value) {
3186
3571
  if (value === void 0) return void 0;
@@ -3228,7 +3613,7 @@ function printResult(result) {
3228
3613
  for (const w of result.warnings) warn(w);
3229
3614
  }
3230
3615
  function createAppetiteCommand() {
3231
- const appetite = new import_commander10.Command("appetite").description("Check which carriers will write a risk");
3616
+ const appetite = new import_commander11.Command("appetite").description("Check which carriers will write a risk");
3232
3617
  appetite.command("match").description("Match a business to carrier appetite").requiredOption("-s, --state <state>", "Two-letter state code").option("-i, --industry <industry>", 'Industry, e.g. "bakery"').option("-d, --description <text>", "What the business does").option("--naics <code>", "NAICS code").option("--sic <code>", "SIC code").option("-c, --coverage <types>", "Comma-separated coverage types, e.g. general_liability,workers_comp").option("--carriers <names>", "Comma-separated carriers to limit the match to").option("--market-size <size>", '"Small Business" or "Middle Market"').option("--revenue <usd>", "Annual revenue").option("--payroll <usd>", "Annual payroll").option("--property-value <usd>", "Total property value").option("--min-fit <fit>", "Raise the quality floor: possible or strong").option("--top <n>", "Maximum matches (1-50)").option("--no-wait", "Return the job id instead of waiting for a cold match").option("--timeout <ms>", "How long to wait for a cold match", "120000").option("--json", "Output as JSON").action(async (options) => {
3233
3618
  const input = buildMatchInput(options);
3234
3619
  const timeoutMs = positiveInt(options.timeout, "--timeout");
@@ -3250,7 +3635,7 @@ function createAppetiteCommand() {
3250
3635
  if (!options.wait) {
3251
3636
  spinner.succeed(`Match queued: ${start.jobId}`);
3252
3637
  if (options.json) json(start);
3253
- else info(`Check it with "delegance appetite status ${start.jobId}"`);
3638
+ else info(`Check it with "${cliInvocation()} appetite status ${start.jobId}"`);
3254
3639
  return;
3255
3640
  }
3256
3641
  spinner.text = `Matching appetite (about ${start.estimatedSeconds}s)...`;
@@ -3289,7 +3674,7 @@ function createAppetiteCommand() {
3289
3674
  }
3290
3675
 
3291
3676
  // src/commands/lead.ts
3292
- var import_commander11 = require("commander");
3677
+ var import_commander12 = require("commander");
3293
3678
  var import_ora12 = __toESM(require("ora"));
3294
3679
  function buildLeadInput(options) {
3295
3680
  const input = {
@@ -3320,7 +3705,7 @@ function buildLeadInput(options) {
3320
3705
  return input;
3321
3706
  }
3322
3707
  function createLeadCommand() {
3323
- const lead = new import_commander11.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3708
+ const lead = new import_commander12.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3324
3709
  lead.command("create").description("Create a lead (idempotent on --external-id and contact email)").requiredOption("-n, --name <name>", "Business name").requiredOption("-e, --email <email>", "Contact email").option("--legal-name <name>", "Legal name, if different").option("-i, --industry <industry>", "Industry").option("-p, --phone <phone>", "Contact phone").option("-w, --website <url>", "Website (full URL)").option("--size <size>", "Company size").option("-d, --description <text>", "What the business does").option("--naics <code>", "NAICS code").option("--sic <code>", "SIC code").option("-s, --state <state>", "Two-letter state code").option("--street <street>", "Street address").option("--suite <suite>", "Suite").option("--city <city>", "City").option("--address-state <state>", "Address state (defaults to --state)").option("--zip <zip>", "ZIP code").option("--external-id <id>", "Your id for this lead").option("--source <source>", "Lead source label").option("--notes <notes>", "Notes for the broker").option("--json", "Output as JSON").action(async (options) => {
3325
3710
  const input = buildLeadInput(options);
3326
3711
  if (input.address && (!input.address.street || !input.address.city || !input.address.state || !input.address.zip)) {
@@ -3343,11 +3728,11 @@ function createLeadCommand() {
3343
3728
  }
3344
3729
 
3345
3730
  // src/commands/knowledge.ts
3346
- var import_commander12 = require("commander");
3731
+ var import_commander13 = require("commander");
3347
3732
  var import_ora13 = __toESM(require("ora"));
3348
3733
  var SEARCH_TYPES = ["notecard", "document_chunk"];
3349
3734
  function createKnowledgeCommand() {
3350
- const knowledge = new import_commander12.Command("knowledge").alias("kb").description("Search notecards and document facts");
3735
+ const knowledge = new import_commander13.Command("knowledge").alias("kb").description("Search notecards and document facts");
3351
3736
  knowledge.command("search <query...>").description("Search notecards and document text").option("-t, --type <type>", `Limit to one result type (${SEARCH_TYPES.join(", ")})`).option("-l, --limit <n>", "Maximum results", "10").option("--json", "Output as JSON").action(async (queryParts, options) => {
3352
3737
  const client = getClient();
3353
3738
  const query = queryParts.join(" ");
@@ -3396,7 +3781,7 @@ function createKnowledgeCommand() {
3396
3781
  );
3397
3782
  }
3398
3783
  if (pagination.hasMore && pagination.nextCursor) {
3399
- info(`More: delegance knowledge notecards --cursor ${pagination.nextCursor}`);
3784
+ info(`More: ${cliInvocation()} knowledge notecards --cursor ${pagination.nextCursor}`);
3400
3785
  }
3401
3786
  } catch (err) {
3402
3787
  spinner.fail("Failed to list notecards");
@@ -3449,7 +3834,7 @@ function createKnowledgeCommand() {
3449
3834
  }
3450
3835
 
3451
3836
  // src/commands/onboarding.ts
3452
- var import_commander13 = require("commander");
3837
+ var import_commander14 = require("commander");
3453
3838
  var import_ora14 = __toESM(require("ora"));
3454
3839
  var ONBOARDING_STATES = [
3455
3840
  "created",
@@ -3459,7 +3844,7 @@ var ONBOARDING_STATES = [
3459
3844
  "ready"
3460
3845
  ];
3461
3846
  function createOnboardingCommand() {
3462
- const onboarding = new import_commander13.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3847
+ const onboarding = new import_commander14.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3463
3848
  onboarding.command("status").description("Show the setup checklist and the next step").option("--json", "Output as JSON").action(async (options) => {
3464
3849
  const client = getClient();
3465
3850
  const spinner = (0, import_ora14.default)("Fetching onboarding status...").start();
@@ -3520,7 +3905,7 @@ function createOnboardingCommand() {
3520
3905
  const result = await client.onboarding.requestVerification();
3521
3906
  spinner.succeed(`Verification sent to ${result.sentTo}`);
3522
3907
  if (options.json) json(result);
3523
- else info('Open the link in that email, then check progress with "delegance onboarding state"');
3908
+ else info(`Open the link in that email, then check progress with "${cliInvocation()} onboarding state"`);
3524
3909
  } catch (err) {
3525
3910
  spinner.fail("Failed to request verification");
3526
3911
  failWith("API error", err);
@@ -3550,7 +3935,7 @@ function createOnboardingCommand() {
3550
3935
  }
3551
3936
 
3552
3937
  // src/commands/usage.ts
3553
- var import_commander14 = require("commander");
3938
+ var import_commander15 = require("commander");
3554
3939
  var import_ora15 = __toESM(require("ora"));
3555
3940
  function isoDay(daysAgo, now = /* @__PURE__ */ new Date()) {
3556
3941
  const d = new Date(now.getTime() - daysAgo * 24 * 60 * 60 * 1e3);
@@ -3560,7 +3945,7 @@ function cents(n) {
3560
3945
  return `$${(n / 100).toFixed(2)}`;
3561
3946
  }
3562
3947
  function createUsageCommand() {
3563
- const usage = new import_commander14.Command("usage").description("Show API usage, billing, and rate limits");
3948
+ const usage = new import_commander15.Command("usage").description("Show API usage, billing, and rate limits");
3564
3949
  usage.command("summary").description("Usage for the current billing period").option("--json", "Output as JSON").action(async (options) => {
3565
3950
  const client = getClient();
3566
3951
  const spinner = (0, import_ora15.default)("Fetching usage summary...").start();
@@ -3640,21 +4025,30 @@ function createUsageCommand() {
3640
4025
  }
3641
4026
 
3642
4027
  // src/commands/keys.ts
3643
- var import_commander15 = require("commander");
4028
+ var import_commander16 = require("commander");
3644
4029
  var import_ora16 = __toESM(require("ora"));
3645
4030
  var import_crypto3 = require("crypto");
3646
- var import_sdk6 = require("@delegance/sdk");
4031
+ var import_sdk7 = require("@delegance/sdk");
3647
4032
  var KEYS_PORTAL_URL = `${PORTAL_URL}/portal/settings/api-keys`;
4033
+ function parseExpiresInDays(raw) {
4034
+ if (raw === void 0 || raw === "") return void 0;
4035
+ if (raw.trim().toLowerCase() === "never") return "never";
4036
+ return parseInt(raw, 10);
4037
+ }
3648
4038
  function parseScopes(raw) {
3649
4039
  const parts = (Array.isArray(raw) ? raw : [raw ?? "read,write"]).flatMap((p) => p.split(/[\s,]+/)).map((p) => p.trim()).filter(Boolean);
3650
- const unknown = parts.filter((p) => !import_sdk6.API_KEY_SCOPES.includes(p));
4040
+ const unknown = parts.filter((p) => !import_sdk7.API_KEY_SCOPES.includes(p));
3651
4041
  if (unknown.length > 0) {
3652
- throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk6.API_KEY_SCOPES.join(", ")}`);
4042
+ throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk7.API_KEY_SCOPES.join(", ")}`);
3653
4043
  }
3654
4044
  return Array.from(new Set(parts));
3655
4045
  }
3656
- function replacementExpiryDays(expiresAt, now = /* @__PURE__ */ new Date()) {
3657
- if (!expiresAt) return void 0;
4046
+ var EXPIRING_SCOPES = /* @__PURE__ */ new Set(["write", "admin", "claims:write"]);
4047
+ function isReadOnlyScopeSet(scopes) {
4048
+ return !scopes.some((s) => EXPIRING_SCOPES.has(s));
4049
+ }
4050
+ function replacementExpiryDays(expiresAt, now = /* @__PURE__ */ new Date(), scopes = []) {
4051
+ if (!expiresAt) return isReadOnlyScopeSet(scopes) ? "never" : void 0;
3658
4052
  const ms = new Date(expiresAt).getTime() - now.getTime();
3659
4053
  if (!Number.isFinite(ms)) throw new Error(`Cannot read the old key's expiry "${expiresAt}"; not rotating`);
3660
4054
  const days = Math.ceil(ms / (24 * 60 * 60 * 1e3));
@@ -3674,7 +4068,7 @@ function printCreatedKey(created) {
3674
4068
  console.log(` ${created.key}`);
3675
4069
  }
3676
4070
  function createKeysCommand() {
3677
- const keys = new import_commander15.Command("keys").alias("api-keys").description("Manage API keys");
4071
+ const keys = new import_commander16.Command("keys").alias("api-keys").description("Manage API keys");
3678
4072
  keys.command("list").alias("ls").description("List API keys for your company").option("-l, --limit <n>", "Maximum results", "50").option("--cursor <cursor>", "Page cursor from a previous list").option("--json", "Output as JSON").action(async (options) => {
3679
4073
  const client = getClient();
3680
4074
  const spinner = (0, import_ora16.default)("Fetching API keys...").start();
@@ -3703,14 +4097,14 @@ function createKeysCommand() {
3703
4097
  ])
3704
4098
  );
3705
4099
  if (pagination?.hasMore && pagination.nextCursor) {
3706
- info(`More keys: delegance keys list --cursor ${pagination.nextCursor}`);
4100
+ info(`More keys: ${cliInvocation()} keys list --cursor ${pagination.nextCursor}`);
3707
4101
  }
3708
4102
  } catch (err) {
3709
4103
  spinner.fail("Failed to list API keys");
3710
4104
  failWith("API error", err);
3711
4105
  }
3712
4106
  });
3713
- keys.command("create <name>").description("Create an API key (needs a key with the admin scope)").option("-s, --scopes <scopes>", `Comma-separated scopes (${import_sdk6.API_KEY_SCOPES.join(", ")})`, "read,write").option("-e, --expires-in-days <days>", "Expire the key after N days (1-365)").option("--json", "Output as JSON").action(async (name, options) => {
4107
+ keys.command("create <name>").description("Create an API key (needs a key with the admin scope)").option("-s, --scopes <scopes>", `Comma-separated scopes (${import_sdk7.API_KEY_SCOPES.join(", ")})`, "read,write").option("-e, --expires-in-days <days>", 'Expire the key after N days (1-365; default 90), or "never" for a read-only key').option("--json", "Output as JSON").action(async (name, options) => {
3714
4108
  let scopes;
3715
4109
  try {
3716
4110
  scopes = parseScopes(options.scopes);
@@ -3725,7 +4119,7 @@ function createKeysCommand() {
3725
4119
  {
3726
4120
  name,
3727
4121
  scopes,
3728
- expiresInDays: options.expiresInDays ? parseInt(options.expiresInDays) : void 0
4122
+ expiresInDays: parseExpiresInDays(options.expiresInDays)
3729
4123
  },
3730
4124
  { idempotencyKey: (0, import_crypto3.randomUUID)() }
3731
4125
  );
@@ -3760,7 +4154,7 @@ function createKeysCommand() {
3760
4154
  {
3761
4155
  name: `${current2.name} (rotated)`,
3762
4156
  scopes: current2.scopes,
3763
- expiresInDays: replacementExpiryDays(current2.expiresAt)
4157
+ expiresInDays: replacementExpiryDays(current2.expiresAt, /* @__PURE__ */ new Date(), current2.scopes)
3764
4158
  },
3765
4159
  { idempotencyKey: (0, import_crypto3.randomUUID)() }
3766
4160
  );
@@ -3771,6 +4165,9 @@ function createKeysCommand() {
3771
4165
  }
3772
4166
  printCreatedKey(created);
3773
4167
  console.log();
4168
+ if (!current2.expiresAt && !isReadOnlyScopeSet(current2.scopes)) {
4169
+ warn("The old key never expired. Keys that can write must expire now, so the new key lasts 90 days.");
4170
+ }
3774
4171
  warn(`The old key ${current2.prefix} is still active.`);
3775
4172
  info(`Switch your integrations to the new key, then revoke the old one at ${KEYS_PORTAL_URL}`);
3776
4173
  } catch (err) {
@@ -3786,7 +4183,7 @@ function createKeysCommand() {
3786
4183
  spinner.succeed("API key revoked");
3787
4184
  } catch (err) {
3788
4185
  spinner.fail("Failed to revoke API key");
3789
- if (err instanceof import_sdk6.AuthenticationError) {
4186
+ if (err instanceof import_sdk7.AuthenticationError) {
3790
4187
  error("Revoking a key needs a signed-in portal session today");
3791
4188
  info(`Revoke it at ${KEYS_PORTAL_URL}`);
3792
4189
  process.exit(1);
@@ -3798,10 +4195,10 @@ function createKeysCommand() {
3798
4195
  }
3799
4196
 
3800
4197
  // src/commands/config.ts
3801
- var import_commander16 = require("commander");
3802
- var import_inquirer9 = __toESM(require("inquirer"));
4198
+ var import_commander17 = require("commander");
4199
+ var import_inquirer10 = __toESM(require("inquirer"));
3803
4200
  function createConfigCommand() {
3804
- const config2 = new import_commander16.Command("config").description("Manage CLI configuration");
4201
+ const config2 = new import_commander17.Command("config").description("Manage CLI configuration");
3805
4202
  config2.command("show").alias("list").description("Show current configuration").option("--json", "Output as JSON").action((options) => {
3806
4203
  const currentConfig = getConfig();
3807
4204
  const apiKey = getApiKey();
@@ -3845,7 +4242,7 @@ function createConfigCommand() {
3845
4242
  });
3846
4243
  config2.command("reset").description("Reset all configuration to defaults").option("-f, --force", "Skip confirmation").action(async (options) => {
3847
4244
  if (!options.force) {
3848
- const { confirm } = await import_inquirer9.default.prompt([
4245
+ const { confirm } = await import_inquirer10.default.prompt([
3849
4246
  {
3850
4247
  type: "confirm",
3851
4248
  name: "confirm",
@@ -3862,7 +4259,7 @@ function createConfigCommand() {
3862
4259
  currentConfig.clear();
3863
4260
  clearCredentials();
3864
4261
  success("Configuration reset to defaults");
3865
- info('You will need to run "delegance auth login" again');
4262
+ info(`You will need to run "${cliInvocation()} auth login" again`);
3866
4263
  });
3867
4264
  config2.command("env").description("Show environment information").action(() => {
3868
4265
  header("Environment");
@@ -3888,7 +4285,7 @@ function createConfigCommand() {
3888
4285
  info("No profiles configured");
3889
4286
  info("Profiles allow you to switch between different accounts/environments");
3890
4287
  console.log();
3891
- info("Example: delegance config set-profile production --url https://portal.delegancebrokerage.com");
4288
+ info(`Example: ${cliInvocation()} config set-profile production --url https://portal.delegancebrokerage.com`);
3892
4289
  } else {
3893
4290
  for (const [name, profile] of Object.entries(profiles)) {
3894
4291
  const isActive = name === activeProfile;
@@ -3904,7 +4301,7 @@ function createConfigCommand() {
3904
4301
  const profiles = currentConfig.get("profiles") || {};
3905
4302
  if (!profiles[name] && name !== "default") {
3906
4303
  error(`Profile "${name}" not found`);
3907
- info("Create it with: delegance config set-profile <name> --url <base-url>");
4304
+ info(`Create it with: ${cliInvocation()} config set-profile <name> --url <base-url>`);
3908
4305
  process.exit(1);
3909
4306
  }
3910
4307
  currentConfig.set("activeProfile", name);
@@ -3930,15 +4327,15 @@ function createConfigCommand() {
3930
4327
  }
3931
4328
 
3932
4329
  // src/program.ts
3933
- var import_commander19 = require("commander");
4330
+ var import_commander20 = require("commander");
3934
4331
 
3935
4332
  // src/commands/feedback.ts
3936
- var import_commander17 = require("commander");
3937
- var import_inquirer10 = __toESM(require("inquirer"));
3938
- var import_sdk7 = require("@delegance/sdk");
4333
+ var import_commander18 = require("commander");
4334
+ var import_inquirer11 = __toESM(require("inquirer"));
4335
+ var import_sdk8 = require("@delegance/sdk");
3939
4336
  var TYPES = ["bug", "idea", "question"];
3940
4337
  var MESSAGE_MAX = 500;
3941
- var USAGE = 'delegance feedback "what happened" [--type bug|idea|question] [--include-last]';
4338
+ var USAGE = `${cliInvocation()} feedback "what happened" [--type bug|idea|question] [--include-last]`;
3942
4339
  function feedbackInputMode(o) {
3943
4340
  if (o.message && o.message.trim()) return "given";
3944
4341
  return o.isTTY ? "prompt" : "usage_error";
@@ -3952,7 +4349,7 @@ function buildFeedbackContext(last) {
3952
4349
  ctx.at = last.at;
3953
4350
  }
3954
4351
  ctx.cliVersion = CLI_VERSION;
3955
- ctx.sdkVersion = import_sdk7.SDK_VERSION;
4352
+ ctx.sdkVersion = import_sdk8.SDK_VERSION;
3956
4353
  return ctx;
3957
4354
  }
3958
4355
  function usageError(message) {
@@ -3961,14 +4358,14 @@ function usageError(message) {
3961
4358
  process.exit(2);
3962
4359
  }
3963
4360
  function createFeedbackCommand() {
3964
- return new import_commander17.Command("feedback").alias("bug").description("Report a bug, an idea, or a question to Delegance").argument("[message...]", "What happened (asked for when left out on a terminal)").option("-t, --type <type>", "bug, idea, or question", "bug").option("--include-last", "Attach the last command name, exit code, trace id, and CLI/SDK versions (never its arguments)").option("--json", "Output as JSON").action(async (words, options) => {
4361
+ return new import_commander18.Command("feedback").alias("bug").description("Report a bug, an idea, or a question to Delegance").argument("[message...]", "What happened (asked for when left out on a terminal)").option("-t, --type <type>", "bug, idea, or question", "bug").option("--include-last", "Attach the last command name, exit code, trace id, and CLI/SDK versions (never its arguments)").option("--json", "Output as JSON").action(async (words, options) => {
3965
4362
  const type = String(options.type ?? "bug").toLowerCase();
3966
4363
  if (!TYPES.includes(type)) usageError(`--type must be bug, idea, or question, got "${options.type}"`);
3967
4364
  let message = (words ?? []).join(" ").trim();
3968
4365
  const mode = feedbackInputMode({ message, isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY) });
3969
4366
  if (mode === "usage_error") usageError(`Say what happened: ${USAGE}`);
3970
4367
  if (mode === "prompt") {
3971
- const answer = await import_inquirer10.default.prompt([
4368
+ const answer = await import_inquirer11.default.prompt([
3972
4369
  { type: "input", name: "message", message: type === "bug" ? "What went wrong?" : "What would you like to tell us?" }
3973
4370
  ]);
3974
4371
  message = String(answer.message ?? "").trim();
@@ -3989,12 +4386,42 @@ function createFeedbackCommand() {
3989
4386
  });
3990
4387
  }
3991
4388
 
4389
+ // src/utils/checkbox-prompt.ts
4390
+ var import_inquirer12 = __toESM(require("inquirer"));
4391
+ var import_chalk3 = __toESM(require("chalk"));
4392
+ var CHECKBOX_HINT = "(space to select, Enter to continue)";
4393
+ var registered = false;
4394
+ function minimalCheckboxPrompt(Base) {
4395
+ return class MinimalCheckboxPrompt extends Base {
4396
+ constructor(...args) {
4397
+ super(...args);
4398
+ this.dontShowHints = true;
4399
+ }
4400
+ getQuestion() {
4401
+ const question = super.getQuestion();
4402
+ return this.status === "answered" ? question : `${question}${import_chalk3.default.dim(CHECKBOX_HINT)} `;
4403
+ }
4404
+ onAllKey() {
4405
+ }
4406
+ onInverseKey() {
4407
+ }
4408
+ };
4409
+ }
4410
+ function registerMinimalCheckbox() {
4411
+ if (registered) return;
4412
+ const prompts = import_inquirer12.default.prompt.prompts;
4413
+ const Base = prompts?.checkbox;
4414
+ if (!Base) return;
4415
+ import_inquirer12.default.registerPrompt("checkbox", minimalCheckboxPrompt(Base));
4416
+ registered = true;
4417
+ }
4418
+
3992
4419
  // src/commands/commerce.ts
3993
- var import_commander18 = require("commander");
4420
+ var import_commander19 = require("commander");
3994
4421
  var fs7 = __toESM(require("fs"));
3995
- var import_inquirer11 = __toESM(require("inquirer"));
4422
+ var import_inquirer13 = __toESM(require("inquirer"));
3996
4423
  var import_ora17 = __toESM(require("ora"));
3997
- var import_sdk8 = require("@delegance/sdk");
4424
+ var import_sdk9 = require("@delegance/sdk");
3998
4425
  function formatCents(cents2, currency = "usd") {
3999
4426
  return currency.toLowerCase() === "usd" ? formatCurrency(cents2 / 100) : `${(cents2 / 100).toFixed(2)} ${currency.toUpperCase()}`;
4000
4427
  }
@@ -4020,9 +4447,58 @@ function describeBindResult(r) {
4020
4447
  lines.push(r.next);
4021
4448
  return lines;
4022
4449
  }
4450
+ var BROKER_REVIEW_EMAIL = "support@delegancebrokerage.com";
4451
+ function selfDirectedAckLines(submissionId, offerId) {
4452
+ return [
4453
+ "This is a self-directed placement: Delegance binds the coverage you chose and does not advise on whether it fits your needs (Terms Section 9A).",
4454
+ `Want a licensed broker to review it first? Run: ${cliInvocation()} bind ${submissionId} ${offerId} --broker-review`
4455
+ ];
4456
+ }
4457
+ function brokerReviewMailto(submissionId, offerId) {
4458
+ const subject = encodeURIComponent(`Broker review before bind: submission ${submissionId}, offer ${offerId}`);
4459
+ return `mailto:${BROKER_REVIEW_EMAIL}?subject=${subject}`;
4460
+ }
4461
+ function brokerReviewLines(submissionId, offerId) {
4462
+ return [
4463
+ "Nothing was bound, and no review has been requested yet.",
4464
+ `To request a review by a licensed Delegance broker, send an email to ${BROKER_REVIEW_EMAIL}`,
4465
+ `naming submission ${submissionId} and offer ${offerId}: ${brokerReviewMailto(submissionId, offerId)}`,
4466
+ "Wait for the broker to reply before you bind. A reviewed placement is not self-directed."
4467
+ ];
4468
+ }
4469
+ function brokerReviewResult(submissionId, offerId) {
4470
+ return {
4471
+ bound: false,
4472
+ reviewRequested: false,
4473
+ submissionId,
4474
+ offerId,
4475
+ brokerReview: { email: BROKER_REVIEW_EMAIL, mailto: brokerReviewMailto(submissionId, offerId) },
4476
+ message: brokerReviewLines(submissionId, offerId)
4477
+ };
4478
+ }
4479
+ function exactDollars(cents2) {
4480
+ return `$${(cents2 / 100).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
4481
+ }
4482
+ function describeFinancing(f) {
4483
+ if (!f || !f.available) return [];
4484
+ const lines = [];
4485
+ if (f.checkoutUrl) {
4486
+ lines.push(`Pay over time with ${f.lender}: ${f.checkoutUrl}`);
4487
+ } else {
4488
+ lines.push(`Financing with ${f.lender} opens once your broker confirms the final premium.`);
4489
+ }
4490
+ const t = f.terms;
4491
+ if (t && t.aprBps !== null && t.downPaymentCents !== null && t.installmentCents !== null && t.numberOfInstallments !== null) {
4492
+ lines.push(
4493
+ `Lender terms: ${(t.aprBps / 100).toFixed(2)}% APR, ${exactDollars(t.downPaymentCents)} down, ${t.numberOfInstallments} payments of ${exactDollars(t.installmentCents)}.`
4494
+ );
4495
+ }
4496
+ lines.push(f.disclosure);
4497
+ return lines;
4498
+ }
4023
4499
  async function askCode() {
4024
4500
  if (!process.stdin.isTTY) return null;
4025
- const answer = await import_inquirer11.default.prompt([{
4501
+ const answer = await import_inquirer13.default.prompt([{
4026
4502
  type: "input",
4027
4503
  name: "code",
4028
4504
  message: "Code from your email:",
@@ -4031,11 +4507,19 @@ async function askCode() {
4031
4507
  return String(answer.code).trim();
4032
4508
  }
4033
4509
  function createBindCommand() {
4034
- return new import_commander18.Command("bind").description('Bind one offer from "quote status": the carrier checkout when the carrier offers it, otherwise a broker review').argument("<submissionId>", "The quote submission id").argument("<offerId>", "The offer id from the quote table").option("--attest", "Confirm the application answers are accurate (asked interactively when omitted)").option("--step-up <id>", "Finish an earlier attempt: the stepUpId the code email belongs to").option("--code <code>", "The 6-digit code from the email").option("--json", "Output as JSON").action(async (submissionId, offerId, options) => {
4510
+ return new import_commander19.Command("bind").description('Bind one offer from "quote status": the carrier checkout when the carrier offers it, otherwise a broker review').argument("<submissionId>", "The quote submission id").argument("<offerId>", "The offer id from the quote table").option("--attest", "Confirm the application answers are accurate (asked interactively when omitted)").option("--broker-review", "Do not bind; ask a licensed broker to review this coverage first").option("--step-up <id>", "Finish an earlier attempt: the stepUpId the code email belongs to").option("--code <code>", "The 6-digit code from the email").option("--json", "Output as JSON").action(async (submissionId, offerId, options) => {
4511
+ if (options.brokerReview) {
4512
+ if (options.json) json(brokerReviewResult(submissionId, offerId));
4513
+ else brokerReviewLines(submissionId, offerId).forEach((l) => info(l));
4514
+ return;
4515
+ }
4035
4516
  const client = getClient();
4517
+ const ack = selfDirectedAckLines(submissionId, offerId);
4518
+ if (options.json) ack.forEach((l) => console.error(l));
4519
+ else ack.forEach((l) => info(l));
4036
4520
  let attest = options.attest === true;
4037
4521
  if (!attest && process.stdin.isTTY && !options.json) {
4038
- const a = await import_inquirer11.default.prompt([{
4522
+ const a = await import_inquirer13.default.prompt([{
4039
4523
  type: "confirm",
4040
4524
  name: "ok",
4041
4525
  message: "Are the answers on this application accurate? Binding relies on them.",
@@ -4043,7 +4527,7 @@ function createBindCommand() {
4043
4527
  }]);
4044
4528
  attest = a.ok === true;
4045
4529
  if (!attest) {
4046
- warn('Not bound. Fix the answers with "delegance quote start", then bind again.');
4530
+ warn(`Not bound. Fix the answers with "${cliInvocation()} quote start", then bind again.`);
4047
4531
  return;
4048
4532
  }
4049
4533
  }
@@ -4059,7 +4543,7 @@ function createBindCommand() {
4059
4543
  info(`We emailed a 6-digit code to ${r.sentTo}. It expires in 10 minutes.`);
4060
4544
  const code = options.code ? String(options.code) : await askCode();
4061
4545
  if (!code) {
4062
- warn(`Finish with: delegance bind ${submissionId} ${offerId} --attest --step-up ${stepUpId} --code <code>`);
4546
+ warn(`Finish with: ${cliInvocation()} bind ${submissionId} ${offerId} --attest --step-up ${stepUpId} --code <code>`);
4063
4547
  return;
4064
4548
  }
4065
4549
  r = await client.instantQuotes.bindWithStepUp(submissionId, offerId, { ...attest ? { attest: true } : {}, stepUpId, code });
@@ -4069,16 +4553,17 @@ function createBindCommand() {
4069
4553
  }
4070
4554
  }
4071
4555
  if (options.json) {
4072
- json(r);
4556
+ json({ ...r, selfDirected: true, disclosure: ack[0] });
4073
4557
  return;
4074
4558
  }
4075
4559
  if (r.existing) warn(`A bind for this coverage is already open (${r.carrierName}). Showing it.`);
4076
- else if (r.tier !== "A") success(`Bind requested: ${r.carrierName} ${r.coverage}${r.premium === null ? "" : ` at ${formatCurrency(r.premium)}/yr`}`);
4560
+ else if (r.tier !== "A") success(`Bind requested: ${r.carrierName} ${coverageName(r.coverage)}${r.premium === null ? "" : ` at ${formatCurrency(r.premium)}/yr`}`);
4077
4561
  keyValue({ "Bind request": r.bindRequestId, Status: r.status });
4078
4562
  describeBindResult(r).forEach((l) => info(l));
4563
+ describeFinancing(r.financing).forEach((l) => info(l));
4079
4564
  } catch (err) {
4080
4565
  spinner?.stop();
4081
- if (err instanceof import_sdk8.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4566
+ if (err instanceof import_sdk9.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4082
4567
  error(err.message);
4083
4568
  process.exit(1);
4084
4569
  }
@@ -4099,7 +4584,7 @@ function summarizeBilling(payments) {
4099
4584
  return { openCents, paidCents, openCount };
4100
4585
  }
4101
4586
  function createBillingCommand() {
4102
- return new import_commander18.Command("billing").description("What you owe and what you paid: every premium payment request on the account").option("--json", "Output as JSON").action(async (options) => {
4587
+ return new import_commander19.Command("billing").description("What you owe and what you paid: every premium payment request on the account").option("--json", "Output as JSON").action(async (options) => {
4103
4588
  try {
4104
4589
  const payments = await getClient().payments.list();
4105
4590
  const sum = summarizeBilling(payments);
@@ -4116,14 +4601,14 @@ function createBillingCommand() {
4116
4601
  payments.map((p) => [p.id, formatCents(p.amount, p.currency), p.status, p.dueDate ? formatDate(p.dueDate) : "-", p.description ?? "-"])
4117
4602
  );
4118
4603
  keyValue({ "Open": `${formatCents(sum.openCents)} (${sum.openCount})`, "Paid": formatCents(sum.paidCents) });
4119
- if (sum.openCount > 0) info("Pay one with: delegance pay <paymentId>");
4604
+ if (sum.openCount > 0) info(`Pay one with: ${cliInvocation()} pay <paymentId>`);
4120
4605
  } catch (err) {
4121
4606
  failWith("API error", err);
4122
4607
  }
4123
4608
  });
4124
4609
  }
4125
4610
  function createPayCommand() {
4126
- return new import_commander18.Command("pay").description("Pay a premium: list payment requests, or get a checkout link for one").argument("[paymentId]", "Payment request to pay (omit to list them)").option("--json", "Output as JSON").action(async (paymentId, options) => {
4611
+ return new import_commander19.Command("pay").description("Pay a premium: list payment requests, or get a checkout link for one").argument("[paymentId]", "Payment request to pay (omit to list them)").option("--json", "Output as JSON").action(async (paymentId, options) => {
4127
4612
  const client = getClient();
4128
4613
  try {
4129
4614
  if (!paymentId) {
@@ -4141,7 +4626,7 @@ function createPayCommand() {
4141
4626
  payments.map((p) => [p.id, formatCents(p.amount, p.currency), p.description ?? "", p.payable ? `${p.status} (payable)` : p.status, p.dueDate ? formatDate(p.dueDate) : "-"])
4142
4627
  );
4143
4628
  const next = payments.find((p) => p.payable);
4144
- if (next) info(`Pay it: delegance pay ${next.id}`);
4629
+ if (next) info(`Pay it: ${cliInvocation()} pay ${next.id}`);
4145
4630
  return;
4146
4631
  }
4147
4632
  const { checkoutUrl } = await client.payments.checkout(paymentId);
@@ -4171,14 +4656,14 @@ function bondStartLines(r, ctx = {}) {
4171
4656
  out.push(` ${str(q.key)}: ${str(q.label)}${q.required ? " (required)" : ""}${opts}`);
4172
4657
  });
4173
4658
  }
4174
- out.push(`Answer with: delegance bond answer ${str(r.session_id)} --answers answers.json`);
4659
+ out.push(`Answer with: ${cliInvocation()} bond answer ${str(r.session_id)} --answers answers.json`);
4175
4660
  return out;
4176
4661
  }
4177
4662
  if (Array.isArray(r.candidates) && r.candidates.length) {
4178
4663
  out.push("That name fits more than one bond. Rerun with the exact name:");
4179
4664
  const rawState = (ctx.state ?? "").trim();
4180
4665
  const state = !rawState ? null : /^[A-Za-z]{2}$/.test(rawState) ? rawState.toUpperCase() : shellQuote(rawState);
4181
- r.candidates.forEach((name) => out.push(state ? ` delegance bond quote --state ${state} --bond ${shellQuote(str(name))}` : ` --bond ${shellQuote(str(name))}`));
4666
+ r.candidates.forEach((name) => out.push(state ? ` ${cliInvocation()} bond quote --state ${state} --bond ${shellQuote(str(name))}` : ` --bond ${shellQuote(str(name))}`));
4182
4667
  return out;
4183
4668
  }
4184
4669
  if (r.needsAmount) {
@@ -4208,7 +4693,7 @@ function bondStartLines(r, ctx = {}) {
4208
4693
  return out;
4209
4694
  }
4210
4695
  function createBondCommand() {
4211
- const bond = new import_commander18.Command("bond").alias("bonds").description("Surety bond quotes");
4696
+ const bond = new import_commander19.Command("bond").alias("bonds").description("Surety bond quotes");
4212
4697
  bond.command("quote").description("Start a bond quote and list its questions").requiredOption("-s, --state <state>", "Two-letter state, e.g. TX").option("-b, --bond <name>", 'Bond name or keyword, e.g. "notary", "contractor license"').option("--entity-id <id>", "Exact bond id, when you have it").option("--contract-amount <amount>", "Contract value, for contract bonds").option("--bond-amount <amount>", "Bond penal sum").option("--json", "Output as JSON").action(async (options) => {
4213
4698
  try {
4214
4699
  const r = await getClient().bonds.start({
@@ -4233,7 +4718,7 @@ function createBondCommand() {
4233
4718
  if (options.json) json(r);
4234
4719
  else {
4235
4720
  console.log(JSON.stringify(r, null, 2));
4236
- info(`Check it: delegance bond status ${sessionId}`);
4721
+ info(`Check it: ${cliInvocation()} bond status ${sessionId}`);
4237
4722
  }
4238
4723
  } catch (err) {
4239
4724
  failWith("Could not submit the answers", err);
@@ -4254,7 +4739,7 @@ function createBondCommand() {
4254
4739
  return bond;
4255
4740
  }
4256
4741
  function createClaimCommand() {
4257
- const claim = new import_commander18.Command("claim").alias("claims").description("File and track claims");
4742
+ const claim = new import_commander19.Command("claim").alias("claims").description("File and track claims");
4258
4743
  claim.command("file").description("File a claim. The first time, accept the claims disclaimer in the portal").option("-d, --description <text>", "What happened (visible in shell history; prefer --description-file)").option("--description-file <file>", "Read what happened from a file, or - for stdin").option("--date <yyyy-mm-dd>", "When it happened").option("--policy <id>", "Policy id, if you know it").option("--json", "Output as JSON").action(async (options) => {
4259
4744
  let description = options.description;
4260
4745
  if (options.descriptionFile) {
@@ -4278,7 +4763,7 @@ function createClaimCommand() {
4278
4763
  success(r.message);
4279
4764
  keyValue({ Claim: r.claimId, Status: r.status, Portal: r.portalUrl });
4280
4765
  } catch (err) {
4281
- if (err instanceof import_sdk8.DeleganceError && err.reason === "gate_not_acknowledged") {
4766
+ if (err instanceof import_sdk9.DeleganceError && err.reason === "gate_not_acknowledged") {
4282
4767
  error("Accept the claims disclaimer once in the portal, then file again. It cannot be accepted for you.");
4283
4768
  info(String(err.body?.portalUrl ?? ""));
4284
4769
  process.exit(1);
@@ -4310,7 +4795,8 @@ function createClaimCommand() {
4310
4795
 
4311
4796
  // src/program.ts
4312
4797
  function createProgram() {
4313
- const program = new import_commander19.Command();
4798
+ registerMinimalCheckbox();
4799
+ const program = new import_commander20.Command();
4314
4800
  program.name("delegance").description("CLI for the Delegance Brokerage platform").version(CLI_VERSION).enablePositionalOptions().option("-v, --verbose", "Enable verbose output").option("--json", "Output in JSON format").hook("preAction", () => {
4315
4801
  migrateLegacyConfigKey();
4316
4802
  });
@@ -4336,6 +4822,7 @@ function createProgram() {
4336
4822
  program.addCommand(createBondCommand());
4337
4823
  program.addCommand(createClaimCommand());
4338
4824
  program.addCommand(createFeedbackCommand());
4825
+ program.addCommand(createTermsCommand());
4339
4826
  program.addCommand(createConfigCommand());
4340
4827
  return program;
4341
4828
  }