@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.
@@ -24,20 +24,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/bin/delegance.ts
27
- var import_chalk3 = __toESM(require("chalk"));
27
+ var import_chalk4 = __toESM(require("chalk"));
28
28
 
29
29
  // src/program.ts
30
- var import_commander19 = require("commander");
30
+ var import_commander20 = require("commander");
31
31
 
32
32
  // src/version.ts
33
- var CLI_VERSION = "0.2.1";
33
+ var CLI_VERSION = "0.3.0";
34
34
 
35
35
  // src/commands/auth.ts
36
36
  var os4 = __toESM(require("os"));
37
- var import_commander2 = require("commander");
38
- var import_inquirer2 = __toESM(require("inquirer"));
37
+ var import_commander3 = require("commander");
38
+ var import_inquirer3 = __toESM(require("inquirer"));
39
39
  var import_ora2 = __toESM(require("ora"));
40
- var import_sdk3 = require("@delegance/sdk");
40
+ var import_sdk4 = require("@delegance/sdk");
41
41
 
42
42
  // src/utils/config.ts
43
43
  var import_conf = __toESM(require("conf"));
@@ -235,12 +235,28 @@ function formatValue(value) {
235
235
  }
236
236
  return String(value);
237
237
  }
238
+ function visibleWidth(s) {
239
+ return s.replace(/\x1b\[[0-9;]*m/g, "").length;
240
+ }
241
+ function renderCompactTable(headers, rows) {
242
+ const cells = rows.map((r) => headers.map((_, i) => r[i] === null || r[i] === void 0 ? "-" : String(r[i])));
243
+ const widths = headers.map((h, i) => Math.max(visibleWidth(h), ...cells.map((r) => visibleWidth(r[i]))));
244
+ const line = (parts) => ` ${parts.map((p, i) => p + " ".repeat(widths[i] - visibleWidth(p))).join(" ")}`.replace(/\s+$/, "");
245
+ return [
246
+ line(headers.map((h) => import_chalk.default.bold(h))),
247
+ import_chalk.default.dim(line(widths.map((w) => "\u2500".repeat(w)))),
248
+ ...cells.map(line)
249
+ ].join("\n");
250
+ }
238
251
  function table(headers, rows, options = {}) {
252
+ if (options.compact) {
253
+ console.log(renderCompactTable(headers, rows));
254
+ return;
255
+ }
239
256
  const tbl = new import_cli_table3.default({
240
257
  head: headers.map((h) => import_chalk.default.bold(h)),
241
258
  style: {
242
- head: ["cyan"],
243
- compact: options.compact
259
+ head: ["cyan"]
244
260
  }
245
261
  });
246
262
  for (const row of rows) {
@@ -262,6 +278,15 @@ function formatDate(dateStr) {
262
278
  minute: "2-digit"
263
279
  });
264
280
  }
281
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
282
+ function formatDateOnly(iso) {
283
+ if (!iso) return "";
284
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso);
285
+ if (!m) return iso;
286
+ const month = MONTHS[Number(m[2]) - 1];
287
+ if (!month) return iso;
288
+ return `${month} ${Number(m[3])}, ${m[1]}`;
289
+ }
265
290
  function formatFileSize(bytes) {
266
291
  if (bytes === void 0) return import_chalk.default.gray("(unknown)");
267
292
  const units = ["B", "KB", "MB", "GB"];
@@ -371,14 +396,26 @@ function installLastCommandRecorder(program2) {
371
396
  });
372
397
  }
373
398
 
399
+ // src/utils/invocation.ts
400
+ var NPX_INVOCATION = "npx -y @delegance/cli";
401
+ function cliInvocation(env = process.env, argv = process.argv) {
402
+ const entry = (argv[1] ?? "").replace(/\\/g, "/");
403
+ if (entry.includes("/_npx/")) return NPX_INVOCATION;
404
+ if (env.npm_command === "exec" && /(^|\/)delegance(\.[cm]?js)?$/.test(entry)) return NPX_INVOCATION;
405
+ return "delegance";
406
+ }
407
+ function cliCommand(rest) {
408
+ return `${cliInvocation()} ${rest}`;
409
+ }
410
+
374
411
  // src/utils/client.ts
375
412
  var PORTAL_URL = "https://portal.delegancebrokerage.com";
376
413
  function getClient() {
377
414
  const apiKey = getApiKey();
378
415
  if (!apiKey) {
379
416
  error("Not authenticated");
380
- info('New to Delegance? Run "delegance signup" to create an account.');
381
- info('Have an API key? Run "delegance auth login", or set DELEGANCE_API_KEY.');
417
+ info(`New to Delegance? Run "${cliInvocation()} signup" to create an account.`);
418
+ info(`Have an API key? Run "${cliInvocation()} auth login", or set DELEGANCE_API_KEY.`);
382
419
  process.exit(1);
383
420
  }
384
421
  return new import_sdk.DeleganceClient({
@@ -390,7 +427,7 @@ function getCompanyId(options) {
390
427
  const companyId = options.company || getConfigValue("defaultCompanyId");
391
428
  if (!companyId) {
392
429
  error("No company specified");
393
- info('Use --company <id> or set a default with "delegance company use <id>"');
430
+ info(`Use --company <id> or set a default with "${cliInvocation()} company use <id>"`);
394
431
  process.exit(1);
395
432
  }
396
433
  return companyId;
@@ -402,9 +439,9 @@ function describeApiError(err) {
402
439
  }
403
440
  if (err instanceof import_sdk.AuthenticationError) {
404
441
  if (err.reason === "key_expired" || err.reason === "key_membership_revoked") {
405
- return { message: `${err.message}${traceSuffix}`, hint: 'Run "delegance auth login" to sign in again.' };
442
+ return { message: `${err.message}${traceSuffix}`, hint: `Run "${cliInvocation()} auth login" to sign in again.` };
406
443
  }
407
- return { message: `${err.message}${traceSuffix}`, hint: 'Check your key with "delegance auth status", or log in again.' };
444
+ return { message: `${err.message}${traceSuffix}`, hint: `Check your key with "${cliInvocation()} auth status", or log in again.` };
408
445
  }
409
446
  if (err instanceof import_sdk.ForbiddenError) {
410
447
  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." };
@@ -465,10 +502,10 @@ function openInBrowser(url, platform = process.platform) {
465
502
 
466
503
  // src/commands/signup.ts
467
504
  var import_crypto = require("crypto");
468
- var import_commander = require("commander");
469
- var import_inquirer = __toESM(require("inquirer"));
505
+ var import_commander2 = require("commander");
506
+ var import_inquirer2 = __toESM(require("inquirer"));
470
507
  var import_ora = __toESM(require("ora"));
471
- var import_sdk2 = require("@delegance/sdk");
508
+ var import_sdk3 = require("@delegance/sdk");
472
509
 
473
510
  // src/utils/pending-signup.ts
474
511
  var fs3 = __toESM(require("fs"));
@@ -509,6 +546,82 @@ function clearPendingSignup(home) {
509
546
  }
510
547
  }
511
548
 
549
+ // src/commands/terms.ts
550
+ var import_commander = require("commander");
551
+ var import_inquirer = __toESM(require("inquirer"));
552
+ var import_sdk2 = require("@delegance/sdk");
553
+ function termsAcceptRefusal(prompted) {
554
+ if (!prompted) {
555
+ return { kind: "error", message: `No prompt to answer. Read the Terms, then run "${cliCommand("terms accept --yes")}".` };
556
+ }
557
+ return { kind: "warn", message: "Not accepted. You can still quote; binding needs the current Terms." };
558
+ }
559
+ function termsLines(t) {
560
+ return [
561
+ `Delegance Terms of Service (version ${t.version}): ${t.termsUrl}`,
562
+ `Privacy Policy: ${t.privacyUrl}`,
563
+ ...t.summaries
564
+ ];
565
+ }
566
+ async function confirmTerms(t, opts) {
567
+ termsLines(t).forEach((l) => (opts.print ?? info)(l));
568
+ if (opts.flag) return true;
569
+ if (!opts.interactive) return false;
570
+ const ask = opts.ask ?? (async () => {
571
+ const a = await import_inquirer.default.prompt([{
572
+ type: "confirm",
573
+ name: "ok",
574
+ message: "Do you accept the Terms of Service and Privacy Policy?",
575
+ default: false
576
+ }]);
577
+ return a.ok === true;
578
+ });
579
+ return ask();
580
+ }
581
+ function createTermsCommand() {
582
+ 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) => {
583
+ try {
584
+ const t = await (0, import_sdk2.createSignup)({ baseUrl: getBaseUrl() }).getTerms();
585
+ if (options.json) {
586
+ json(t);
587
+ return;
588
+ }
589
+ termsLines(t).forEach((l) => info(l));
590
+ info(`Broker review before you bind: ${t.brokerReview.command}, or email ${t.brokerReview.email}`);
591
+ } catch (err) {
592
+ failWith("Could not load the Terms", err);
593
+ }
594
+ });
595
+ 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) => {
596
+ const client = getClient();
597
+ try {
598
+ const t = await client.terms.get();
599
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json;
600
+ const ok = await confirmTerms(t, {
601
+ flag: options.yes === true,
602
+ interactive,
603
+ // --json keeps stdout to one JSON document; the Terms still print, on stderr.
604
+ ...options.json ? { print: (l) => console.error(l) } : {}
605
+ });
606
+ if (!ok) {
607
+ const refusal = termsAcceptRefusal(interactive);
608
+ if (refusal.kind === "error") error(refusal.message);
609
+ else warn(refusal.message);
610
+ process.exit(1);
611
+ }
612
+ const r = await client.terms.accept(t.version);
613
+ if (options.json) {
614
+ json(r);
615
+ return;
616
+ }
617
+ success(`Accepted the Terms of Service, version ${r.version}.`);
618
+ } catch (err) {
619
+ failWith("Could not record your acceptance", err);
620
+ }
621
+ });
622
+ return cmd;
623
+ }
624
+
512
625
  // src/commands/signup.ts
513
626
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
514
627
  var COMPANY_SIZES = ["0", "1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"];
@@ -533,34 +646,72 @@ function addressProblem(a) {
533
646
  if (!/^\d{5}(-\d{4})?$/.test(a.zip.trim())) return "ZIP must be 5 digits (or ZIP+4).";
534
647
  return null;
535
648
  }
649
+ var TERMS_REASONS = /* @__PURE__ */ new Set(["terms_not_accepted", "terms_version_outdated"]);
650
+ function isTermsRefusal(err) {
651
+ return err instanceof import_sdk3.DeleganceError && TERMS_REASONS.has(String(err.reason ?? ""));
652
+ }
653
+ async function loadSignupTerms(get) {
654
+ try {
655
+ return await get();
656
+ } catch (err) {
657
+ if (err instanceof import_sdk3.DeleganceError && err.statusCode === 404) return null;
658
+ throw err;
659
+ }
660
+ }
661
+ async function loadSignupTermsOrExit(baseUrl) {
662
+ try {
663
+ return await loadSignupTerms(() => (0, import_sdk3.createSignup)({ baseUrl }).getTerms());
664
+ } catch (err) {
665
+ failWith("Could not load the Terms of Service", err);
666
+ }
667
+ }
668
+ function nonInteractiveMissing(options, terms) {
669
+ const missing = missingSignupFields(options);
670
+ if (terms && options.acceptTerms !== true) missing.push("--accept-terms");
671
+ return missing;
672
+ }
673
+ async function acceptTermsOrExit(baseUrl, flag, preloaded) {
674
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
675
+ const terms = preloaded === void 0 ? await loadSignupTermsOrExit(baseUrl) : preloaded;
676
+ if (!terms) return "";
677
+ const ok = await confirmTerms(terms, { flag, interactive });
678
+ if (!ok) {
679
+ if (interactive) warn("Not signed up. Delegance needs your acceptance of the Terms and Privacy Policy to open an account.");
680
+ else error("No terminal to ask in. Read the Terms and Privacy Policy above, then pass --accept-terms.");
681
+ process.exit(1);
682
+ }
683
+ return terms.version;
684
+ }
536
685
  function exchangeRefusal(err) {
537
- if (!(err instanceof import_sdk2.DeleganceError)) return null;
686
+ if (!(err instanceof import_sdk3.DeleganceError)) return null;
538
687
  switch (err.reason) {
539
688
  case "account_exists":
540
689
  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`;
541
690
  case "already_collected":
542
691
  return `The key for this signup was already collected. If you lost it, create a new key at ${PORTAL_URL}/portal/settings/api-keys`;
543
692
  case "expired":
544
- return 'This signup expired (24 hours). Run "delegance signup" again.';
693
+ return `This signup expired (24 hours). Run "${cliInvocation()} signup" again.`;
545
694
  default:
546
695
  return null;
547
696
  }
548
697
  }
549
698
  async function ensureEnrolled(pending) {
550
699
  if (pending.enrollmentId) return pending;
551
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
700
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
552
701
  const hash = (0, import_crypto.createHash)("sha256").update(pending.deviceSecret).digest("hex");
553
702
  const enrollment = await signup.enroll(pending.bootstrapKey, {
554
703
  deviceSecretHash: hash,
555
704
  firstName: pending.firstName ?? "",
556
- lastName: pending.lastName ?? ""
705
+ lastName: pending.lastName ?? "",
706
+ termsAccepted: true,
707
+ termsVersion: pending.termsVersion ?? ""
557
708
  });
558
709
  const next = { ...pending, enrollmentId: enrollment.enrollmentId, verificationSent: false };
559
710
  savePendingSignup(next);
560
711
  return sendVerification(next);
561
712
  }
562
713
  async function sendVerification(pending) {
563
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
714
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
564
715
  const next = { ...pending, verificationSent: true };
565
716
  savePendingSignup(next);
566
717
  return next;
@@ -571,14 +722,14 @@ function storeOrPrintKey(apiKey, store = storeApiKey) {
571
722
  return true;
572
723
  } catch (err) {
573
724
  error(`Could not save the key to ~/.delegance/credentials: ${err.message}`);
574
- warn('Your key is below. It is shown once. Save it now, then run "delegance auth login --key <key>".');
725
+ warn(`Your key is below. It is shown once. Save it now, then run "${cliInvocation()} auth login --key <key>".`);
575
726
  console.log(apiKey);
576
727
  return false;
577
728
  }
578
729
  }
579
730
  async function waitAndStore(pending, timeoutMs) {
580
- const signup = (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl });
581
- 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();
731
+ const signup = (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl });
732
+ 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();
582
733
  const started = Date.now();
583
734
  try {
584
735
  const result = await signup.waitForKey(pending.enrollmentId, pending.deviceSecret, {
@@ -590,7 +741,7 @@ async function waitAndStore(pending, timeoutMs) {
590
741
  });
591
742
  if (result.status !== "ready") {
592
743
  spinner.warn("Still waiting on the email confirmation.");
593
- info('Run "delegance verify" after you click the link.');
744
+ info(`Run "${cliInvocation()} verify" after you click the link.`);
594
745
  return;
595
746
  }
596
747
  spinner.stop();
@@ -598,7 +749,7 @@ async function waitAndStore(pending, timeoutMs) {
598
749
  setConfig("defaultCompanyId", result.companyId);
599
750
  clearPendingSignup();
600
751
  if (stored) success(`Verified. API key ${maskApiKey(result.apiKey)} saved to ~/.delegance/credentials`);
601
- success("You can quote now: delegance quote start --coverage gl");
752
+ success(`You can quote now: ${cliInvocation()} quote start --coverage gl`);
602
753
  } catch (err) {
603
754
  spinner.stop();
604
755
  const why = exchangeRefusal(err);
@@ -628,21 +779,24 @@ function signupPrompts(options, interactive) {
628
779
  return all.filter((q) => q.when !== false).map(({ when: _when, ...q }) => q);
629
780
  }
630
781
  function createSignupCommand() {
631
- 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) => {
782
+ 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) => {
632
783
  const existing = loadPendingSignup();
633
784
  if (existing) {
634
785
  warn(`A signup for ${existing.email} is already waiting for its email confirmation.`);
635
- info('Run "delegance verify" to finish it, or "delegance verify --cancel" to start over.');
786
+ info(`Run "${cliInvocation()} verify" to finish it, or "${cliInvocation()} verify --cancel" to start over.`);
636
787
  process.exit(1);
637
788
  }
789
+ const baseUrl = getBaseUrl();
790
+ let preloadedTerms;
638
791
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
639
- const missing = missingSignupFields(options);
792
+ preloadedTerms = await loadSignupTermsOrExit(baseUrl);
793
+ const missing = nonInteractiveMissing(options, preloadedTerms);
640
794
  if (missing.length) {
641
795
  error(`No terminal to ask in. Missing: ${missing.join(" ")}`);
642
796
  process.exit(1);
643
797
  }
644
798
  }
645
- const answers = await import_inquirer.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
799
+ const answers = await import_inquirer2.default.prompt(signupPrompts(options, Boolean(process.stdin.isTTY && process.stdout.isTTY)));
646
800
  const address = {
647
801
  street: String(options.street ?? answers.street).trim(),
648
802
  city: String(options.city ?? answers.city).trim(),
@@ -665,8 +819,8 @@ function createSignupCommand() {
665
819
  error(`--size must be one of: ${COMPANY_SIZES.join(", ")}`);
666
820
  process.exit(1);
667
821
  }
668
- const baseUrl = getBaseUrl();
669
- const signup = (0, import_sdk2.createSignup)({ baseUrl });
822
+ const termsVersion = await acceptTermsOrExit(baseUrl, options.acceptTerms === true, preloadedTerms);
823
+ const signup = (0, import_sdk3.createSignup)({ baseUrl });
670
824
  const spinner = (0, import_ora.default)("Creating your account...").start();
671
825
  try {
672
826
  const account = await signup.createAccount({
@@ -678,7 +832,7 @@ function createSignupCommand() {
678
832
  ...description ? { description } : {},
679
833
  ...options.website ? { website: options.website } : {}
680
834
  });
681
- const device = (0, import_sdk2.newDeviceSecret)();
835
+ const device = (0, import_sdk3.newDeviceSecret)();
682
836
  let pending = {
683
837
  enrollmentId: "",
684
838
  deviceSecret: device.secret,
@@ -687,6 +841,7 @@ function createSignupCommand() {
687
841
  email,
688
842
  firstName: String(options.first ?? answers.first).trim(),
689
843
  lastName: String(options.last ?? answers.last).trim(),
844
+ termsVersion,
690
845
  baseUrl,
691
846
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
692
847
  };
@@ -697,7 +852,7 @@ function createSignupCommand() {
697
852
  warn("We could not save your business address. Add it in the portal before quoting, or carriers cannot price you.");
698
853
  }
699
854
  if (options.wait === false) {
700
- info('After you click it, run "delegance verify" to collect your API key.');
855
+ info(`After you click it, run "${cliInvocation()} verify" to collect your API key.`);
701
856
  return;
702
857
  }
703
858
  await waitAndStore(pending, Number(options.timeout) * 6e4 || 15 * 6e4);
@@ -708,17 +863,17 @@ function createSignupCommand() {
708
863
  });
709
864
  }
710
865
  function resendFailureMessage(err) {
711
- if (err instanceof import_sdk2.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
866
+ if (err instanceof import_sdk3.DeleganceError && (err.statusCode === 401 || err.statusCode === 403)) {
712
867
  return "Your email is already confirmed, so there is nothing to re-send. Collecting your key now.";
713
868
  }
714
869
  const why = err instanceof Error ? err.message : String(err);
715
870
  return `Could not re-send the email (${why}). Still waiting for the link you already have.`;
716
871
  }
717
872
  function createVerifyCommand() {
718
- 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) => {
873
+ 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) => {
719
874
  const pending = loadPendingSignup();
720
875
  if (!pending) {
721
- info('No signup is waiting on this machine. Start one with "delegance signup".');
876
+ info(`No signup is waiting on this machine. Start one with "${cliInvocation()} signup".`);
722
877
  return;
723
878
  }
724
879
  if (options.cancel) {
@@ -735,8 +890,21 @@ function createVerifyCommand() {
735
890
  failWith("Could not send the confirm email", err);
736
891
  }
737
892
  } else if (!pending.enrollmentId) {
893
+ let toEnroll = pending;
894
+ if (!pending.termsVersion) {
895
+ toEnroll = { ...pending, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
896
+ savePendingSignup(toEnroll);
897
+ }
738
898
  try {
739
- resumed = await ensureEnrolled(pending);
899
+ try {
900
+ resumed = await ensureEnrolled(toEnroll);
901
+ } catch (err) {
902
+ if (!isTermsRefusal(err)) throw err;
903
+ warn("The Terms of Service changed since this signup started. Review them again.");
904
+ toEnroll = { ...toEnroll, termsVersion: await acceptTermsOrExit(pending.baseUrl, options.acceptTerms === true) };
905
+ savePendingSignup(toEnroll);
906
+ resumed = await ensureEnrolled(toEnroll);
907
+ }
740
908
  success(`Finished setting up the signup. We emailed a confirm link to ${pending.email}.`);
741
909
  } catch (err) {
742
910
  failWith("Could not finish the signup", err);
@@ -744,7 +912,7 @@ function createVerifyCommand() {
744
912
  }
745
913
  if (options.resend && resumed === pending) {
746
914
  try {
747
- await (0, import_sdk2.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
915
+ await (0, import_sdk3.createSignup)({ baseUrl: pending.baseUrl }).requestVerification(pending.bootstrapKey);
748
916
  success(`Sent the confirm link to ${pending.email} again.`);
749
917
  } catch (err) {
750
918
  info(resendFailureMessage(err));
@@ -775,27 +943,27 @@ function describeExpiry(expiresAt, now = /* @__PURE__ */ new Date()) {
775
943
  return `${date} (in ${days} day${days === 1 ? "" : "s"})`;
776
944
  }
777
945
  function deviceLoginRefusal(err) {
778
- if (!(err instanceof import_sdk3.DeleganceError)) return null;
946
+ if (!(err instanceof import_sdk4.DeleganceError)) return null;
779
947
  switch (err.reason) {
780
948
  case "access_denied":
781
949
  return "The request was denied in the portal. Nothing was stored.";
782
950
  case "expired":
783
- return 'The code expired before it was approved. Run "delegance auth login" again.';
951
+ return `The code expired before it was approved. Run "${cliInvocation()} auth login" again.`;
784
952
  case "already_collected":
785
- return 'This login was already used. Run "delegance auth login" again.';
953
+ return `This login was already used. Run "${cliInvocation()} auth login" again.`;
786
954
  default:
787
955
  return null;
788
956
  }
789
957
  }
790
958
  function notAvailable(err) {
791
- return err instanceof import_sdk3.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
959
+ return err instanceof import_sdk4.DeleganceError && (err.statusCode === 404 || err.reason === "not_available");
792
960
  }
793
961
  function pasteFallbackHint() {
794
- info(`Create a key at ${PORTAL_URL}/portal/settings/api-keys, then run "delegance auth login --key <key>".`);
962
+ info(`Create a key at ${PORTAL_URL}/portal/settings/api-keys, then run "${cliInvocation()} auth login --key <key>".`);
795
963
  }
796
964
  async function readKeyInfo(apiKey, timeoutMs = 5e3) {
797
965
  try {
798
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
966
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: timeoutMs, retries: 0 });
799
967
  return await client.auth.keyInfo();
800
968
  } catch {
801
969
  return null;
@@ -816,7 +984,7 @@ async function loginWithKey(apiKey, skipVerify) {
816
984
  }
817
985
  const spinner = (0, import_ora2.default)("Verifying API key...").start();
818
986
  try {
819
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
987
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
820
988
  const isValid = await client.verifyApiKey();
821
989
  if (!isValid) {
822
990
  spinner.fail("API key verification failed");
@@ -837,8 +1005,8 @@ async function loginWithKey(apiKey, skipVerify) {
837
1005
  }
838
1006
  }
839
1007
  async function loginWithBrowser(openBrowser) {
840
- const login = (0, import_sdk3.createDeviceLogin)({ baseUrl: getBaseUrl() });
841
- const device = (0, import_sdk3.newDeviceSecret)();
1008
+ const login = (0, import_sdk4.createDeviceLogin)({ baseUrl: getBaseUrl() });
1009
+ const device = (0, import_sdk4.newDeviceSecret)();
842
1010
  let start;
843
1011
  try {
844
1012
  start = await login.start({ deviceSecretHash: device.hash, deviceName: defaultDeviceName() });
@@ -868,7 +1036,7 @@ async function loginWithBrowser(openBrowser) {
868
1036
  });
869
1037
  if (result.status !== "ready") {
870
1038
  spinner.fail("The code expired before it was approved.");
871
- info('Run "delegance auth login" again.');
1039
+ info(`Run "${cliInvocation()} auth login" again.`);
872
1040
  process.exit(1);
873
1041
  }
874
1042
  spinner.stop();
@@ -892,7 +1060,7 @@ async function loginWithBrowser(openBrowser) {
892
1060
  }
893
1061
  }
894
1062
  function createAuthCommand() {
895
- const auth = new import_commander2.Command("auth").description("Manage authentication");
1063
+ const auth = new import_commander3.Command("auth").description("Manage authentication");
896
1064
  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) => {
897
1065
  try {
898
1066
  if (options.key) {
@@ -900,7 +1068,7 @@ function createAuthCommand() {
900
1068
  return;
901
1069
  }
902
1070
  if (options.paste) {
903
- const answers = await import_inquirer2.default.prompt([
1071
+ const answers = await import_inquirer3.default.prompt([
904
1072
  {
905
1073
  type: "password",
906
1074
  name: "apiKey",
@@ -925,7 +1093,7 @@ function createAuthCommand() {
925
1093
  header("Authentication Status");
926
1094
  if (!isAuthenticated()) {
927
1095
  warn("Not authenticated");
928
- info('Run "delegance auth login" to sign in, or "delegance signup" to create an account');
1096
+ info(`Run "${cliInvocation()} auth login" to sign in, or "${cliInvocation()} signup" to create an account`);
929
1097
  return;
930
1098
  }
931
1099
  const apiKey = getApiKey() || "";
@@ -935,20 +1103,20 @@ function createAuthCommand() {
935
1103
  let origin = null;
936
1104
  let refused = null;
937
1105
  try {
938
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
1106
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl(), timeout: 5e3, retries: 0 });
939
1107
  const keyInfo = await client.auth.keyInfo();
940
1108
  origin = keyInfo.origin;
941
1109
  expiryLine = describeExpiry(keyInfo.expiresAt);
942
1110
  if (!fromEnv) setStoredKeyExpiry(keyInfo.expiresAt);
943
1111
  } catch (err) {
944
- if (err instanceof import_sdk3.DeleganceError && err.statusCode === 401) {
1112
+ if (err instanceof import_sdk4.DeleganceError && err.statusCode === 401) {
945
1113
  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";
946
1114
  expiryLine = err.reason === "key_expired" ? "Expired" : "Not valid";
947
1115
  }
948
1116
  }
949
1117
  if (refused) {
950
1118
  warn(refused);
951
- info('Run "delegance auth login" to sign in again.');
1119
+ info(`Run "${cliInvocation()} auth login" to sign in again.`);
952
1120
  } else {
953
1121
  success("Authenticated");
954
1122
  }
@@ -966,18 +1134,18 @@ function createAuthCommand() {
966
1134
  const apiKey = getApiKey();
967
1135
  if (!apiKey) {
968
1136
  error("Not authenticated");
969
- info('Run "delegance auth login" to sign in');
1137
+ info(`Run "${cliInvocation()} auth login" to sign in`);
970
1138
  process.exit(1);
971
1139
  }
972
1140
  const spinner = (0, import_ora2.default)("Refreshing your key...").start();
973
1141
  try {
974
- const client = new import_sdk3.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
1142
+ const client = new import_sdk4.DeleganceClient({ apiKey, baseUrl: getBaseUrl() });
975
1143
  const { expiresAt } = await client.auth.refresh();
976
1144
  if (!process.env.DELEGANCE_API_KEY) setStoredKeyExpiry(expiresAt);
977
1145
  spinner.succeed(`Key refreshed. Expires ${describeExpiry(expiresAt)}.`);
978
1146
  } catch (err) {
979
1147
  spinner.stop();
980
- if (err instanceof import_sdk3.DeleganceError && err.reason === "not_refreshable") {
1148
+ if (err instanceof import_sdk4.DeleganceError && err.reason === "not_refreshable") {
981
1149
  info("This key came from the portal and keeps the expiry it was created with. Nothing changed.");
982
1150
  return;
983
1151
  }
@@ -994,7 +1162,7 @@ function createAuthCommand() {
994
1162
  return;
995
1163
  }
996
1164
  if (!options.force) {
997
- const { confirm } = await import_inquirer2.default.prompt([
1165
+ const { confirm } = await import_inquirer3.default.prompt([
998
1166
  {
999
1167
  type: "confirm",
1000
1168
  name: "confirm",
@@ -1014,7 +1182,7 @@ function createAuthCommand() {
1014
1182
  auth.command("whoami").description("Show current authenticated identity").action(async () => {
1015
1183
  if (!isAuthenticated()) {
1016
1184
  error("Not authenticated");
1017
- info('Run "delegance auth login" to authenticate');
1185
+ info(`Run "${cliInvocation()} auth login" to authenticate`);
1018
1186
  process.exit(1);
1019
1187
  }
1020
1188
  const apiKey = getApiKey();
@@ -1024,7 +1192,7 @@ function createAuthCommand() {
1024
1192
  }
1025
1193
  const spinner = (0, import_ora2.default)("Fetching account info...").start();
1026
1194
  try {
1027
- const client = new import_sdk3.DeleganceClient({
1195
+ const client = new import_sdk4.DeleganceClient({
1028
1196
  apiKey,
1029
1197
  baseUrl: getBaseUrl()
1030
1198
  });
@@ -1052,11 +1220,11 @@ function createAuthCommand() {
1052
1220
  }
1053
1221
 
1054
1222
  // src/commands/company.ts
1055
- var import_commander3 = require("commander");
1056
- var import_inquirer3 = __toESM(require("inquirer"));
1223
+ var import_commander4 = require("commander");
1224
+ var import_inquirer4 = __toESM(require("inquirer"));
1057
1225
  var import_ora3 = __toESM(require("ora"));
1058
1226
  function createCompanyCommand() {
1059
- const company = new import_commander3.Command("company").alias("companies").description("Manage companies");
1227
+ const company = new import_commander4.Command("company").alias("companies").description("Manage companies");
1060
1228
  company.command("list").description("List companies").option("--include-created", "Include companies created via this API key").option("--json", "Output as JSON").action(async (options) => {
1061
1229
  const client = getClient();
1062
1230
  const spinner = (0, import_ora3.default)("Fetching companies...").start();
@@ -1092,7 +1260,7 @@ function createCompanyCommand() {
1092
1260
  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) => {
1093
1261
  let companyData;
1094
1262
  if (options.interactive || !options.name && !options.industry) {
1095
- const answers = await import_inquirer3.default.prompt([
1263
+ const answers = await import_inquirer4.default.prompt([
1096
1264
  {
1097
1265
  type: "input",
1098
1266
  name: "name",
@@ -1210,7 +1378,7 @@ function createCompanyCommand() {
1210
1378
  const companyId = getConfigValue("defaultCompanyId");
1211
1379
  if (!companyId) {
1212
1380
  info("No default company set");
1213
- info('Use "delegance company use <id>" to set one');
1381
+ info(`Use "${cliInvocation()} company use <id>" to set one`);
1214
1382
  return;
1215
1383
  }
1216
1384
  const client = getClient();
@@ -1238,7 +1406,7 @@ function createCompanyCommand() {
1238
1406
  }
1239
1407
 
1240
1408
  // src/commands/document.ts
1241
- var import_commander4 = require("commander");
1409
+ var import_commander5 = require("commander");
1242
1410
  var import_ora4 = __toESM(require("ora"));
1243
1411
  var fs4 = __toESM(require("fs"));
1244
1412
  var path4 = __toESM(require("path"));
@@ -1249,7 +1417,7 @@ function extractionOutcome(status) {
1249
1417
  return "pending";
1250
1418
  }
1251
1419
  function createDocumentCommand() {
1252
- const doc = new import_commander4.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1420
+ const doc = new import_commander5.Command("doc").alias("docs").alias("document").alias("documents").description("Manage documents");
1253
1421
  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) => {
1254
1422
  const companyId = getCompanyId(options);
1255
1423
  const client = getClient();
@@ -1484,7 +1652,7 @@ function createDocumentCommand() {
1484
1652
  process.exit(1);
1485
1653
  } else {
1486
1654
  waitSpinner.warn(`Extraction still ${finished.status}`);
1487
- if (!options.json) info(`Run "delegance doc wait ${documentId}" to keep following it`);
1655
+ if (!options.json) info(`Run "${cliInvocation()} doc wait ${documentId}" to keep following it`);
1488
1656
  }
1489
1657
  return;
1490
1658
  }
@@ -1492,7 +1660,7 @@ function createDocumentCommand() {
1492
1660
  json(result);
1493
1661
  } else {
1494
1662
  info(`${result.reprocessesRemaining} reprocess attempts left today`);
1495
- info(`Run "delegance doc wait ${documentId}" to follow it`);
1663
+ info(`Run "${cliInvocation()} doc wait ${documentId}" to follow it`);
1496
1664
  }
1497
1665
  } catch (err) {
1498
1666
  spinner.fail("Failed to reprocess document");
@@ -1527,11 +1695,11 @@ function createDocumentCommand() {
1527
1695
  }
1528
1696
 
1529
1697
  // src/commands/chat.ts
1530
- var import_commander5 = require("commander");
1698
+ var import_commander6 = require("commander");
1531
1699
  var import_ora5 = __toESM(require("ora"));
1532
- var import_inquirer4 = __toESM(require("inquirer"));
1700
+ var import_inquirer5 = __toESM(require("inquirer"));
1533
1701
  function createChatCommand() {
1534
- const chat = new import_commander5.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1702
+ const chat = new import_commander6.Command("ask").alias("chat").description("Ask the Orin insurance assistant a question");
1535
1703
  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) => {
1536
1704
  const question = questionParts.join(" ");
1537
1705
  const client = getClient();
@@ -1567,7 +1735,7 @@ function createChatCommand() {
1567
1735
  console.log('Type your questions. Enter "exit" or "quit" to end the session.');
1568
1736
  console.log();
1569
1737
  while (true) {
1570
- const { question } = await import_inquirer4.default.prompt([
1738
+ const { question } = await import_inquirer5.default.prompt([
1571
1739
  {
1572
1740
  type: "input",
1573
1741
  name: "question",
@@ -1627,18 +1795,102 @@ function createChatCommand() {
1627
1795
  }
1628
1796
 
1629
1797
  // src/commands/quote.ts
1630
- var import_commander6 = require("commander");
1798
+ var import_commander7 = require("commander");
1631
1799
  var import_ora7 = __toESM(require("ora"));
1632
- var import_inquirer6 = __toESM(require("inquirer"));
1633
- var import_sdk5 = require("@delegance/sdk");
1800
+ var import_inquirer7 = __toESM(require("inquirer"));
1801
+ var import_sdk6 = require("@delegance/sdk");
1634
1802
 
1635
1803
  // src/commands/instant-quote.ts
1636
1804
  var fs5 = __toESM(require("fs"));
1637
1805
  var import_crypto2 = require("crypto");
1638
1806
  var import_chalk2 = __toESM(require("chalk"));
1639
- var import_inquirer5 = __toESM(require("inquirer"));
1807
+ var import_inquirer6 = __toESM(require("inquirer"));
1640
1808
  var import_ora6 = __toESM(require("ora"));
1641
- var import_sdk4 = require("@delegance/sdk");
1809
+ var import_sdk5 = require("@delegance/sdk");
1810
+
1811
+ // src/utils/coverage-names.ts
1812
+ var NAMES = {
1813
+ // General liability
1814
+ cgl: "General Liability",
1815
+ gl: "General Liability",
1816
+ general_liability: "General Liability",
1817
+ // Workers' comp
1818
+ wc: "Workers' Comp",
1819
+ workers_comp: "Workers' Comp",
1820
+ workers_compensation: "Workers' Comp",
1821
+ // Business owner's policy
1822
+ bop: "Business Owner's Policy",
1823
+ business_owners: "Business Owner's Policy",
1824
+ business_owners_policy: "Business Owner's Policy",
1825
+ // Cyber
1826
+ cyber: "Cyber",
1827
+ cyber_liability: "Cyber",
1828
+ // Professional liability (E&O)
1829
+ mpl: "Professional Liability (E&O)",
1830
+ pl: "Professional Liability (E&O)",
1831
+ pro_liab: "Professional Liability (E&O)",
1832
+ professional_liability: "Professional Liability (E&O)",
1833
+ eo: "Professional Liability (E&O)",
1834
+ e_o: "Professional Liability (E&O)",
1835
+ tech_eo: "Tech E&O",
1836
+ errors_omissions: "Tech E&O",
1837
+ // Auto
1838
+ ca: "Commercial Auto",
1839
+ auto: "Commercial Auto",
1840
+ commercial_auto: "Commercial Auto",
1841
+ // Property
1842
+ cp: "Commercial Property",
1843
+ property: "Commercial Property",
1844
+ commercial_property: "Commercial Property",
1845
+ // Umbrella
1846
+ umbrella: "Umbrella",
1847
+ excess: "Umbrella",
1848
+ commercial_umbrella: "Umbrella",
1849
+ // Builders risk
1850
+ br: "Builders' Risk",
1851
+ builders_risk: "Builders' Risk",
1852
+ // Inland marine and marine
1853
+ im: "Inland Marine",
1854
+ inland_marine: "Inland Marine",
1855
+ marine: "Marine",
1856
+ // Management liability family
1857
+ ml: "Management Liability",
1858
+ management_liability: "Management Liability",
1859
+ do: "Directors and Officers (D&O)",
1860
+ d_o: "Directors and Officers (D&O)",
1861
+ directors_officers: "Directors and Officers (D&O)",
1862
+ epli: "Employment Practices Liability",
1863
+ employment_practices: "Employment Practices Liability",
1864
+ crime: "Crime",
1865
+ fiduciary: "Fiduciary Liability",
1866
+ fiduciary_liability: "Fiduciary Liability",
1867
+ // Everything else on the canonical list
1868
+ product_liability: "Product Liability",
1869
+ liquor_liability: "Liquor Liability",
1870
+ contractors_liability: "Contractors' Liability",
1871
+ equipment_breakdown: "Equipment Breakdown",
1872
+ environmental_liability: "Environmental Liability",
1873
+ healthcare_medical: "Healthcare Medical Liability",
1874
+ life_sciences: "Life Sciences",
1875
+ hospitality_programs: "Hospitality Program",
1876
+ commercial_flood: "Commercial Flood",
1877
+ home_based_business: "Home-Based Business",
1878
+ foreign_package: "Foreign Package",
1879
+ multinational_package: "Multinational Package",
1880
+ political_risk: "Political Risk",
1881
+ trade_credit: "Trade Credit",
1882
+ kidnap_ransom: "Kidnap and Ransom",
1883
+ product_recall: "Product Recall",
1884
+ railroad_liability: "Railroad Liability"
1885
+ };
1886
+ function coverageName(code) {
1887
+ if (code === null || code === void 0) return "";
1888
+ const key = code.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1889
+ return NAMES[key] ?? code;
1890
+ }
1891
+ function coverageNames(codes) {
1892
+ return codes.map(coverageName).filter(Boolean).join(", ");
1893
+ }
1642
1894
 
1643
1895
  // src/commerce/questions.ts
1644
1896
  var COVERAGE_ALIASES = {
@@ -1718,14 +1970,23 @@ function validateAnswers(questions, provided) {
1718
1970
  }
1719
1971
  return { answers, problems };
1720
1972
  }
1973
+ function rowStatus(q) {
1974
+ if (String(q.state).toUpperCase() === "REFERRED") {
1975
+ return q.resultStatus === "needs_info" ? "needs_info" : "referred";
1976
+ }
1977
+ return q.marketStatus || q.state;
1978
+ }
1721
1979
  function sortQuoteRows(quotes) {
1722
1980
  return quotes.map((q) => ({
1723
1981
  carrier: q.carrierName || q.carrierId,
1724
1982
  coverage: q.coverage ?? "",
1725
1983
  premium: q.premium,
1726
- status: q.marketStatus || q.state,
1984
+ status: rowStatus(q),
1727
1985
  bindable: q.bindable === true && q.state === "QUOTED",
1728
- opportunityId: q.opportunityId
1986
+ opportunityId: q.opportunityId,
1987
+ limits: typeof q.limits === "string" && q.limits.trim() ? q.limits : null,
1988
+ deductible: typeof q.deductible === "number" && Number.isFinite(q.deductible) ? q.deductible : null,
1989
+ message: typeof q.message === "string" && q.message.trim() ? q.message.trim() : null
1729
1990
  })).sort((a, b) => {
1730
1991
  if (a.bindable !== b.bindable) return a.bindable ? -1 : 1;
1731
1992
  if (a.premium === null && b.premium === null) return 0;
@@ -1734,8 +1995,50 @@ function sortQuoteRows(quotes) {
1734
1995
  return a.premium - b.premium;
1735
1996
  });
1736
1997
  }
1737
- function cheapestBindable(rows) {
1738
- return rows.find((r) => r.bindable && r.premium !== null) ?? null;
1998
+ function bestPerCoverage(rows) {
1999
+ const best = /* @__PURE__ */ new Map();
2000
+ for (const r of rows) {
2001
+ if (!r.bindable || r.premium === null) continue;
2002
+ const key = coverageName(r.coverage);
2003
+ const cur = best.get(key);
2004
+ if (!cur || r.premium < cur.premium) best.set(key, r);
2005
+ }
2006
+ return [...best.values()].sort((a, b) => a.premium - b.premium);
2007
+ }
2008
+ function groupRowsByCoverage(rows) {
2009
+ const order = /* @__PURE__ */ new Map();
2010
+ rows.forEach((r) => {
2011
+ const key = coverageName(r.coverage);
2012
+ if (!order.has(key)) order.set(key, order.size);
2013
+ });
2014
+ const rank = (r) => order.get(coverageName(r.coverage));
2015
+ return rows.map((r, i) => ({ r, i })).sort((a, b) => rank(a.r) - rank(b.r) || a.i - b.i).map((x) => x.r);
2016
+ }
2017
+ var STATUS_WORDS = {
2018
+ quote: "Quoted",
2019
+ quoted: "Quoted",
2020
+ declined: "Declined",
2021
+ decline: "Declined",
2022
+ quoting: "Pricing",
2023
+ pending: "Pricing",
2024
+ submitted: "Pricing",
2025
+ in_progress: "Pricing",
2026
+ referred: "Referred to an underwriter",
2027
+ refer: "Referred to an underwriter",
2028
+ needs_info: "Needs more info",
2029
+ awaiting_broker_review: "With a broker",
2030
+ broker_review: "With a broker",
2031
+ bind_requested: "Bind requested",
2032
+ bound: "Bound",
2033
+ expired: "Expired",
2034
+ error: "Failed",
2035
+ failed: "Failed"
2036
+ };
2037
+ function quoteStatusWord(status) {
2038
+ const key = status.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_");
2039
+ if (STATUS_WORDS[key]) return STATUS_WORDS[key];
2040
+ const words = key.replace(/_/g, " ").trim();
2041
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : status;
1739
2042
  }
1740
2043
  function summarizeStatus(s) {
1741
2044
  const quoted = s.carrierQuotes.filter((q) => q.premium !== null).length;
@@ -1785,7 +2088,14 @@ function formatKnown(q, value) {
1785
2088
  }
1786
2089
 
1787
2090
  // src/commerce/demo.ts
1788
- var DEMO_BUSINESS = "Riverbend Bakery (demo), Austin TX, 6 employees";
2091
+ var DEMO_BUSINESS = "Riverbend Bakery (demo), Austin TX";
2092
+ var DEMO_SHORT_LABELS = {
2093
+ annual_revenue: "Annual revenue",
2094
+ employees: "Full-time employees",
2095
+ delivery: "Delivers orders",
2096
+ delivery_vehicles: "Delivery vehicles",
2097
+ claims_5y: "Claims in last 5 years"
2098
+ };
1789
2099
  var DEMO_QUESTIONS = [
1790
2100
  { id: "annual_revenue", label: "Annual revenue (USD)", type: "currency", required: true, prefill: 85e4 },
1791
2101
  { id: "employees", label: "Full-time employees", type: "number", required: true, prefill: 6 },
@@ -1819,6 +2129,7 @@ var DEMO_QUESTIONS = [
1819
2129
  ];
1820
2130
  var DEMO_STATUS = {
1821
2131
  submissionId: "demo-submission",
2132
+ effectiveDate: "2026-11-01",
1822
2133
  coverages: ["general_liability", "workers_comp"],
1823
2134
  expiresAt: null,
1824
2135
  submitted: true,
@@ -1826,19 +2137,19 @@ var DEMO_STATUS = {
1826
2137
  allCarriersResolved: true,
1827
2138
  awaitingBrokerReviewCount: 0,
1828
2139
  carrierQuotes: [
1829
- { opportunityId: "demo-1", carrierId: "CARRIER_A", carrierName: "Carrier A", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 612, quoteNumber: "DEMO-GL-1", bindable: true },
1830
- { opportunityId: "demo-2", carrierId: "CARRIER_B", carrierName: "Carrier B", coverage: "CGL", state: "QUOTED", marketStatus: "quote", premium: 748, quoteNumber: "DEMO-GL-2", bindable: true },
1831
- { opportunityId: "demo-3", carrierId: "CARRIER_C", carrierName: "Carrier C", coverage: "WC", state: "QUOTED", marketStatus: "quote", premium: 1184, quoteNumber: "DEMO-WC-1", bindable: true },
1832
- { opportunityId: "demo-4", carrierId: "CARRIER_D", carrierName: "Carrier D", coverage: "WC", state: "DECLINED", marketStatus: "declined", premium: null, quoteNumber: null, bindable: false }
2140
+ { 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 },
2141
+ { 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 },
2142
+ { 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 },
2143
+ { 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 }
1833
2144
  ]
1834
2145
  };
1835
2146
 
1836
2147
  // src/commands/instant-quote.ts
1837
2148
  function activeRequestLines(err, coverageFlag) {
1838
- if (!(err instanceof import_sdk4.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
2149
+ if (!(err instanceof import_sdk5.DeleganceError) || err.statusCode !== 409 || !err.body) return null;
1839
2150
  const { body } = err;
1840
2151
  const code = body.message;
1841
- const requote = `delegance quote start --coverage ${coverageFlag} --replace`;
2152
+ const requote = `${cliInvocation()} quote start --coverage ${coverageFlag} --replace`;
1842
2153
  if (code === "active_request_exists") {
1843
2154
  const active = Array.isArray(body.active) ? body.active : [];
1844
2155
  const first = active[0];
@@ -1846,7 +2157,7 @@ function activeRequestLines(err, coverageFlag) {
1846
2157
  const carriers = Array.isArray(first?.carriers) ? first.carriers.map((c) => `${c.carrierId}${c.state ? ` (${c.state.toLowerCase()})` : ""}`).join(", ") : "";
1847
2158
  return [
1848
2159
  `Already with carriers${id ? `: ${id}` : ""}${carriers ? `, ${carriers}` : ""}.`,
1849
- `Check it: ${id ? `delegance quote status ${id}` : "delegance quote status <id>"} Replace it: ${requote}`
2160
+ `Check it: ${id ? `${cliInvocation()} quote status ${id}` : `${cliInvocation()} quote status <id>`} Replace it: ${requote}`
1850
2161
  ];
1851
2162
  }
1852
2163
  if (code === "replace_conflict") {
@@ -1898,7 +2209,7 @@ async function askOne(q, answers, fallback) {
1898
2209
  }
1899
2210
  };
1900
2211
  }
1901
- const { v } = await import_inquirer5.default.prompt([prompt]);
2212
+ const { v } = await import_inquirer6.default.prompt([prompt]);
1902
2213
  const c = coerceAnswer(q, v);
1903
2214
  if (c.ok && c.value !== void 0) answers[q.id] = c.value;
1904
2215
  }
@@ -1909,7 +2220,7 @@ async function askQuestions(questions, answers = {}) {
1909
2220
  const round = planQuestionRound(questions, answers, handled);
1910
2221
  if (round.confirm.length + round.checklist.length + round.ask.length === 0) break;
1911
2222
  if (round.confirm.length) {
1912
- const { keep } = await import_inquirer5.default.prompt([
2223
+ const { keep } = await import_inquirer6.default.prompt([
1913
2224
  {
1914
2225
  type: "checkbox",
1915
2226
  name: "keep",
@@ -1938,7 +2249,7 @@ async function askQuestions(questions, answers = {}) {
1938
2249
  }
1939
2250
  }
1940
2251
  if (round.checklist.length) {
1941
- const { yes } = await import_inquirer5.default.prompt([
2252
+ const { yes } = await import_inquirer6.default.prompt([
1942
2253
  {
1943
2254
  type: "checkbox",
1944
2255
  name: "yes",
@@ -1949,7 +2260,7 @@ async function askQuestions(questions, answers = {}) {
1949
2260
  ]);
1950
2261
  const yn = checklistAnswers(round.checklist, yes);
1951
2262
  const yesCount = Object.values(yn).filter((v) => v === "yes").length;
1952
- const { ok } = await import_inquirer5.default.prompt([
2263
+ const { ok } = await import_inquirer6.default.prompt([
1953
2264
  { type: "confirm", name: "ok", message: `Yes to ${yesCount}, No to ${round.checklist.length - yesCount}. Correct?`, default: true }
1954
2265
  ]);
1955
2266
  if (ok) {
@@ -1973,7 +2284,7 @@ function handoffLines(r) {
1973
2284
  if (!r.alreadyHandedOff && r.unansweredRequired > 0) {
1974
2285
  lines.push(`The broker will email you for the ${r.unansweredRequired} answer(s) still missing.`);
1975
2286
  }
1976
- lines.push(`Check it: delegance quote status ${r.submissionId}`);
2287
+ lines.push(`Check it: ${cliInvocation()} quote status ${r.submissionId}`);
1977
2288
  return lines;
1978
2289
  }
1979
2290
  async function runBrokerHandoff(submissionId, instantAnswers, opts) {
@@ -1983,7 +2294,7 @@ async function runBrokerHandoff(submissionId, instantAnswers, opts) {
1983
2294
  try {
1984
2295
  plan = await client.instantQuotes.brokerHandoffQuestions(submissionId, instantAnswers);
1985
2296
  } catch (err) {
1986
- if (err instanceof import_sdk4.DeleganceError && err.statusCode === 503) {
2297
+ if (err instanceof import_sdk5.DeleganceError && err.statusCode === 503) {
1987
2298
  say("A broker can still market it: reply to the confirmation email, or start in the portal.");
1988
2299
  return;
1989
2300
  }
@@ -2014,7 +2325,7 @@ async function runBrokerHandoff(submissionId, instantAnswers, opts) {
2014
2325
  process.exit(1);
2015
2326
  }
2016
2327
  } else if (!opts.json && isInteractive() && plan.questions.length > 0) {
2017
- info(`A broker can place ${plan.coverages.join(", ")} with a market that quotes by hand. ${plan.questions.length} application question(s) left.`);
2328
+ info(`A broker can place ${coverageNames(plan.coverages)} with a market that quotes by hand. ${plan.questions.length} application question(s) left.`);
2018
2329
  info("Press Ctrl-C to stop at any point; what you have answered goes to the broker.");
2019
2330
  const onInterrupt = () => {
2020
2331
  complete = false;
@@ -2046,7 +2357,7 @@ async function sendHandoff(submissionId, input, idempotencyKey, asJson) {
2046
2357
  else handoffLines(result).forEach((l) => info(l));
2047
2358
  } catch (err) {
2048
2359
  spinner?.fail("Could not reach a broker");
2049
- console.error(`Try again: delegance quote handoff ${submissionId}`);
2360
+ console.error(`Try again: ${cliInvocation()} quote handoff ${submissionId}`);
2050
2361
  failWith("API error", err);
2051
2362
  }
2052
2363
  }
@@ -2057,8 +2368,34 @@ function printFloorDrops(failures) {
2057
2368
  floors.forEach((f) => console.log(` - ${f.carrierId}: ${f.missing}`));
2058
2369
  info("Add it to your business profile in the portal, then run the quote again.");
2059
2370
  }
2371
+ 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.";
2372
+ var premiumText = (n) => n === null ? "-" : formatCurrency(n);
2373
+ var deductibleText = (n) => n === null ? "-" : n === 0 ? "None" : formatCurrency(n);
2374
+ function bestPriceLines(best) {
2375
+ if (best.length === 0) return [];
2376
+ const names = best.map((r) => coverageName(r.coverage));
2377
+ const nameW = Math.max(...names.map((n) => n.length));
2378
+ const carrierW = Math.max(...best.map((r) => r.carrier.length));
2379
+ return [
2380
+ "Best price per coverage:",
2381
+ ...best.map((r, i) => ` ${names[i].padEnd(nameW)} ${r.carrier.padEnd(carrierW)} ${formatCurrency(r.premium)}/yr`)
2382
+ ];
2383
+ }
2384
+ function bindHintLines(submissionId, best) {
2385
+ if (best.length === 1) return [`Bind it: ${cliCommand(`bind ${submissionId} ${best[0].opportunityId}`)}`];
2386
+ return best.map((r) => `Bind ${coverageName(r.coverage)}: ${cliCommand(`bind ${submissionId} ${r.opportunityId}`)}`);
2387
+ }
2388
+ function demoClosingLines(best) {
2389
+ const example = best[0] ? ` (e.g. bind ... ${best[0].opportunityId})` : "";
2390
+ return [
2391
+ `Next, on a real quote: ${cliCommand("bind <quote id> <offer>")}${example}`,
2392
+ "DEMO: sample premiums, nothing went to a carrier.",
2393
+ `Get real quotes: ${cliCommand("signup")}`,
2394
+ AGENT_TIP
2395
+ ];
2396
+ }
2060
2397
  function printQuoteTable(status, opts = {}) {
2061
- const rows = sortQuoteRows(status.carrierQuotes);
2398
+ const rows = groupRowsByCoverage(sortQuoteRows(status.carrierQuotes));
2062
2399
  if (rows.length === 0) {
2063
2400
  if (status.brokerReview) {
2064
2401
  info(`A broker has this request (${status.brokerReview.status.replace(/_/g, " ")}). They place it by hand and email you with quotes or questions.`);
@@ -2068,25 +2405,67 @@ function printQuoteTable(status, opts = {}) {
2068
2405
  if (status.awaitingBrokerReviewCount > 0) info(`${status.awaitingBrokerReviewCount} quote(s) are with a broker for review.`);
2069
2406
  return;
2070
2407
  }
2071
- const best = cheapestBindable(rows);
2072
- if (best) {
2073
- console.log(import_chalk2.default.bold(`${opts.demo ? "[DEMO] " : ""}Cheapest bindable: ${best.carrier} ${best.coverage} at ${formatCurrency(best.premium)}/yr`));
2408
+ const best = bestPerCoverage(rows);
2409
+ const bestIds = new Set(best.map((r) => r.opportunityId));
2410
+ const effectiveDate = status.effectiveDate;
2411
+ console.log();
2412
+ if (effectiveDate && opts.showStartDate !== false) {
2413
+ console.log(`Coverage starts ${formatDateOnly(effectiveDate)}`);
2414
+ }
2415
+ const bestLines = bestPriceLines(best);
2416
+ if (bestLines.length) {
2417
+ console.log(import_chalk2.default.bold(bestLines[0]));
2418
+ bestLines.slice(1).forEach((l) => console.log(l));
2419
+ console.log();
2074
2420
  }
2075
2421
  table(
2076
- ["Carrier", "Coverage", "Premium/yr", "Status", "Bindable", "Offer id"],
2422
+ ["Carrier", "Coverage", "Premium/yr", "Limits", "Deductible", "Status", "Offer"],
2077
2423
  rows.map((r) => {
2078
- const cells = [r.carrier, r.coverage, r.premium === null ? "-" : formatCurrency(r.premium), r.status, r.bindable ? "yes" : "no", r.opportunityId];
2079
- return r === best ? cells.map((c) => import_chalk2.default.bold(String(c))) : cells;
2080
- })
2424
+ const cells = [
2425
+ r.carrier,
2426
+ coverageName(r.coverage),
2427
+ premiumText(r.premium),
2428
+ r.limits ?? "-",
2429
+ deductibleText(r.deductible),
2430
+ quoteStatusWord(r.status),
2431
+ r.opportunityId
2432
+ ];
2433
+ return bestIds.has(r.opportunityId) ? cells.map((c) => import_chalk2.default.bold(c)) : cells;
2434
+ }),
2435
+ { compact: true }
2081
2436
  );
2082
- console.log(import_chalk2.default.dim(summarizeStatus(status)));
2083
- if (best && !opts.demo) {
2084
- console.log(import_chalk2.default.green(`Bind it: delegance bind ${status.submissionId} ${best.opportunityId}`));
2437
+ const reasons = rows.filter((r) => r.message);
2438
+ if (reasons.length) {
2439
+ console.log();
2440
+ reasons.forEach((r) => console.log(`${r.carrier} (${quoteStatusWord(r.status)}): ${r.message}`));
2085
2441
  }
2086
- if (opts.demo) console.log(import_chalk2.default.yellow('DEMO: sample premiums, nothing was sent to a carrier. Run "delegance signup" for real quotes.'));
2442
+ console.log();
2443
+ console.log(import_chalk2.default.dim(`${summarizeStatus(status)}.`));
2444
+ if (opts.demo) {
2445
+ const [next, notice, signup, tip] = demoClosingLines(best);
2446
+ console.log(import_chalk2.default.green(next));
2447
+ console.log(import_chalk2.default.yellow(notice));
2448
+ console.log(import_chalk2.default.yellow(signup));
2449
+ console.log(import_chalk2.default.dim(tip));
2450
+ return;
2451
+ }
2452
+ bindHintLines(status.submissionId, best).forEach((l) => console.log(import_chalk2.default.green(l)));
2453
+ }
2454
+ function demoAnswerLines(answers, effectiveDate) {
2455
+ const pairs = [];
2456
+ for (const q of DEMO_QUESTIONS) {
2457
+ if (answers[q.id] === void 0) continue;
2458
+ const v = answers[q.id];
2459
+ const shown = q.type === "currency" && typeof v === "number" ? formatCurrency(v) : formatKnown(q, v);
2460
+ pairs.push([DEMO_SHORT_LABELS[q.id] ?? q.label, shown]);
2461
+ }
2462
+ if (effectiveDate) pairs.push(["Coverage starts", formatDateOnly(effectiveDate)]);
2463
+ const w = Math.max(...pairs.map(([k]) => k.length));
2464
+ return ["Sample answers (a real quote asks you these):", ...pairs.map(([k, v]) => ` ${k.padEnd(w)} ${v}`)];
2087
2465
  }
2088
2466
  async function runDemo(asJson, answersFile) {
2089
2467
  (asJson ? console.error : console.log)(import_chalk2.default.yellow(`DEMO quote for ${DEMO_BUSINESS}. Nothing leaves this machine.`));
2468
+ let printedStart = false;
2090
2469
  if (answersFile) {
2091
2470
  let provided;
2092
2471
  try {
@@ -2104,15 +2483,19 @@ async function runDemo(asJson, answersFile) {
2104
2483
  const mode = answerMode({ demo: true, hasAnswersFile: false, json: asJson, isTTY: isInteractive() });
2105
2484
  if (mode === "prompt") await askQuestions(DEMO_QUESTIONS);
2106
2485
  else {
2107
- suggestedAnswers(DEMO_QUESTIONS);
2108
- if (!asJson) info("No terminal to ask in, so the demo uses its suggested answers.");
2486
+ const assumed = suggestedAnswers(DEMO_QUESTIONS);
2487
+ if (!asJson) {
2488
+ demoAnswerLines(assumed, DEMO_STATUS.effectiveDate).forEach((l) => console.log(l));
2489
+ printedStart = true;
2490
+ }
2109
2491
  }
2110
2492
  }
2111
- const spinner = asJson ? null : (0, import_ora6.default)("Asking carriers (demo)...").start();
2493
+ const spinner = asJson ? null : (0, import_ora6.default)("Asking carriers (demo)...");
2494
+ if (spinner && process.stderr.isTTY) spinner.start();
2112
2495
  await new Promise((resolve) => setTimeout(resolve, asJson ? 0 : 1200));
2113
2496
  spinner?.succeed("4 carriers answered (demo)");
2114
2497
  if (asJson) json({ demo: true, ...DEMO_STATUS });
2115
- else printQuoteTable(DEMO_STATUS, { demo: true });
2498
+ else printQuoteTable(DEMO_STATUS, { demo: true, showStartDate: !printedStart });
2116
2499
  }
2117
2500
  function addInstantQuoteCommands(quote) {
2118
2501
  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) => {
@@ -2184,7 +2567,7 @@ function addInstantQuoteCommands(quote) {
2184
2567
  process.exit(1);
2185
2568
  }
2186
2569
  submitSpinner.fail("Submit failed");
2187
- console.error(`Before trying again, check whether it went through: delegance quote status ${session.submissionId}`);
2570
+ console.error(`Before trying again, check whether it went through: ${cliInvocation()} quote status ${session.submissionId}`);
2188
2571
  failWith("API error", err);
2189
2572
  }
2190
2573
  if (submitted.status === "no_carriers") {
@@ -2200,14 +2583,14 @@ function addInstantQuoteCommands(quote) {
2200
2583
  }
2201
2584
  if (submitted.status === "acord_pending") {
2202
2585
  submitSpinner.succeed("Sent to a broker: these coverages need a person, not an instant quote.");
2203
- info(`Track it with: delegance quote status ${session.submissionId}`);
2586
+ info(`Track it with: ${cliInvocation()} quote status ${session.submissionId}`);
2204
2587
  return;
2205
2588
  }
2206
2589
  submitSpinner.succeed(`Filed with ${submitted.quotes.filter((q) => q.status === "submitted").length} carrier(s).`);
2207
2590
  printFloorDrops(submitted.partialFailures);
2208
2591
  if (submitted.replaceNotice && !options.json) info(submitted.replaceNotice);
2209
2592
  if (options.wait === false) {
2210
- info(`Check premiums with: delegance quote status ${session.submissionId} --wait`);
2593
+ info(`Check premiums with: ${cliInvocation()} quote status ${session.submissionId} --wait`);
2211
2594
  return;
2212
2595
  }
2213
2596
  await waitAndPrint(session.submissionId, Number(options.timeout) * 6e4 || 6e5, !!options.json);
@@ -2236,11 +2619,11 @@ function addInstantQuoteCommands(quote) {
2236
2619
  }
2237
2620
  if (submitted.status !== "submitted") {
2238
2621
  info("Sent to a broker for these coverages.");
2239
- info(`Check it: delegance quote status ${submissionId}`);
2622
+ info(`Check it: ${cliInvocation()} quote status ${submissionId}`);
2240
2623
  return;
2241
2624
  }
2242
2625
  if (options.wait === false) {
2243
- info(`Check premiums with: delegance quote status ${submissionId} --wait`);
2626
+ info(`Check premiums with: ${cliInvocation()} quote status ${submissionId} --wait`);
2244
2627
  return;
2245
2628
  }
2246
2629
  await waitAndPrint(submissionId, Number(options.timeout) * 6e4 || 6e5, !!options.json);
@@ -2251,7 +2634,7 @@ function addInstantQuoteCommands(quote) {
2251
2634
  guardLines.forEach((l) => options.json ? console.error(l) : info(l));
2252
2635
  process.exit(1);
2253
2636
  }
2254
- console.error(`Before trying again, check whether it went through: delegance quote status ${submissionId}`);
2637
+ console.error(`Before trying again, check whether it went through: ${cliInvocation()} quote status ${submissionId}`);
2255
2638
  failWith("Submit failed", err);
2256
2639
  }
2257
2640
  });
@@ -2287,7 +2670,7 @@ async function waitAndPrint(submissionId, timeoutMs, asJson) {
2287
2670
  spinner?.stop();
2288
2671
  if (asJson) json(status);
2289
2672
  else printQuoteTable(status);
2290
- if (!status.allCarriersResolved && !asJson) info(`Some carriers are still working. Check again: delegance quote status ${submissionId} --wait`);
2673
+ if (!status.allCarriersResolved && !asJson) info(`Some carriers are still working. Check again: ${cliInvocation()} quote status ${submissionId} --wait`);
2291
2674
  } catch (err) {
2292
2675
  spinner?.fail("Could not read the quote");
2293
2676
  failWith("API error", err);
@@ -2297,7 +2680,7 @@ async function waitAndPrint(submissionId, timeoutMs, asJson) {
2297
2680
  // src/commands/quote.ts
2298
2681
  var QUOTE_SUBMISSION_UNAVAILABLE = "Quote submission via API isn't available yet";
2299
2682
  function createQuoteCommand() {
2300
- const quote = new import_commander6.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2683
+ const quote = new import_commander7.Command("quote").alias("quotes").description("Request and manage insurance quotes");
2301
2684
  quote.command("carriers").description("List available carriers for quoting").option("--json", "Output as JSON").action(async (options) => {
2302
2685
  const client = getClient();
2303
2686
  const spinner = (0, import_ora7.default)("Fetching carriers...").start();
@@ -2344,7 +2727,7 @@ function createQuoteCommand() {
2344
2727
  process.exit(1);
2345
2728
  }
2346
2729
  if (options.interactive || carrierIds.length === 0 && !options.all) {
2347
- const { selectedCarriers } = await import_inquirer6.default.prompt([
2730
+ const { selectedCarriers } = await import_inquirer7.default.prompt([
2348
2731
  {
2349
2732
  type: "checkbox",
2350
2733
  name: "selectedCarriers",
@@ -2400,13 +2783,13 @@ function createQuoteCommand() {
2400
2783
  }
2401
2784
  console.log();
2402
2785
  info(`Queue IDs: ${result.queueIds.join(", ")}`);
2403
- info('Use "delegance quote list" to check status');
2786
+ info(`Use "${cliInvocation()} quote list" to check status`);
2404
2787
  }
2405
2788
  } catch (err) {
2406
2789
  spinner.fail("Failed to submit quote request");
2407
- if (err instanceof import_sdk5.NotImplementedError) {
2790
+ if (err instanceof import_sdk6.NotImplementedError) {
2408
2791
  error(QUOTE_SUBMISSION_UNAVAILABLE);
2409
- info("For an instant quote from the terminal: delegance quote start --coverage gl");
2792
+ info(`For an instant quote from the terminal: ${cliInvocation()} quote start --coverage gl`);
2410
2793
  info(`Or start a quote at ${PORTAL_URL}`);
2411
2794
  process.exit(1);
2412
2795
  }
@@ -2537,11 +2920,11 @@ function formatQuoteStatus(status) {
2537
2920
  }
2538
2921
 
2539
2922
  // src/commands/policy.ts
2540
- var import_commander7 = require("commander");
2541
- var import_inquirer7 = __toESM(require("inquirer"));
2923
+ var import_commander8 = require("commander");
2924
+ var import_inquirer8 = __toESM(require("inquirer"));
2542
2925
  var import_ora8 = __toESM(require("ora"));
2543
2926
  function createPolicyCommand() {
2544
- const policy = new import_commander7.Command("policy").alias("policies").description("Manage insurance policies");
2927
+ const policy = new import_commander8.Command("policy").alias("policies").description("Manage insurance policies");
2545
2928
  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) => {
2546
2929
  const client = getClient();
2547
2930
  const spinner = (0, import_ora8.default)("Fetching policies...").start();
@@ -2564,7 +2947,7 @@ function createPolicyCommand() {
2564
2947
  ["Carrier", "Type", "Policy #", "Expiry", "Status", "Premium"],
2565
2948
  policies.map((p) => [
2566
2949
  p.carrier || "Unknown",
2567
- p.policyType || p.name || "-",
2950
+ (p.policyType ? coverageName(p.policyType) : p.name) || "-",
2568
2951
  p.policyNumber || "-",
2569
2952
  p.expiryDate ? formatDate(p.expiryDate) : "-",
2570
2953
  formatPolicyStatus(p.isActive, p.daysUntilExpiry),
@@ -2598,21 +2981,21 @@ function createPolicyCommand() {
2598
2981
  if (urgent.length > 0) {
2599
2982
  warn(`\u26A0\uFE0F Expiring within 7 days (${urgent.length}):`);
2600
2983
  for (const p of urgent) {
2601
- console.log(` - ${p.carrier} ${p.policyType || p.name} - expires ${formatDate(p.expiryDate)}`);
2984
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - expires ${formatDate(p.expiryDate)}`);
2602
2985
  }
2603
2986
  console.log();
2604
2987
  }
2605
2988
  if (soon.length > 0) {
2606
2989
  info(`\u{1F4C5} Expiring within 30 days (${soon.length}):`);
2607
2990
  for (const p of soon) {
2608
- console.log(` - ${p.carrier} ${p.policyType || p.name} - expires ${formatDate(p.expiryDate)}`);
2991
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - expires ${formatDate(p.expiryDate)}`);
2609
2992
  }
2610
2993
  console.log();
2611
2994
  }
2612
2995
  if (later.length > 0) {
2613
2996
  console.log(`\u{1F4C6} Expiring later (${later.length}):`);
2614
2997
  for (const p of later) {
2615
- console.log(` - ${p.carrier} ${p.policyType || p.name} - ${p.daysUntilExpiry} days`);
2998
+ console.log(` - ${p.carrier} ${p.policyType ? coverageName(p.policyType) : p.name} - ${p.daysUntilExpiry} days`);
2616
2999
  }
2617
3000
  }
2618
3001
  }
@@ -2636,11 +3019,11 @@ function createPolicyCommand() {
2636
3019
  } else {
2637
3020
  const { policy: p, coverages } = found;
2638
3021
  console.log();
2639
- header(`${p.carrier} - ${p.policyType || p.name}`);
3022
+ header(`${p.carrier} - ${p.policyType ? coverageName(p.policyType) : p.name}`);
2640
3023
  console.log();
2641
3024
  console.log(` Policy #: ${p.policyNumber || "N/A"}`);
2642
3025
  console.log(` Carrier: ${p.carrier}`);
2643
- console.log(` Type: ${p.policyType || "N/A"}`);
3026
+ console.log(` Type: ${p.policyType ? coverageName(p.policyType) : "N/A"}`);
2644
3027
  console.log(` Effective: ${p.effectiveDate ? formatDate(p.effectiveDate) : "N/A"}`);
2645
3028
  console.log(` Expiry: ${p.expiryDate ? formatDate(p.expiryDate) : "N/A"}`);
2646
3029
  console.log(` Status: ${formatPolicyStatus(p.isActive, p.daysUntilExpiry)}`);
@@ -2691,14 +3074,14 @@ function createPolicyCommand() {
2691
3074
  return;
2692
3075
  }
2693
3076
  if (docs.length === 0) {
2694
- info("No source documents are linked to this policy yet. Upload one with: delegance document upload <file>");
3077
+ info(`No source documents are linked to this policy yet. Upload one with: ${cliInvocation()} document upload <file>`);
2695
3078
  return;
2696
3079
  }
2697
3080
  table(
2698
3081
  ["Document", "File", "Type", "Status", "Added"],
2699
3082
  docs.map((d) => [d.id, d.fileName ?? "-", d.documentType ?? "-", d.status, d.createdAt ? formatDate(d.createdAt) : "-"])
2700
3083
  );
2701
- info("Download one with: delegance document status <documentId>");
3084
+ info(`Download one with: ${cliInvocation()} document status <documentId>`);
2702
3085
  } catch (err) {
2703
3086
  failWith("API error", err);
2704
3087
  }
@@ -2731,9 +3114,9 @@ function createPolicyCommand() {
2731
3114
  await signWithStepUp(client, out.request.id, sig, void 0, void 0);
2732
3115
  } else {
2733
3116
  info(`Sign here: ${out.signatureUrl}`);
2734
- info(`Or sign from here: delegance policy sign ${out.request.id} --signer-name "..." --signer-title "..." --attest`);
3117
+ info(`Or sign from here: ${cliInvocation()} policy sign ${out.request.id} --signer-name "..." --signer-title "..." --attest`);
2735
3118
  }
2736
- info(`Check progress with "delegance policy cancellation ${out.request.id}"`);
3119
+ info(`Check progress with "${cliInvocation()} policy cancellation ${out.request.id}"`);
2737
3120
  } catch (err) {
2738
3121
  spinner.fail("Could not request the cancellation");
2739
3122
  failWith("API error", err);
@@ -2790,10 +3173,10 @@ async function signWithStepUp(client, requestId, sig, stepUpId, presetCode) {
2790
3173
  let code = presetCode;
2791
3174
  if (!code) {
2792
3175
  if (!process.stdin.isTTY) {
2793
- 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>`);
3176
+ 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>`);
2794
3177
  return;
2795
3178
  }
2796
- const answer = await import_inquirer7.default.prompt([{
3179
+ const answer = await import_inquirer8.default.prompt([{
2797
3180
  type: "input",
2798
3181
  name: "code",
2799
3182
  message: "Code from your email:",
@@ -2820,11 +3203,11 @@ function formatPolicyStatus(isActive, daysUntilExpiry) {
2820
3203
  }
2821
3204
 
2822
3205
  // src/commands/coi.ts
2823
- var import_commander8 = require("commander");
3206
+ var import_commander9 = require("commander");
2824
3207
  var import_ora9 = __toESM(require("ora"));
2825
- var import_inquirer8 = __toESM(require("inquirer"));
3208
+ var import_inquirer9 = __toESM(require("inquirer"));
2826
3209
  function createCOICommand() {
2827
- const coi = new import_commander8.Command("coi").description("Generate and manage Certificates of Insurance");
3210
+ const coi = new import_commander9.Command("coi").description("Generate and manage Certificates of Insurance");
2828
3211
  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) => {
2829
3212
  const client = getClient();
2830
3213
  let policyIds = options.policies || [];
@@ -2840,16 +3223,16 @@ function createCOICommand() {
2840
3223
  policiesSpinner.stop();
2841
3224
  if (policies.length === 0) {
2842
3225
  error("No active policies found");
2843
- info('Upload policy documents first with "delegance doc upload"');
3226
+ info(`Upload policy documents first with "${cliInvocation()} doc upload"`);
2844
3227
  process.exit(1);
2845
3228
  }
2846
- const answers = await import_inquirer8.default.prompt([
3229
+ const answers = await import_inquirer9.default.prompt([
2847
3230
  {
2848
3231
  type: "checkbox",
2849
3232
  name: "selectedPolicies",
2850
3233
  message: "Select policies to include:",
2851
3234
  choices: policies.map((p) => ({
2852
- name: `${p.carrier} - ${p.policyType || p.name} (${p.policyNumber || "No #"})`,
3235
+ name: `${p.carrier} - ${p.policyType ? coverageName(p.policyType) : p.name} (${p.policyNumber || "No #"})`,
2853
3236
  value: p.id,
2854
3237
  checked: policyIds.includes(p.id)
2855
3238
  })),
@@ -2936,7 +3319,7 @@ function createCOICommand() {
2936
3319
  console.log();
2937
3320
  console.log("Policies included:");
2938
3321
  for (const p of result.policiesIncluded) {
2939
- console.log(` - ${p.carrier} (${p.policyType})`);
3322
+ console.log(` - ${p.carrier} (${coverageName(p.policyType)})`);
2940
3323
  }
2941
3324
  }
2942
3325
  } catch (err) {
@@ -2952,7 +3335,7 @@ function createCOICommand() {
2952
3335
  spinner.succeed(`Found ${count} COIs`);
2953
3336
  if (cois.length === 0) {
2954
3337
  info("No COIs generated yet");
2955
- info('Generate one with "delegance coi generate --interactive"');
3338
+ info(`Generate one with "${cliInvocation()} coi generate --interactive"`);
2956
3339
  return;
2957
3340
  }
2958
3341
  if (options.json) {
@@ -2979,12 +3362,12 @@ function createCOICommand() {
2979
3362
  }
2980
3363
 
2981
3364
  // src/commands/sov.ts
2982
- var import_commander9 = require("commander");
3365
+ var import_commander10 = require("commander");
2983
3366
  var import_ora10 = __toESM(require("ora"));
2984
3367
  var import_fs = __toESM(require("fs"));
2985
3368
  var import_path = __toESM(require("path"));
2986
3369
  function createSOVCommand() {
2987
- const sov = new import_commander9.Command("sov").description("Manage Schedules of Values (property schedules)");
3370
+ const sov = new import_commander10.Command("sov").description("Manage Schedules of Values (property schedules)");
2988
3371
  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) => {
2989
3372
  const client = getClient();
2990
3373
  const filePath = import_path.default.resolve(file);
@@ -3029,7 +3412,7 @@ function createSOVCommand() {
3029
3412
  info(`SOV ID: ${result.sovId}`);
3030
3413
  info(`Status: ${result.status}`);
3031
3414
  if (!options.wait) {
3032
- info('Use "delegance sov status <id>" to check parsing progress');
3415
+ info(`Use "${cliInvocation()} sov status <id>" to check parsing progress`);
3033
3416
  }
3034
3417
  }
3035
3418
  } catch (err) {
@@ -3048,7 +3431,7 @@ function createSOVCommand() {
3048
3431
  spinner.succeed(`Found ${count} SOVs`);
3049
3432
  if (sovs.length === 0) {
3050
3433
  info("No SOVs found");
3051
- info('Upload one with "delegance sov upload schedule.xlsx"');
3434
+ info(`Upload one with "${cliInvocation()} sov upload schedule.xlsx"`);
3052
3435
  return;
3053
3436
  }
3054
3437
  if (options.json) {
@@ -3142,7 +3525,7 @@ function showSOVDetails(s) {
3142
3525
  }
3143
3526
 
3144
3527
  // src/commands/appetite.ts
3145
- var import_commander10 = require("commander");
3528
+ var import_commander11 = require("commander");
3146
3529
  var import_ora11 = __toESM(require("ora"));
3147
3530
  function num(value) {
3148
3531
  if (value === void 0) return void 0;
@@ -3190,7 +3573,7 @@ function printResult(result) {
3190
3573
  for (const w of result.warnings) warn(w);
3191
3574
  }
3192
3575
  function createAppetiteCommand() {
3193
- const appetite = new import_commander10.Command("appetite").description("Check which carriers will write a risk");
3576
+ const appetite = new import_commander11.Command("appetite").description("Check which carriers will write a risk");
3194
3577
  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) => {
3195
3578
  const input = buildMatchInput(options);
3196
3579
  const timeoutMs = positiveInt(options.timeout, "--timeout");
@@ -3212,7 +3595,7 @@ function createAppetiteCommand() {
3212
3595
  if (!options.wait) {
3213
3596
  spinner.succeed(`Match queued: ${start.jobId}`);
3214
3597
  if (options.json) json(start);
3215
- else info(`Check it with "delegance appetite status ${start.jobId}"`);
3598
+ else info(`Check it with "${cliInvocation()} appetite status ${start.jobId}"`);
3216
3599
  return;
3217
3600
  }
3218
3601
  spinner.text = `Matching appetite (about ${start.estimatedSeconds}s)...`;
@@ -3251,7 +3634,7 @@ function createAppetiteCommand() {
3251
3634
  }
3252
3635
 
3253
3636
  // src/commands/lead.ts
3254
- var import_commander11 = require("commander");
3637
+ var import_commander12 = require("commander");
3255
3638
  var import_ora12 = __toESM(require("ora"));
3256
3639
  function buildLeadInput(options) {
3257
3640
  const input = {
@@ -3282,7 +3665,7 @@ function buildLeadInput(options) {
3282
3665
  return input;
3283
3666
  }
3284
3667
  function createLeadCommand() {
3285
- const lead = new import_commander11.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3668
+ const lead = new import_commander12.Command("lead").alias("leads").description("Send prospect businesses to Delegance");
3286
3669
  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) => {
3287
3670
  const input = buildLeadInput(options);
3288
3671
  if (input.address && (!input.address.street || !input.address.city || !input.address.state || !input.address.zip)) {
@@ -3305,11 +3688,11 @@ function createLeadCommand() {
3305
3688
  }
3306
3689
 
3307
3690
  // src/commands/knowledge.ts
3308
- var import_commander12 = require("commander");
3691
+ var import_commander13 = require("commander");
3309
3692
  var import_ora13 = __toESM(require("ora"));
3310
3693
  var SEARCH_TYPES = ["notecard", "document_chunk"];
3311
3694
  function createKnowledgeCommand() {
3312
- const knowledge = new import_commander12.Command("knowledge").alias("kb").description("Search notecards and document facts");
3695
+ const knowledge = new import_commander13.Command("knowledge").alias("kb").description("Search notecards and document facts");
3313
3696
  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) => {
3314
3697
  const client = getClient();
3315
3698
  const query = queryParts.join(" ");
@@ -3358,7 +3741,7 @@ function createKnowledgeCommand() {
3358
3741
  );
3359
3742
  }
3360
3743
  if (pagination.hasMore && pagination.nextCursor) {
3361
- info(`More: delegance knowledge notecards --cursor ${pagination.nextCursor}`);
3744
+ info(`More: ${cliInvocation()} knowledge notecards --cursor ${pagination.nextCursor}`);
3362
3745
  }
3363
3746
  } catch (err) {
3364
3747
  spinner.fail("Failed to list notecards");
@@ -3411,7 +3794,7 @@ function createKnowledgeCommand() {
3411
3794
  }
3412
3795
 
3413
3796
  // src/commands/onboarding.ts
3414
- var import_commander13 = require("commander");
3797
+ var import_commander14 = require("commander");
3415
3798
  var import_ora14 = __toESM(require("ora"));
3416
3799
  var ONBOARDING_STATES = [
3417
3800
  "created",
@@ -3421,7 +3804,7 @@ var ONBOARDING_STATES = [
3421
3804
  "ready"
3422
3805
  ];
3423
3806
  function createOnboardingCommand() {
3424
- const onboarding = new import_commander13.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3807
+ const onboarding = new import_commander14.Command("onboarding").alias("onboard").description("Check account setup and onboarding state");
3425
3808
  onboarding.command("status").description("Show the setup checklist and the next step").option("--json", "Output as JSON").action(async (options) => {
3426
3809
  const client = getClient();
3427
3810
  const spinner = (0, import_ora14.default)("Fetching onboarding status...").start();
@@ -3482,7 +3865,7 @@ function createOnboardingCommand() {
3482
3865
  const result = await client.onboarding.requestVerification();
3483
3866
  spinner.succeed(`Verification sent to ${result.sentTo}`);
3484
3867
  if (options.json) json(result);
3485
- else info('Open the link in that email, then check progress with "delegance onboarding state"');
3868
+ else info(`Open the link in that email, then check progress with "${cliInvocation()} onboarding state"`);
3486
3869
  } catch (err) {
3487
3870
  spinner.fail("Failed to request verification");
3488
3871
  failWith("API error", err);
@@ -3512,7 +3895,7 @@ function createOnboardingCommand() {
3512
3895
  }
3513
3896
 
3514
3897
  // src/commands/usage.ts
3515
- var import_commander14 = require("commander");
3898
+ var import_commander15 = require("commander");
3516
3899
  var import_ora15 = __toESM(require("ora"));
3517
3900
  function isoDay(daysAgo, now = /* @__PURE__ */ new Date()) {
3518
3901
  const d = new Date(now.getTime() - daysAgo * 24 * 60 * 60 * 1e3);
@@ -3522,7 +3905,7 @@ function cents(n) {
3522
3905
  return `$${(n / 100).toFixed(2)}`;
3523
3906
  }
3524
3907
  function createUsageCommand() {
3525
- const usage = new import_commander14.Command("usage").description("Show API usage, billing, and rate limits");
3908
+ const usage = new import_commander15.Command("usage").description("Show API usage, billing, and rate limits");
3526
3909
  usage.command("summary").description("Usage for the current billing period").option("--json", "Output as JSON").action(async (options) => {
3527
3910
  const client = getClient();
3528
3911
  const spinner = (0, import_ora15.default)("Fetching usage summary...").start();
@@ -3602,21 +3985,30 @@ function createUsageCommand() {
3602
3985
  }
3603
3986
 
3604
3987
  // src/commands/keys.ts
3605
- var import_commander15 = require("commander");
3988
+ var import_commander16 = require("commander");
3606
3989
  var import_ora16 = __toESM(require("ora"));
3607
3990
  var import_crypto3 = require("crypto");
3608
- var import_sdk6 = require("@delegance/sdk");
3991
+ var import_sdk7 = require("@delegance/sdk");
3609
3992
  var KEYS_PORTAL_URL = `${PORTAL_URL}/portal/settings/api-keys`;
3993
+ function parseExpiresInDays(raw) {
3994
+ if (raw === void 0 || raw === "") return void 0;
3995
+ if (raw.trim().toLowerCase() === "never") return "never";
3996
+ return parseInt(raw, 10);
3997
+ }
3610
3998
  function parseScopes(raw) {
3611
3999
  const parts = (Array.isArray(raw) ? raw : [raw ?? "read,write"]).flatMap((p) => p.split(/[\s,]+/)).map((p) => p.trim()).filter(Boolean);
3612
- const unknown = parts.filter((p) => !import_sdk6.API_KEY_SCOPES.includes(p));
4000
+ const unknown = parts.filter((p) => !import_sdk7.API_KEY_SCOPES.includes(p));
3613
4001
  if (unknown.length > 0) {
3614
- throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk6.API_KEY_SCOPES.join(", ")}`);
4002
+ throw new Error(`Unknown scope(s): ${unknown.join(", ")}. Allowed: ${import_sdk7.API_KEY_SCOPES.join(", ")}`);
3615
4003
  }
3616
4004
  return Array.from(new Set(parts));
3617
4005
  }
3618
- function replacementExpiryDays(expiresAt, now = /* @__PURE__ */ new Date()) {
3619
- if (!expiresAt) return void 0;
4006
+ var EXPIRING_SCOPES = /* @__PURE__ */ new Set(["write", "admin", "claims:write"]);
4007
+ function isReadOnlyScopeSet(scopes) {
4008
+ return !scopes.some((s) => EXPIRING_SCOPES.has(s));
4009
+ }
4010
+ function replacementExpiryDays(expiresAt, now = /* @__PURE__ */ new Date(), scopes = []) {
4011
+ if (!expiresAt) return isReadOnlyScopeSet(scopes) ? "never" : void 0;
3620
4012
  const ms = new Date(expiresAt).getTime() - now.getTime();
3621
4013
  if (!Number.isFinite(ms)) throw new Error(`Cannot read the old key's expiry "${expiresAt}"; not rotating`);
3622
4014
  const days = Math.ceil(ms / (24 * 60 * 60 * 1e3));
@@ -3636,7 +4028,7 @@ function printCreatedKey(created) {
3636
4028
  console.log(` ${created.key}`);
3637
4029
  }
3638
4030
  function createKeysCommand() {
3639
- const keys = new import_commander15.Command("keys").alias("api-keys").description("Manage API keys");
4031
+ const keys = new import_commander16.Command("keys").alias("api-keys").description("Manage API keys");
3640
4032
  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) => {
3641
4033
  const client = getClient();
3642
4034
  const spinner = (0, import_ora16.default)("Fetching API keys...").start();
@@ -3665,14 +4057,14 @@ function createKeysCommand() {
3665
4057
  ])
3666
4058
  );
3667
4059
  if (pagination?.hasMore && pagination.nextCursor) {
3668
- info(`More keys: delegance keys list --cursor ${pagination.nextCursor}`);
4060
+ info(`More keys: ${cliInvocation()} keys list --cursor ${pagination.nextCursor}`);
3669
4061
  }
3670
4062
  } catch (err) {
3671
4063
  spinner.fail("Failed to list API keys");
3672
4064
  failWith("API error", err);
3673
4065
  }
3674
4066
  });
3675
- 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) => {
4067
+ 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) => {
3676
4068
  let scopes;
3677
4069
  try {
3678
4070
  scopes = parseScopes(options.scopes);
@@ -3687,7 +4079,7 @@ function createKeysCommand() {
3687
4079
  {
3688
4080
  name,
3689
4081
  scopes,
3690
- expiresInDays: options.expiresInDays ? parseInt(options.expiresInDays) : void 0
4082
+ expiresInDays: parseExpiresInDays(options.expiresInDays)
3691
4083
  },
3692
4084
  { idempotencyKey: (0, import_crypto3.randomUUID)() }
3693
4085
  );
@@ -3722,7 +4114,7 @@ function createKeysCommand() {
3722
4114
  {
3723
4115
  name: `${current2.name} (rotated)`,
3724
4116
  scopes: current2.scopes,
3725
- expiresInDays: replacementExpiryDays(current2.expiresAt)
4117
+ expiresInDays: replacementExpiryDays(current2.expiresAt, /* @__PURE__ */ new Date(), current2.scopes)
3726
4118
  },
3727
4119
  { idempotencyKey: (0, import_crypto3.randomUUID)() }
3728
4120
  );
@@ -3733,6 +4125,9 @@ function createKeysCommand() {
3733
4125
  }
3734
4126
  printCreatedKey(created);
3735
4127
  console.log();
4128
+ if (!current2.expiresAt && !isReadOnlyScopeSet(current2.scopes)) {
4129
+ warn("The old key never expired. Keys that can write must expire now, so the new key lasts 90 days.");
4130
+ }
3736
4131
  warn(`The old key ${current2.prefix} is still active.`);
3737
4132
  info(`Switch your integrations to the new key, then revoke the old one at ${KEYS_PORTAL_URL}`);
3738
4133
  } catch (err) {
@@ -3748,7 +4143,7 @@ function createKeysCommand() {
3748
4143
  spinner.succeed("API key revoked");
3749
4144
  } catch (err) {
3750
4145
  spinner.fail("Failed to revoke API key");
3751
- if (err instanceof import_sdk6.AuthenticationError) {
4146
+ if (err instanceof import_sdk7.AuthenticationError) {
3752
4147
  error("Revoking a key needs a signed-in portal session today");
3753
4148
  info(`Revoke it at ${KEYS_PORTAL_URL}`);
3754
4149
  process.exit(1);
@@ -3760,10 +4155,10 @@ function createKeysCommand() {
3760
4155
  }
3761
4156
 
3762
4157
  // src/commands/config.ts
3763
- var import_commander16 = require("commander");
3764
- var import_inquirer9 = __toESM(require("inquirer"));
4158
+ var import_commander17 = require("commander");
4159
+ var import_inquirer10 = __toESM(require("inquirer"));
3765
4160
  function createConfigCommand() {
3766
- const config2 = new import_commander16.Command("config").description("Manage CLI configuration");
4161
+ const config2 = new import_commander17.Command("config").description("Manage CLI configuration");
3767
4162
  config2.command("show").alias("list").description("Show current configuration").option("--json", "Output as JSON").action((options) => {
3768
4163
  const currentConfig = getConfig();
3769
4164
  const apiKey = getApiKey();
@@ -3807,7 +4202,7 @@ function createConfigCommand() {
3807
4202
  });
3808
4203
  config2.command("reset").description("Reset all configuration to defaults").option("-f, --force", "Skip confirmation").action(async (options) => {
3809
4204
  if (!options.force) {
3810
- const { confirm } = await import_inquirer9.default.prompt([
4205
+ const { confirm } = await import_inquirer10.default.prompt([
3811
4206
  {
3812
4207
  type: "confirm",
3813
4208
  name: "confirm",
@@ -3824,7 +4219,7 @@ function createConfigCommand() {
3824
4219
  currentConfig.clear();
3825
4220
  clearCredentials();
3826
4221
  success("Configuration reset to defaults");
3827
- info('You will need to run "delegance auth login" again');
4222
+ info(`You will need to run "${cliInvocation()} auth login" again`);
3828
4223
  });
3829
4224
  config2.command("env").description("Show environment information").action(() => {
3830
4225
  header("Environment");
@@ -3850,7 +4245,7 @@ function createConfigCommand() {
3850
4245
  info("No profiles configured");
3851
4246
  info("Profiles allow you to switch between different accounts/environments");
3852
4247
  console.log();
3853
- info("Example: delegance config set-profile production --url https://portal.delegancebrokerage.com");
4248
+ info(`Example: ${cliInvocation()} config set-profile production --url https://portal.delegancebrokerage.com`);
3854
4249
  } else {
3855
4250
  for (const [name, profile] of Object.entries(profiles)) {
3856
4251
  const isActive = name === activeProfile;
@@ -3866,7 +4261,7 @@ function createConfigCommand() {
3866
4261
  const profiles = currentConfig.get("profiles") || {};
3867
4262
  if (!profiles[name] && name !== "default") {
3868
4263
  error(`Profile "${name}" not found`);
3869
- info("Create it with: delegance config set-profile <name> --url <base-url>");
4264
+ info(`Create it with: ${cliInvocation()} config set-profile <name> --url <base-url>`);
3870
4265
  process.exit(1);
3871
4266
  }
3872
4267
  currentConfig.set("activeProfile", name);
@@ -3892,12 +4287,12 @@ function createConfigCommand() {
3892
4287
  }
3893
4288
 
3894
4289
  // src/commands/feedback.ts
3895
- var import_commander17 = require("commander");
3896
- var import_inquirer10 = __toESM(require("inquirer"));
3897
- var import_sdk7 = require("@delegance/sdk");
4290
+ var import_commander18 = require("commander");
4291
+ var import_inquirer11 = __toESM(require("inquirer"));
4292
+ var import_sdk8 = require("@delegance/sdk");
3898
4293
  var TYPES = ["bug", "idea", "question"];
3899
4294
  var MESSAGE_MAX = 500;
3900
- var USAGE = 'delegance feedback "what happened" [--type bug|idea|question] [--include-last]';
4295
+ var USAGE = `${cliInvocation()} feedback "what happened" [--type bug|idea|question] [--include-last]`;
3901
4296
  function feedbackInputMode(o) {
3902
4297
  if (o.message && o.message.trim()) return "given";
3903
4298
  return o.isTTY ? "prompt" : "usage_error";
@@ -3911,7 +4306,7 @@ function buildFeedbackContext(last) {
3911
4306
  ctx.at = last.at;
3912
4307
  }
3913
4308
  ctx.cliVersion = CLI_VERSION;
3914
- ctx.sdkVersion = import_sdk7.SDK_VERSION;
4309
+ ctx.sdkVersion = import_sdk8.SDK_VERSION;
3915
4310
  return ctx;
3916
4311
  }
3917
4312
  function usageError(message) {
@@ -3920,14 +4315,14 @@ function usageError(message) {
3920
4315
  process.exit(2);
3921
4316
  }
3922
4317
  function createFeedbackCommand() {
3923
- 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) => {
4318
+ 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) => {
3924
4319
  const type = String(options.type ?? "bug").toLowerCase();
3925
4320
  if (!TYPES.includes(type)) usageError(`--type must be bug, idea, or question, got "${options.type}"`);
3926
4321
  let message = (words ?? []).join(" ").trim();
3927
4322
  const mode = feedbackInputMode({ message, isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY) });
3928
4323
  if (mode === "usage_error") usageError(`Say what happened: ${USAGE}`);
3929
4324
  if (mode === "prompt") {
3930
- const answer = await import_inquirer10.default.prompt([
4325
+ const answer = await import_inquirer11.default.prompt([
3931
4326
  { type: "input", name: "message", message: type === "bug" ? "What went wrong?" : "What would you like to tell us?" }
3932
4327
  ]);
3933
4328
  message = String(answer.message ?? "").trim();
@@ -3948,12 +4343,42 @@ function createFeedbackCommand() {
3948
4343
  });
3949
4344
  }
3950
4345
 
4346
+ // src/utils/checkbox-prompt.ts
4347
+ var import_inquirer12 = __toESM(require("inquirer"));
4348
+ var import_chalk3 = __toESM(require("chalk"));
4349
+ var CHECKBOX_HINT = "(space to select, Enter to continue)";
4350
+ var registered = false;
4351
+ function minimalCheckboxPrompt(Base) {
4352
+ return class MinimalCheckboxPrompt extends Base {
4353
+ constructor(...args) {
4354
+ super(...args);
4355
+ this.dontShowHints = true;
4356
+ }
4357
+ getQuestion() {
4358
+ const question = super.getQuestion();
4359
+ return this.status === "answered" ? question : `${question}${import_chalk3.default.dim(CHECKBOX_HINT)} `;
4360
+ }
4361
+ onAllKey() {
4362
+ }
4363
+ onInverseKey() {
4364
+ }
4365
+ };
4366
+ }
4367
+ function registerMinimalCheckbox() {
4368
+ if (registered) return;
4369
+ const prompts = import_inquirer12.default.prompt.prompts;
4370
+ const Base = prompts?.checkbox;
4371
+ if (!Base) return;
4372
+ import_inquirer12.default.registerPrompt("checkbox", minimalCheckboxPrompt(Base));
4373
+ registered = true;
4374
+ }
4375
+
3951
4376
  // src/commands/commerce.ts
3952
- var import_commander18 = require("commander");
4377
+ var import_commander19 = require("commander");
3953
4378
  var fs7 = __toESM(require("fs"));
3954
- var import_inquirer11 = __toESM(require("inquirer"));
4379
+ var import_inquirer13 = __toESM(require("inquirer"));
3955
4380
  var import_ora17 = __toESM(require("ora"));
3956
- var import_sdk8 = require("@delegance/sdk");
4381
+ var import_sdk9 = require("@delegance/sdk");
3957
4382
  function formatCents(cents2, currency = "usd") {
3958
4383
  return currency.toLowerCase() === "usd" ? formatCurrency(cents2 / 100) : `${(cents2 / 100).toFixed(2)} ${currency.toUpperCase()}`;
3959
4384
  }
@@ -3979,9 +4404,58 @@ function describeBindResult(r) {
3979
4404
  lines.push(r.next);
3980
4405
  return lines;
3981
4406
  }
4407
+ var BROKER_REVIEW_EMAIL = "support@delegancebrokerage.com";
4408
+ function selfDirectedAckLines(submissionId, offerId) {
4409
+ return [
4410
+ "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).",
4411
+ `Want a licensed broker to review it first? Run: ${cliInvocation()} bind ${submissionId} ${offerId} --broker-review`
4412
+ ];
4413
+ }
4414
+ function brokerReviewMailto(submissionId, offerId) {
4415
+ const subject = encodeURIComponent(`Broker review before bind: submission ${submissionId}, offer ${offerId}`);
4416
+ return `mailto:${BROKER_REVIEW_EMAIL}?subject=${subject}`;
4417
+ }
4418
+ function brokerReviewLines(submissionId, offerId) {
4419
+ return [
4420
+ "Nothing was bound, and no review has been requested yet.",
4421
+ `To request a review by a licensed Delegance broker, send an email to ${BROKER_REVIEW_EMAIL}`,
4422
+ `naming submission ${submissionId} and offer ${offerId}: ${brokerReviewMailto(submissionId, offerId)}`,
4423
+ "Wait for the broker to reply before you bind. A reviewed placement is not self-directed."
4424
+ ];
4425
+ }
4426
+ function brokerReviewResult(submissionId, offerId) {
4427
+ return {
4428
+ bound: false,
4429
+ reviewRequested: false,
4430
+ submissionId,
4431
+ offerId,
4432
+ brokerReview: { email: BROKER_REVIEW_EMAIL, mailto: brokerReviewMailto(submissionId, offerId) },
4433
+ message: brokerReviewLines(submissionId, offerId)
4434
+ };
4435
+ }
4436
+ function exactDollars(cents2) {
4437
+ return `$${(cents2 / 100).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
4438
+ }
4439
+ function describeFinancing(f) {
4440
+ if (!f || !f.available) return [];
4441
+ const lines = [];
4442
+ if (f.checkoutUrl) {
4443
+ lines.push(`Pay over time with ${f.lender}: ${f.checkoutUrl}`);
4444
+ } else {
4445
+ lines.push(`Financing with ${f.lender} opens once your broker confirms the final premium.`);
4446
+ }
4447
+ const t = f.terms;
4448
+ if (t && t.aprBps !== null && t.downPaymentCents !== null && t.installmentCents !== null && t.numberOfInstallments !== null) {
4449
+ lines.push(
4450
+ `Lender terms: ${(t.aprBps / 100).toFixed(2)}% APR, ${exactDollars(t.downPaymentCents)} down, ${t.numberOfInstallments} payments of ${exactDollars(t.installmentCents)}.`
4451
+ );
4452
+ }
4453
+ lines.push(f.disclosure);
4454
+ return lines;
4455
+ }
3982
4456
  async function askCode() {
3983
4457
  if (!process.stdin.isTTY) return null;
3984
- const answer = await import_inquirer11.default.prompt([{
4458
+ const answer = await import_inquirer13.default.prompt([{
3985
4459
  type: "input",
3986
4460
  name: "code",
3987
4461
  message: "Code from your email:",
@@ -3990,11 +4464,19 @@ async function askCode() {
3990
4464
  return String(answer.code).trim();
3991
4465
  }
3992
4466
  function createBindCommand() {
3993
- 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) => {
4467
+ 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) => {
4468
+ if (options.brokerReview) {
4469
+ if (options.json) json(brokerReviewResult(submissionId, offerId));
4470
+ else brokerReviewLines(submissionId, offerId).forEach((l) => info(l));
4471
+ return;
4472
+ }
3994
4473
  const client = getClient();
4474
+ const ack = selfDirectedAckLines(submissionId, offerId);
4475
+ if (options.json) ack.forEach((l) => console.error(l));
4476
+ else ack.forEach((l) => info(l));
3995
4477
  let attest = options.attest === true;
3996
4478
  if (!attest && process.stdin.isTTY && !options.json) {
3997
- const a = await import_inquirer11.default.prompt([{
4479
+ const a = await import_inquirer13.default.prompt([{
3998
4480
  type: "confirm",
3999
4481
  name: "ok",
4000
4482
  message: "Are the answers on this application accurate? Binding relies on them.",
@@ -4002,7 +4484,7 @@ function createBindCommand() {
4002
4484
  }]);
4003
4485
  attest = a.ok === true;
4004
4486
  if (!attest) {
4005
- warn('Not bound. Fix the answers with "delegance quote start", then bind again.');
4487
+ warn(`Not bound. Fix the answers with "${cliInvocation()} quote start", then bind again.`);
4006
4488
  return;
4007
4489
  }
4008
4490
  }
@@ -4018,7 +4500,7 @@ function createBindCommand() {
4018
4500
  info(`We emailed a 6-digit code to ${r.sentTo}. It expires in 10 minutes.`);
4019
4501
  const code = options.code ? String(options.code) : await askCode();
4020
4502
  if (!code) {
4021
- warn(`Finish with: delegance bind ${submissionId} ${offerId} --attest --step-up ${stepUpId} --code <code>`);
4503
+ warn(`Finish with: ${cliInvocation()} bind ${submissionId} ${offerId} --attest --step-up ${stepUpId} --code <code>`);
4022
4504
  return;
4023
4505
  }
4024
4506
  r = await client.instantQuotes.bindWithStepUp(submissionId, offerId, { ...attest ? { attest: true } : {}, stepUpId, code });
@@ -4028,16 +4510,17 @@ function createBindCommand() {
4028
4510
  }
4029
4511
  }
4030
4512
  if (options.json) {
4031
- json(r);
4513
+ json({ ...r, selfDirected: true, disclosure: ack[0] });
4032
4514
  return;
4033
4515
  }
4034
4516
  if (r.existing) warn(`A bind for this coverage is already open (${r.carrierName}). Showing it.`);
4035
- else if (r.tier !== "A") success(`Bind requested: ${r.carrierName} ${r.coverage}${r.premium === null ? "" : ` at ${formatCurrency(r.premium)}/yr`}`);
4517
+ else if (r.tier !== "A") success(`Bind requested: ${r.carrierName} ${coverageName(r.coverage)}${r.premium === null ? "" : ` at ${formatCurrency(r.premium)}/yr`}`);
4036
4518
  keyValue({ "Bind request": r.bindRequestId, Status: r.status });
4037
4519
  describeBindResult(r).forEach((l) => info(l));
4520
+ describeFinancing(r.financing).forEach((l) => info(l));
4038
4521
  } catch (err) {
4039
4522
  spinner?.stop();
4040
- if (err instanceof import_sdk8.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4523
+ if (err instanceof import_sdk9.DeleganceError && [400, 403, 409].includes(err.statusCode ?? 0)) {
4041
4524
  error(err.message);
4042
4525
  process.exit(1);
4043
4526
  }
@@ -4058,7 +4541,7 @@ function summarizeBilling(payments) {
4058
4541
  return { openCents, paidCents, openCount };
4059
4542
  }
4060
4543
  function createBillingCommand() {
4061
- 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) => {
4544
+ 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) => {
4062
4545
  try {
4063
4546
  const payments = await getClient().payments.list();
4064
4547
  const sum = summarizeBilling(payments);
@@ -4075,14 +4558,14 @@ function createBillingCommand() {
4075
4558
  payments.map((p) => [p.id, formatCents(p.amount, p.currency), p.status, p.dueDate ? formatDate(p.dueDate) : "-", p.description ?? "-"])
4076
4559
  );
4077
4560
  keyValue({ "Open": `${formatCents(sum.openCents)} (${sum.openCount})`, "Paid": formatCents(sum.paidCents) });
4078
- if (sum.openCount > 0) info("Pay one with: delegance pay <paymentId>");
4561
+ if (sum.openCount > 0) info(`Pay one with: ${cliInvocation()} pay <paymentId>`);
4079
4562
  } catch (err) {
4080
4563
  failWith("API error", err);
4081
4564
  }
4082
4565
  });
4083
4566
  }
4084
4567
  function createPayCommand() {
4085
- 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) => {
4568
+ 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) => {
4086
4569
  const client = getClient();
4087
4570
  try {
4088
4571
  if (!paymentId) {
@@ -4100,7 +4583,7 @@ function createPayCommand() {
4100
4583
  payments.map((p) => [p.id, formatCents(p.amount, p.currency), p.description ?? "", p.payable ? `${p.status} (payable)` : p.status, p.dueDate ? formatDate(p.dueDate) : "-"])
4101
4584
  );
4102
4585
  const next = payments.find((p) => p.payable);
4103
- if (next) info(`Pay it: delegance pay ${next.id}`);
4586
+ if (next) info(`Pay it: ${cliInvocation()} pay ${next.id}`);
4104
4587
  return;
4105
4588
  }
4106
4589
  const { checkoutUrl } = await client.payments.checkout(paymentId);
@@ -4130,14 +4613,14 @@ function bondStartLines(r, ctx = {}) {
4130
4613
  out.push(` ${str(q.key)}: ${str(q.label)}${q.required ? " (required)" : ""}${opts}`);
4131
4614
  });
4132
4615
  }
4133
- out.push(`Answer with: delegance bond answer ${str(r.session_id)} --answers answers.json`);
4616
+ out.push(`Answer with: ${cliInvocation()} bond answer ${str(r.session_id)} --answers answers.json`);
4134
4617
  return out;
4135
4618
  }
4136
4619
  if (Array.isArray(r.candidates) && r.candidates.length) {
4137
4620
  out.push("That name fits more than one bond. Rerun with the exact name:");
4138
4621
  const rawState = (ctx.state ?? "").trim();
4139
4622
  const state = !rawState ? null : /^[A-Za-z]{2}$/.test(rawState) ? rawState.toUpperCase() : shellQuote(rawState);
4140
- r.candidates.forEach((name) => out.push(state ? ` delegance bond quote --state ${state} --bond ${shellQuote(str(name))}` : ` --bond ${shellQuote(str(name))}`));
4623
+ r.candidates.forEach((name) => out.push(state ? ` ${cliInvocation()} bond quote --state ${state} --bond ${shellQuote(str(name))}` : ` --bond ${shellQuote(str(name))}`));
4141
4624
  return out;
4142
4625
  }
4143
4626
  if (r.needsAmount) {
@@ -4167,7 +4650,7 @@ function bondStartLines(r, ctx = {}) {
4167
4650
  return out;
4168
4651
  }
4169
4652
  function createBondCommand() {
4170
- const bond = new import_commander18.Command("bond").alias("bonds").description("Surety bond quotes");
4653
+ const bond = new import_commander19.Command("bond").alias("bonds").description("Surety bond quotes");
4171
4654
  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) => {
4172
4655
  try {
4173
4656
  const r = await getClient().bonds.start({
@@ -4192,7 +4675,7 @@ function createBondCommand() {
4192
4675
  if (options.json) json(r);
4193
4676
  else {
4194
4677
  console.log(JSON.stringify(r, null, 2));
4195
- info(`Check it: delegance bond status ${sessionId}`);
4678
+ info(`Check it: ${cliInvocation()} bond status ${sessionId}`);
4196
4679
  }
4197
4680
  } catch (err) {
4198
4681
  failWith("Could not submit the answers", err);
@@ -4213,7 +4696,7 @@ function createBondCommand() {
4213
4696
  return bond;
4214
4697
  }
4215
4698
  function createClaimCommand() {
4216
- const claim = new import_commander18.Command("claim").alias("claims").description("File and track claims");
4699
+ const claim = new import_commander19.Command("claim").alias("claims").description("File and track claims");
4217
4700
  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) => {
4218
4701
  let description = options.description;
4219
4702
  if (options.descriptionFile) {
@@ -4237,7 +4720,7 @@ function createClaimCommand() {
4237
4720
  success(r.message);
4238
4721
  keyValue({ Claim: r.claimId, Status: r.status, Portal: r.portalUrl });
4239
4722
  } catch (err) {
4240
- if (err instanceof import_sdk8.DeleganceError && err.reason === "gate_not_acknowledged") {
4723
+ if (err instanceof import_sdk9.DeleganceError && err.reason === "gate_not_acknowledged") {
4241
4724
  error("Accept the claims disclaimer once in the portal, then file again. It cannot be accepted for you.");
4242
4725
  info(String(err.body?.portalUrl ?? ""));
4243
4726
  process.exit(1);
@@ -4269,7 +4752,8 @@ function createClaimCommand() {
4269
4752
 
4270
4753
  // src/program.ts
4271
4754
  function createProgram() {
4272
- const program2 = new import_commander19.Command();
4755
+ registerMinimalCheckbox();
4756
+ const program2 = new import_commander20.Command();
4273
4757
  program2.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", () => {
4274
4758
  migrateLegacyConfigKey();
4275
4759
  });
@@ -4295,6 +4779,7 @@ function createProgram() {
4295
4779
  program2.addCommand(createBondCommand());
4296
4780
  program2.addCommand(createClaimCommand());
4297
4781
  program2.addCommand(createFeedbackCommand());
4782
+ program2.addCommand(createTermsCommand());
4298
4783
  program2.addCommand(createConfigCommand());
4299
4784
  return program2;
4300
4785
  }
@@ -4303,9 +4788,9 @@ function createProgram() {
4303
4788
  var program = createProgram();
4304
4789
  installLastCommandRecorder(program);
4305
4790
  program.on("command:*", () => {
4306
- console.error(import_chalk3.default.red(`Unknown command: ${program.args.join(" ")}`));
4791
+ console.error(import_chalk4.default.red(`Unknown command: ${program.args.join(" ")}`));
4307
4792
  console.log();
4308
- console.log('Run "delegance --help" for a list of available commands.');
4793
+ console.log(`Run "${cliInvocation()} --help" for a list of available commands.`);
4309
4794
  process.exit(1);
4310
4795
  });
4311
4796
  if (process.argv.length === 2) {