@sonnechasser/ntrp 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2392,7 +2392,7 @@ function secretPromptLine(question) {
2392
2392
  return ` ${paint("accent", "\u25B8")} ${bold(question)} ${chalk2.dim("(hidden \u2014 paste once, Enter)")} `;
2393
2393
  }
2394
2394
  function stripTerminalArtifacts(input) {
2395
- return input.replace(/\x1b\[[0-9;]*[a-zA-Z~]/g, "").replace(/\x1b\][^\x07]*(\x07|\x1b\\)/g, "");
2395
+ return input.replace(/\x1b\[[0-9;]*[a-zA-Z~]/g, "").replace(/\x1b\][^\x07]*(\x07|\x1b\\)/g, "").replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "");
2396
2396
  }
2397
2397
  function renderQuestion(question, defaultValue) {
2398
2398
  const base = ` ${marker()}${bold(question)}`;
@@ -2450,8 +2450,8 @@ function createPromptSession(existing, ctx) {
2450
2450
  for (; ; ) {
2451
2451
  const raw = (await rl.question(renderQuestion(`Your pick [1-${choices.length}]`, defaultLabel))).trim();
2452
2452
  assertNotGlobalReplCommand(raw);
2453
- const pick = raw || defaultLabel || "";
2454
- const n = Number(pick);
2453
+ const pick2 = raw || defaultLabel || "";
2454
+ const n = Number(pick2);
2455
2455
  if (Number.isInteger(n) && n >= 1 && n <= choices.length) {
2456
2456
  return choices[n - 1].value;
2457
2457
  }
@@ -2579,12 +2579,18 @@ function createPromptSession(existing, ctx) {
2579
2579
  console.log(" " + chalk2.dim("Try again \u2014 paste the key once, then Enter."));
2580
2580
  }
2581
2581
  }
2582
+ async function askPressEnter(message) {
2583
+ await rl.question(
2584
+ ` ${paint("accent", "\u25B8")} ${bold(message)} ${chalk2.dim("(Enter)")} `
2585
+ );
2586
+ }
2582
2587
  return {
2583
2588
  ask,
2584
2589
  askRequired,
2585
2590
  confirm,
2586
2591
  choose,
2587
2592
  askMulti,
2593
+ askPressEnter,
2588
2594
  askSecret,
2589
2595
  close: () => {
2590
2596
  if (ctx && existing) {
@@ -5306,16 +5312,16 @@ async function runGlobalAdminCommand(command, line, ctx) {
5306
5312
  const args = tokens.slice(1);
5307
5313
  switch (command) {
5308
5314
  case "scratch": {
5309
- const { handler: handler42 } = await Promise.resolve().then(() => (init_scratch(), scratch_exports));
5310
- return handler42(args, ctx);
5315
+ const { handler: handler44 } = await Promise.resolve().then(() => (init_scratch(), scratch_exports));
5316
+ return handler44(args, ctx);
5311
5317
  }
5312
5318
  case "cleanup": {
5313
- const { handler: handler42 } = await Promise.resolve().then(() => (init_cleanup(), cleanup_exports));
5314
- return handler42(args, ctx);
5319
+ const { handler: handler44 } = await Promise.resolve().then(() => (init_cleanup(), cleanup_exports));
5320
+ return handler44(args, ctx);
5315
5321
  }
5316
5322
  case "deactivate-demo": {
5317
- const { handler: handler42 } = await Promise.resolve().then(() => (init_deactivate_demo(), deactivate_demo_exports));
5318
- return handler42(args, ctx);
5323
+ const { handler: handler44 } = await Promise.resolve().then(() => (init_deactivate_demo(), deactivate_demo_exports));
5324
+ return handler44(args, ctx);
5319
5325
  }
5320
5326
  default:
5321
5327
  return void 0;
@@ -13972,12 +13978,12 @@ async function handleDraftHandoff(input) {
13972
13978
  };
13973
13979
  }
13974
13980
  async function executeToolCall(name, input, ctx) {
13975
- const handler42 = HANDLERS[name];
13976
- if (!handler42) {
13981
+ const handler44 = HANDLERS[name];
13982
+ if (!handler44) {
13977
13983
  return JSON.stringify({ error: `Unknown tool '${name}'` });
13978
13984
  }
13979
13985
  const start = Date.now();
13980
- const rawResult = await handler42(input, ctx);
13986
+ const rawResult = await handler44(input, ctx);
13981
13987
  const safeResult = stripPII(rawResult);
13982
13988
  const resultJson = JSON.stringify(safeResult);
13983
13989
  const duration = Date.now() - start;
@@ -14861,19 +14867,19 @@ async function promptForNewPath(ctx) {
14861
14867
  description: "Set up now, load data later"
14862
14868
  }
14863
14869
  ];
14864
- const pick = await prompts.choose(
14870
+ const pick2 = await prompts.choose(
14865
14871
  "Where should we start?",
14866
14872
  startChoices,
14867
14873
  { default: isDemoEnabled() ? "demo" : "file" }
14868
14874
  );
14869
- if (pick === "demo") {
14875
+ if (pick2 === "demo") {
14870
14876
  const lens2 = await prompts.choose("What kind of analysis?", [
14871
14877
  { value: "gtm_health", label: "Pipeline health", description: "Vital signs \u2014 motion, handoffs, stuck deals" },
14872
14878
  { value: "revenue_metrics", label: "SaaS metrics", description: "ARR, retention, pipeline efficiency" }
14873
14879
  ], { default: "gtm_health" });
14874
14880
  return { source: { kind: "demo" }, lens: lens2 };
14875
14881
  }
14876
- if (pick === "empty") {
14882
+ if (pick2 === "empty") {
14877
14883
  return { source: { kind: "empty" }, lens: "gtm_health" };
14878
14884
  }
14879
14885
  const path = (await prompts.ask("Path to the CSV file")).trim();
@@ -18767,47 +18773,439 @@ var init_config = __esm({
18767
18773
  init_argparse();
18768
18774
  init_prompts();
18769
18775
  init_theme();
18770
- SECRET_KEYS = /* @__PURE__ */ new Set(["api-key", "openai-api-key", "license-key"]);
18776
+ SECRET_KEYS = /* @__PURE__ */ new Set(["api-key", "openai-api-key", "license-key", "license-instance-id"]);
18777
+ }
18778
+ });
18779
+
18780
+ // src/license/trial-policy.ts
18781
+ function getCheckoutUrl() {
18782
+ return process.env.NTRP_CHECKOUT_URL ?? process.env.NTRP_PURCHASE_URL ?? SIGNUP_CHECKOUT_URL;
18783
+ }
18784
+ function getUpgradeUrl() {
18785
+ return process.env.NTRP_UPGRADE_URL ?? PRO_UPGRADE_CHECKOUT_URL ?? getCheckoutUrl();
18786
+ }
18787
+ function evaluateTrial(activatedAt, now2 = /* @__PURE__ */ new Date()) {
18788
+ const daysSince = Math.floor((now2.getTime() - activatedAt.getTime()) / 864e5);
18789
+ if (daysSince >= TRIAL_GRACE_END_DAYS) {
18790
+ return {
18791
+ phase: "expired",
18792
+ daysSinceActivation: daysSince,
18793
+ daysUntilLockout: 0,
18794
+ trialDaysRemaining: 0,
18795
+ shouldNudge: false
18796
+ };
18797
+ }
18798
+ if (daysSince >= TRIAL_FULL_DAYS) {
18799
+ return {
18800
+ phase: "grace",
18801
+ daysSinceActivation: daysSince,
18802
+ daysUntilLockout: TRIAL_GRACE_END_DAYS - daysSince,
18803
+ trialDaysRemaining: 0,
18804
+ shouldNudge: true
18805
+ };
18806
+ }
18807
+ const trialDaysRemaining = TRIAL_FULL_DAYS - daysSince;
18808
+ return {
18809
+ phase: "active",
18810
+ daysSinceActivation: daysSince,
18811
+ daysUntilLockout: TRIAL_GRACE_END_DAYS - daysSince,
18812
+ trialDaysRemaining,
18813
+ shouldNudge: daysSince >= TRIAL_ACTIVE_NUDGE_FROM_DAY
18814
+ };
18815
+ }
18816
+ function formatTrialActiveMessage(daysSince) {
18817
+ const daysLeft = TRIAL_FULL_DAYS - daysSince;
18818
+ if (daysLeft <= 0) return "trial license";
18819
+ const dayWord = daysLeft === 1 ? "day" : "days";
18820
+ return `trial license (${daysLeft} ${dayWord} remaining)`;
18821
+ }
18822
+ var TRIAL_FULL_DAYS, TRIAL_GRACE_END_DAYS, TRIAL_ACTIVE_NUDGE_FROM_DAY, SIGNUP_CHECKOUT_URL, PRO_UPGRADE_CHECKOUT_URL;
18823
+ var init_trial_policy = __esm({
18824
+ "src/license/trial-policy.ts"() {
18825
+ "use strict";
18826
+ TRIAL_FULL_DAYS = 11;
18827
+ TRIAL_GRACE_END_DAYS = 30;
18828
+ TRIAL_ACTIVE_NUDGE_FROM_DAY = 8;
18829
+ SIGNUP_CHECKOUT_URL = "https://sonnechasser.lemonsqueezy.com/checkout/buy/d62d35a2-a369-4cf5-a88b-328223866b5f";
18830
+ PRO_UPGRADE_CHECKOUT_URL = "https://sonnechasser.lemonsqueezy.com/checkout/buy/3bd1da42-936f-49a6-a6c3-d11eee213884";
18831
+ }
18832
+ });
18833
+
18834
+ // src/license/upgrade-whimsy.ts
18835
+ function pick(items) {
18836
+ return items[Math.floor(Math.random() * items.length)] ?? items[0];
18837
+ }
18838
+ function randomGraceNudge(daysLeft) {
18839
+ return pick(GRACE_NUDGES)(daysLeft);
18840
+ }
18841
+ function randomActiveTrialNudge(daysLeft) {
18842
+ return pick(ACTIVE_TRIAL_NUDGES)(daysLeft);
18843
+ }
18844
+ function randomCutoffNudge() {
18845
+ return pick(CUTOFF_NUDGES);
18846
+ }
18847
+ function randomBlockedNudge() {
18848
+ return pick(BLOCKED_WHILE_CUTOFF);
18849
+ }
18850
+ function randomUpgradeHeadline(daysLeft) {
18851
+ return pick(UPGRADE_HEADLINES)(daysLeft);
18852
+ }
18853
+ function randomUpgradeSubtitle(reason) {
18854
+ return pick(UPGRADE_SUBTITLES)(reason);
18855
+ }
18856
+ function randomProActivatedLine() {
18857
+ return pick(PRO_ACTIVATED_LINES);
18858
+ }
18859
+ var GRACE_NUDGES, ACTIVE_TRIAL_NUDGES, CUTOFF_NUDGES, BLOCKED_WHILE_CUTOFF, UPGRADE_HEADLINES, UPGRADE_SUBTITLES, PRO_ACTIVATED_LINES;
18860
+ var init_upgrade_whimsy = __esm({
18861
+ "src/license/upgrade-whimsy.ts"() {
18862
+ "use strict";
18863
+ init_trial_policy();
18864
+ GRACE_NUDGES = [
18865
+ (d) => `Hey \u2014 you still good on this? ${d} day${d === 1 ? "" : "s"} left. /upgrade when it makes sense.`,
18866
+ (d) => `Just checking in. ${d} day${d === 1 ? "" : "s"} before this quietly stops working. /upgrade.`,
18867
+ (d) => `No rush, but not forever either. ${d} day${d === 1 ? "" : "s"} \u2014 /upgrade.`,
18868
+ (d) => `You've had a good run. ${d} day${d === 1 ? "" : "s"} of wiggle room left. /upgrade if you're staying.`,
18869
+ (d) => `Still here? Cool. ${d} day${d === 1 ? "" : "s"} and then I'll need a yes from you. /upgrade.`,
18870
+ (d) => `Didn't want to bug you. ${d} day${d === 1 ? "" : "s"} though \u2014 /upgrade.`,
18871
+ (d) => `The ${TRIAL_FULL_DAYS}-day thing was real. You're in extra time \u2014 ${d} day${d === 1 ? "" : "s"}. /upgrade.`,
18872
+ (d) => `I'll leave you alone after this. ${d} day${d === 1 ? "" : "s"} \u2014 /upgrade or we part ways.`,
18873
+ (d) => `Genuinely hope you stick around. ${d} day${d === 1 ? "" : "s"} to decide. /upgrade.`,
18874
+ (d) => `Not trying to be pushy. ${d} day${d === 1 ? "" : "s"} is just what's left. /upgrade.`,
18875
+ (d) => `You've been at this a while \u2014 ${d} day${d === 1 ? "" : "s"} before the door closes. /upgrade.`,
18876
+ (d) => `Wanted to give you a heads up: ${d} day${d === 1 ? "" : "s"}. /upgrade keeps you in.`,
18877
+ (d) => `If you're still into it, cool. ${d} day${d === 1 ? "" : "s"} \u2014 /upgrade.`,
18878
+ (d) => `Last friendly ping. ${d} day${d === 1 ? "" : "s"}. /upgrade.`
18879
+ ];
18880
+ ACTIVE_TRIAL_NUDGES = [
18881
+ (d) => `Heads up \u2014 ${d} day${d === 1 ? "" : "s"} left on the trial. /upgrade if you know you're staying.`,
18882
+ (d) => `Trial's winding down (${d} day${d === 1 ? "" : "s"}). No rush \u2014 /upgrade when you're ready.`,
18883
+ (d) => `Just so you know: ${d} day${d === 1 ? "" : "s"} on the trial clock. /upgrade keeps you going.`,
18884
+ (d) => `Wanted to mention it early \u2014 ${d} day${d === 1 ? "" : "s"} left. /upgrade if this is your thing.`,
18885
+ (d) => `Still exploring? Cool. ${d} day${d === 1 ? "" : "s"} on trial \u2014 /upgrade when you decide.`
18886
+ ];
18887
+ CUTOFF_NUDGES = [
18888
+ "Okay \u2014 that's the line. /upgrade and you're back.",
18889
+ "We're paused until you say yes. /upgrade.",
18890
+ "Didn't want it to end like this. /upgrade if you want in again.",
18891
+ "Time's up. /upgrade \u2014 takes a minute.",
18892
+ "I'll be here. You just need to /upgrade first.",
18893
+ "That's all I can do on the free side. /upgrade.",
18894
+ "Door's closed for now. /upgrade opens it."
18895
+ ];
18896
+ BLOCKED_WHILE_CUTOFF = [
18897
+ "Can't do that until you're back in \u2014 /upgrade.",
18898
+ "You're on the outside for now. /upgrade first.",
18899
+ "Need you on Pro for this. /upgrade \u2014 quick.",
18900
+ "Not available on the trial anymore. /upgrade, then try again."
18901
+ ];
18902
+ UPGRADE_HEADLINES = [
18903
+ () => "Still with us?",
18904
+ () => "Quick thing",
18905
+ (d) => d !== void 0 ? `${d} day${d === 1 ? "" : "s"} left` : "Let's sort this",
18906
+ () => "Wanted to check in",
18907
+ () => "One small step",
18908
+ () => "Stay?"
18909
+ ];
18910
+ UPGRADE_SUBTITLES = [
18911
+ (r) => r === "expired" ? "Trial's over. Checkout, key in your email, paste below." : r === "grace" ? `You've had ${TRIAL_FULL_DAYS} days plus a little extra. This is the part where you decide.` : "Checkout, email, paste. That's it.",
18912
+ (r) => r === "expired" ? "Nothing else changes. Same session, same data." : r === "grace" ? "I'm not in a hurry. The clock kind of is." : "No call. No runaround.",
18913
+ (r) => r === "expired" ? "Your work's still here. You just need a key." : r === "grace" ? "Stay if you want \u2014 just need to hear from you first." : "Sixty seconds, give or take."
18914
+ ];
18915
+ PRO_ACTIVATED_LINES = [
18916
+ "Good \u2014 you're in. Pick up where you left off.",
18917
+ "All set. Let's go.",
18918
+ "Thanks. Same place you were.",
18919
+ "Done. Back to it.",
18920
+ "Appreciate it.",
18921
+ "You're good. Continue."
18922
+ ];
18923
+ }
18924
+ });
18925
+
18926
+ // src/license/normalize.ts
18927
+ function normalizeLicenseKeyInput(raw) {
18928
+ let key = raw.trim();
18929
+ key = key.replace(/^\[>\s*/, "");
18930
+ key = key.replace(/^\[\s*▶\s*/, "");
18931
+ key = key.replace(/^▶\s*/, "");
18932
+ key = key.replace(/\s+/g, "");
18933
+ if (NTRP_PREFIX.test(key)) {
18934
+ return `NTRP-${key.replace(/^NTRP-/i, "").toLowerCase()}`;
18935
+ }
18936
+ if (UUID_KEY.test(key)) return key.toLowerCase();
18937
+ return key;
18938
+ }
18939
+ function detectLicenseFormat(key) {
18940
+ if (NTRP_PREFIX.test(key)) return "ntrp";
18941
+ if (UUID_KEY.test(key)) return "lemonsqueezy";
18942
+ return "unknown";
18943
+ }
18944
+ var NTRP_PREFIX, UUID_KEY;
18945
+ var init_normalize = __esm({
18946
+ "src/license/normalize.ts"() {
18947
+ "use strict";
18948
+ NTRP_PREFIX = /^NTRP-/i;
18949
+ UUID_KEY = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18950
+ }
18951
+ });
18952
+
18953
+ // src/license/lemonsqueezy.ts
18954
+ import { hostname } from "os";
18955
+ function invalid(message) {
18956
+ return {
18957
+ valid: false,
18958
+ edition: "trial",
18959
+ expiresAt: null,
18960
+ message
18961
+ };
18962
+ }
18963
+ function editionFromMeta(meta) {
18964
+ const label = `${meta?.variant_name ?? ""} ${meta?.product_name ?? ""}`.toLowerCase();
18965
+ if (label.includes("trial")) return "trial";
18966
+ if (label.includes("team")) return "team";
18967
+ return "pro";
18968
+ }
18969
+ function expiresAtFromKey(licenseKey) {
18970
+ if (!licenseKey?.expires_at) return null;
18971
+ const parsed = new Date(licenseKey.expires_at);
18972
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
18973
+ }
18974
+ function statusMessage(edition, expiresAt, meta) {
18975
+ const product = meta?.variant_name || meta?.product_name;
18976
+ const base = product ? `${edition} license (${product})` : `${edition} license`;
18977
+ return expiresAt ? `${base} (expires ${expiresAt.toISOString().slice(0, 10)})` : base;
18978
+ }
18979
+ function mapLsFailure(error, licenseKey) {
18980
+ const status = licenseKey?.status?.toLowerCase();
18981
+ if (status === "expired") {
18982
+ return invalid("Time's up \u2014 /upgrade and paste your key.");
18983
+ }
18984
+ if (status === "disabled") {
18985
+ return invalid("License disabled. Contact support or purchase a new license.");
18986
+ }
18987
+ if (error?.toLowerCase().includes("activation limit")) {
18988
+ return invalid(
18989
+ "License activation limit reached. Deactivate an old machine in your Lemon Squeezy account, then try again."
18990
+ );
18991
+ }
18992
+ return invalid(error?.trim() || "Could not activate license key");
18993
+ }
18994
+ async function postLicense(path, fields) {
18995
+ const body = new URLSearchParams(fields);
18996
+ const res = await fetch(`${LICENSE_API}/${path}`, {
18997
+ method: "POST",
18998
+ headers: { Accept: "application/json" },
18999
+ body,
19000
+ signal: AbortSignal.timeout(15e3)
19001
+ });
19002
+ const data = await res.json();
19003
+ if (!res.ok && !data.error) {
19004
+ throw new Error(`License server error (${res.status})`);
19005
+ }
19006
+ return data;
19007
+ }
19008
+ function defaultInstanceName() {
19009
+ const host = hostname().replace(/[^\w.-]/g, "-").slice(0, 48) || "machine";
19010
+ const user = (process.env.USER || process.env.USERNAME || "user").replace(/[^\w.-]/g, "-").slice(0, 15);
19011
+ return `ntrp-${host}-${user}`;
19012
+ }
19013
+ async function activateLemonSqueezyLicense(licenseKey, instanceName = defaultInstanceName()) {
19014
+ const data = await postLicense("activate", {
19015
+ license_key: licenseKey,
19016
+ instance_name: instanceName
19017
+ });
19018
+ if (!data.activated) {
19019
+ return mapLsFailure(data.error, data.license_key);
19020
+ }
19021
+ const edition = editionFromMeta(data.meta);
19022
+ const expiresAt = expiresAtFromKey(data.license_key);
19023
+ const instanceId = data.instance?.id;
19024
+ if (!instanceId) {
19025
+ return invalid("Activation succeeded but no instance id was returned. Try again.");
19026
+ }
19027
+ return {
19028
+ valid: true,
19029
+ edition,
19030
+ expiresAt,
19031
+ message: statusMessage(edition, expiresAt, data.meta),
19032
+ instanceId
19033
+ };
19034
+ }
19035
+ async function validateLemonSqueezyLicense(licenseKey, instanceId) {
19036
+ const data = await postLicense("validate", {
19037
+ license_key: licenseKey,
19038
+ instance_id: instanceId
19039
+ });
19040
+ if (!data.valid) {
19041
+ return mapLsFailure(data.error, data.license_key);
19042
+ }
19043
+ const edition = editionFromMeta(data.meta);
19044
+ const expiresAt = expiresAtFromKey(data.license_key);
19045
+ return {
19046
+ valid: true,
19047
+ edition,
19048
+ expiresAt,
19049
+ message: statusMessage(edition, expiresAt, data.meta)
19050
+ };
19051
+ }
19052
+ var LICENSE_API;
19053
+ var init_lemonsqueezy = __esm({
19054
+ "src/license/lemonsqueezy.ts"() {
19055
+ "use strict";
19056
+ LICENSE_API = "https://api.lemonsqueezy.com/v1/licenses";
18771
19057
  }
18772
19058
  });
18773
19059
 
18774
19060
  // src/license/verify.ts
18775
19061
  import { createHmac } from "crypto";
18776
19062
  function validateLicenseKey(key) {
18777
- const invalid = (msg) => ({
19063
+ const invalid2 = (msg) => ({
18778
19064
  valid: false,
18779
19065
  edition: "trial",
18780
19066
  expiresAt: null,
18781
19067
  message: msg
18782
19068
  });
18783
19069
  if (!key || !key.startsWith("NTRP-")) {
18784
- return invalid("Invalid key format");
19070
+ return invalid2("Invalid key format");
18785
19071
  }
18786
19072
  const parts = key.replace("NTRP-", "").split("-");
18787
19073
  if (parts.length !== 3) {
18788
- return invalid("Invalid key format");
19074
+ return invalid2("Invalid key format");
18789
19075
  }
18790
19076
  const [payload, meta, signature] = parts;
18791
19077
  const dataToSign = `${payload}-${meta}`;
18792
19078
  const expectedSig = createHmac("sha256", SIGNING_SECRET).update(dataToSign).digest("hex").slice(0, 8);
18793
19079
  if (signature !== expectedSig) {
18794
- return invalid("Invalid license key");
19080
+ return invalid2("Invalid license key");
18795
19081
  }
18796
19082
  const editionCode = meta.slice(0, 2);
18797
19083
  const expiryHex = meta.slice(2);
18798
19084
  const edition = editionCode === "01" ? "pro" : editionCode === "02" ? "team" : "trial";
18799
19085
  const expiryTs = parseInt(expiryHex, 16);
18800
19086
  const expiresAt = expiryTs > 0 ? new Date(expiryTs * 1e3) : null;
18801
- if (expiresAt && expiresAt < /* @__PURE__ */ new Date()) {
18802
- return invalid(`License expired on ${expiresAt.toISOString().slice(0, 10)}`);
19087
+ if (expiresAt && expiresAt < /* @__PURE__ */ new Date() && edition !== "trial") {
19088
+ return invalid2(`License expired on ${expiresAt.toISOString().slice(0, 10)}`);
18803
19089
  }
18804
19090
  return {
18805
19091
  valid: true,
18806
19092
  edition,
18807
19093
  expiresAt,
18808
- message: `${edition} license${expiresAt ? ` (expires ${expiresAt.toISOString().slice(0, 10)})` : " (perpetual)"}`
19094
+ message: edition === "trial" ? "trial license" : `${edition} license${expiresAt ? ` (expires ${expiresAt.toISOString().slice(0, 10)})` : " (perpetual)"}`
19095
+ };
19096
+ }
19097
+ function trialActivatedAt() {
19098
+ const stored = getConfigValue("license-activated-at");
19099
+ if (stored) {
19100
+ const parsed = new Date(stored);
19101
+ if (!Number.isNaN(parsed.getTime())) return parsed;
19102
+ }
19103
+ const now2 = /* @__PURE__ */ new Date();
19104
+ setConfigValue("license-activated-at", now2.toISOString());
19105
+ return now2;
19106
+ }
19107
+ function recordLicenseActivation(edition) {
19108
+ if (edition === "trial") {
19109
+ setConfigValue("license-activated-at", (/* @__PURE__ */ new Date()).toISOString());
19110
+ } else {
19111
+ deleteConfigValue("license-activated-at");
19112
+ }
19113
+ }
19114
+ function applyTrialPolicy(result) {
19115
+ if (result.edition !== "trial") return result;
19116
+ const trial = evaluateTrial(trialActivatedAt());
19117
+ if (trial.phase === "expired") {
19118
+ return {
19119
+ valid: false,
19120
+ edition: "trial",
19121
+ expiresAt: result.expiresAt,
19122
+ message: randomCutoffNudge(),
19123
+ trialPhase: "expired",
19124
+ shouldNudgeUpgrade: false,
19125
+ daysUntilLockout: 0,
19126
+ trialDaysRemaining: 0
19127
+ };
19128
+ }
19129
+ const message = trial.phase === "grace" ? `trial license (grace \u2014 ${trial.daysUntilLockout} day${trial.daysUntilLockout === 1 ? "" : "s"} until lockout)` : formatTrialActiveMessage(trial.daysSinceActivation);
19130
+ return {
19131
+ ...result,
19132
+ message,
19133
+ trialPhase: trial.phase,
19134
+ shouldNudgeUpgrade: trial.shouldNudge,
19135
+ daysUntilLockout: trial.daysUntilLockout,
19136
+ trialDaysRemaining: trial.trialDaysRemaining
18809
19137
  };
18810
19138
  }
19139
+ function storedLicenseProvider(key) {
19140
+ const configured = getConfigValue("license-provider");
19141
+ if (configured === "ntrp" || configured === "lemonsqueezy") return configured;
19142
+ return detectLicenseFormat(key) === "lemonsqueezy" ? "lemonsqueezy" : "ntrp";
19143
+ }
19144
+ function checkLemonSqueezyLicense(key) {
19145
+ const instanceId = getConfigValue("license-instance-id");
19146
+ if (!instanceId) {
19147
+ return {
19148
+ valid: false,
19149
+ edition: "trial",
19150
+ expiresAt: null,
19151
+ message: "License not activated on this machine. Run: ntrp activate <key>"
19152
+ };
19153
+ }
19154
+ const edition = getConfigValue("license-edition") ?? "pro";
19155
+ const base = {
19156
+ valid: true,
19157
+ edition,
19158
+ expiresAt: null,
19159
+ message: `${edition} license`
19160
+ };
19161
+ return applyTrialPolicy(base);
19162
+ }
19163
+ async function activateLicenseKey(rawKey) {
19164
+ const key = normalizeLicenseKeyInput(rawKey);
19165
+ const format = detectLicenseFormat(key);
19166
+ if (format === "unknown") {
19167
+ return {
19168
+ valid: false,
19169
+ edition: "trial",
19170
+ expiresAt: null,
19171
+ message: "Invalid key format"
19172
+ };
19173
+ }
19174
+ if (format === "ntrp") {
19175
+ const result = validateLicenseKey(key);
19176
+ if (!result.valid) return result;
19177
+ setConfigValue("license-key", key);
19178
+ setConfigValue("license-provider", "ntrp");
19179
+ deleteConfigValue("license-instance-id");
19180
+ deleteConfigValue("license-edition");
19181
+ recordLicenseActivation(result.edition);
19182
+ return checkLicense();
19183
+ }
19184
+ const activated = await activateLemonSqueezyLicense(key);
19185
+ if (!activated.valid || !activated.instanceId) return activated;
19186
+ setConfigValue("license-key", key);
19187
+ setConfigValue("license-provider", "lemonsqueezy");
19188
+ setConfigValue("license-instance-id", activated.instanceId);
19189
+ setConfigValue("license-edition", activated.edition);
19190
+ recordLicenseActivation(activated.edition);
19191
+ return checkLicense();
19192
+ }
19193
+ async function refreshLicenseOnline() {
19194
+ const key = getConfigValue("license-key");
19195
+ if (!key || storedLicenseProvider(key) !== "lemonsqueezy") {
19196
+ return checkLicense();
19197
+ }
19198
+ const instanceId = getConfigValue("license-instance-id");
19199
+ if (!instanceId) return checkLicense();
19200
+ try {
19201
+ const result = await validateLemonSqueezyLicense(key, instanceId);
19202
+ if (!result.valid) return result;
19203
+ setConfigValue("license-edition", result.edition);
19204
+ return checkLicense();
19205
+ } catch {
19206
+ return checkLicense();
19207
+ }
19208
+ }
18811
19209
  function checkLicense() {
18812
19210
  const key = getConfigValue("license-key");
18813
19211
  if (!key) {
@@ -18818,13 +19216,24 @@ function checkLicense() {
18818
19216
  message: "No license key found. Run: ntrp activate <key>"
18819
19217
  };
18820
19218
  }
18821
- return validateLicenseKey(key);
19219
+ if (storedLicenseProvider(key) === "lemonsqueezy") {
19220
+ return checkLemonSqueezyLicense(key);
19221
+ }
19222
+ const result = validateLicenseKey(key);
19223
+ if (!result.valid || result.edition !== "trial") {
19224
+ return result;
19225
+ }
19226
+ return applyTrialPolicy(result);
18822
19227
  }
18823
19228
  var SIGNING_SECRET;
18824
19229
  var init_verify = __esm({
18825
19230
  "src/license/verify.ts"() {
18826
19231
  "use strict";
18827
19232
  init_store();
19233
+ init_trial_policy();
19234
+ init_upgrade_whimsy();
19235
+ init_normalize();
19236
+ init_lemonsqueezy();
18828
19237
  SIGNING_SECRET = "ntrp-gtm-health-2026";
18829
19238
  }
18830
19239
  });
@@ -18840,27 +19249,308 @@ async function handler24(args, _ctx) {
18840
19249
  const key = positional[0];
18841
19250
  if (!key) {
18842
19251
  console.error(chalk38.red("\n Usage: /activate <key>"));
18843
- console.error(chalk38.dim(" License key format: NTRP-XXXX-XXXX-XXXX\n"));
19252
+ console.error(chalk38.dim(" Or type /upgrade for checkout + paste flow.\n"));
18844
19253
  process.exit(1);
18845
19254
  }
18846
- const result = validateLicenseKey(key);
18847
- if (!result.valid) {
19255
+ try {
19256
+ const result = await activateLicenseKey(key);
19257
+ if (!result.valid) {
19258
+ console.error(chalk38.red(`
19259
+ ${result.message}
19260
+ `));
19261
+ process.exit(1);
19262
+ }
19263
+ console.log(chalk38.green(`
19264
+ License activated: ${result.message}
19265
+ `));
19266
+ } catch (err) {
19267
+ const message = err instanceof Error ? err.message : "License activation failed";
18848
19268
  console.error(chalk38.red(`
18849
- Invalid license key: ${result.message}
19269
+ ${message}
18850
19270
  `));
19271
+ console.error(chalk38.dim(" Check your network connection and try again.\n"));
18851
19272
  process.exit(1);
18852
19273
  }
18853
- setConfigValue("license-key", key);
18854
- console.log(chalk38.green(`
18855
- License activated: ${result.message}
18856
- `));
18857
19274
  }
18858
19275
  var init_activate = __esm({
18859
19276
  "src/commands/activate.ts"() {
18860
19277
  "use strict";
19278
+ init_verify();
19279
+ init_argparse();
19280
+ }
19281
+ });
19282
+
19283
+ // src/ui/open-browser.ts
19284
+ import { spawn } from "child_process";
19285
+ import { platform } from "os";
19286
+ function openInBrowser(url) {
19287
+ return new Promise((resolve9, reject) => {
19288
+ let cmd;
19289
+ let args;
19290
+ switch (platform()) {
19291
+ case "darwin":
19292
+ cmd = "open";
19293
+ args = [url];
19294
+ break;
19295
+ case "win32":
19296
+ cmd = "cmd";
19297
+ args = ["/c", "start", "", url];
19298
+ break;
19299
+ default:
19300
+ cmd = "xdg-open";
19301
+ args = [url];
19302
+ break;
19303
+ }
19304
+ const child = spawn(cmd, args, { detached: true, stdio: "ignore" });
19305
+ child.on("error", reject);
19306
+ child.unref();
19307
+ resolve9();
19308
+ });
19309
+ }
19310
+ var init_open_browser = __esm({
19311
+ "src/ui/open-browser.ts"() {
19312
+ "use strict";
19313
+ }
19314
+ });
19315
+
19316
+ // src/license/upgrade.ts
19317
+ var upgrade_exports = {};
19318
+ __export(upgrade_exports, {
19319
+ getCheckoutUrl: () => getCheckoutUrl,
19320
+ getUpgradeUrl: () => getUpgradeUrl,
19321
+ hasStoredLicenseKey: () => hasStoredLicenseKey,
19322
+ isTrialCutoff: () => isTrialCutoff,
19323
+ isTrialGrace: () => isTrialGrace,
19324
+ openCheckoutInBrowser: () => openCheckoutInBrowser,
19325
+ printActiveTrialNudge: () => printActiveTrialNudge,
19326
+ printGraceNudge: () => printGraceNudge,
19327
+ printLicenseBlocked: () => printLicenseBlocked,
19328
+ printTrialNudge: () => printTrialNudge,
19329
+ promptForLicenseKey: () => promptForLicenseKey,
19330
+ promptOpenCheckout: () => promptOpenCheckout,
19331
+ resolveUpgradeReason: () => resolveUpgradeReason,
19332
+ runUpgradeFlow: () => runUpgradeFlow
19333
+ });
19334
+ import chalk39 from "chalk";
19335
+ function checkoutUrlFor(purpose) {
19336
+ return purpose === "upgrade" ? getUpgradeUrl() : getCheckoutUrl();
19337
+ }
19338
+ function isTrialCutoff(lic) {
19339
+ return lic.trialPhase === "expired";
19340
+ }
19341
+ function isTrialGrace(lic) {
19342
+ return lic.trialPhase === "grace";
19343
+ }
19344
+ function printLicenseBlocked(context) {
19345
+ const lic = checkLicense();
19346
+ console.log();
19347
+ if (isTrialCutoff(lic)) {
19348
+ console.log(" " + chalk39.yellow(randomBlockedNudge()));
19349
+ } else {
19350
+ console.log(chalk39.red(` A license is required for ${context}.`));
19351
+ console.log(
19352
+ " " + chalk39.dim("Type ") + paint("accent", "/upgrade") + chalk39.dim(" or ") + paint("accent", "/checkout") + chalk39.dim(" to get a license.")
19353
+ );
19354
+ }
19355
+ console.log();
19356
+ }
19357
+ function printGraceNudge(lic) {
19358
+ if (!lic.shouldNudgeUpgrade || lic.daysUntilLockout === void 0) return;
19359
+ console.log(" " + chalk39.yellow(randomGraceNudge(lic.daysUntilLockout)));
19360
+ console.log();
19361
+ }
19362
+ function printActiveTrialNudge(lic) {
19363
+ if (!lic.shouldNudgeUpgrade || lic.trialPhase !== "active") return;
19364
+ const daysLeft = lic.trialDaysRemaining;
19365
+ if (daysLeft === void 0 || daysLeft <= 0) return;
19366
+ console.log(" " + chalk39.yellow(randomActiveTrialNudge(daysLeft)));
19367
+ console.log();
19368
+ }
19369
+ function printTrialNudge(lic) {
19370
+ if (!lic.shouldNudgeUpgrade) return;
19371
+ if (lic.trialPhase === "grace") {
19372
+ printGraceNudge(lic);
19373
+ return;
19374
+ }
19375
+ if (lic.trialPhase === "active") {
19376
+ printActiveTrialNudge(lic);
19377
+ }
19378
+ }
19379
+ function headlineFor(reason, lic) {
19380
+ return randomUpgradeHeadline(lic.daysUntilLockout);
19381
+ }
19382
+ function subtitleFor(reason) {
19383
+ return randomUpgradeSubtitle(reason);
19384
+ }
19385
+ async function promptOpenCheckout(ctx, purpose = "signup") {
19386
+ const url = checkoutUrlFor(purpose);
19387
+ console.log(" " + chalk39.dim(url));
19388
+ if (!process.stdin.isTTY || process.env.NTRP_NO_BROWSER_OPEN === "1") {
19389
+ console.log();
19390
+ return;
19391
+ }
19392
+ const session = createPromptSession(ctx.rl, ctx);
19393
+ try {
19394
+ console.log();
19395
+ await session.askPressEnter("Open checkout in your browser");
19396
+ try {
19397
+ await openInBrowser(url);
19398
+ console.log(" " + chalk39.green("\u2713 Browser opened"));
19399
+ console.log(
19400
+ " " + chalk39.dim(
19401
+ purpose === "upgrade" ? "Complete checkout in your browser, then paste your Pro key below." : "Complete signup in your browser, then paste your key below."
19402
+ )
19403
+ );
19404
+ } catch {
19405
+ console.log(" " + chalk39.yellow("Couldn't open browser \u2014 copy the URL above."));
19406
+ }
19407
+ console.log();
19408
+ } finally {
19409
+ session.close();
19410
+ }
19411
+ }
19412
+ async function openCheckoutInBrowser() {
19413
+ const url = getCheckoutUrl();
19414
+ console.log();
19415
+ console.log(" " + chalk39.dim(url));
19416
+ if (!process.stdin.isTTY) {
19417
+ console.log();
19418
+ return;
19419
+ }
19420
+ try {
19421
+ await openInBrowser(url);
19422
+ console.log(" " + chalk39.green("\u2713 Browser opened"));
19423
+ } catch {
19424
+ console.log(" " + chalk39.yellow("Couldn't open browser \u2014 copy the URL above."));
19425
+ }
19426
+ console.log(" " + chalk39.dim("After signup, paste your key with /activate or /upgrade."));
19427
+ console.log();
19428
+ }
19429
+ async function promptForLicenseKey(ctx, purpose = "signup") {
19430
+ const session = createPromptSession(ctx.rl, ctx);
19431
+ try {
19432
+ for (; ; ) {
19433
+ const key = await session.askSecret("Paste your license key", { confirm: false });
19434
+ if (!key.trim()) {
19435
+ console.log(" " + chalk39.red("A license key is required."));
19436
+ continue;
19437
+ }
19438
+ let result;
19439
+ try {
19440
+ result = await activateLicenseKey(key.trim());
19441
+ } catch (err) {
19442
+ const message = err instanceof Error ? err.message : "License activation failed";
19443
+ console.log(" " + chalk39.red(message));
19444
+ console.log(" " + chalk39.dim("Check your network connection and try again."));
19445
+ console.log();
19446
+ continue;
19447
+ }
19448
+ if (!result.valid) {
19449
+ console.log(" " + chalk39.red(result.message));
19450
+ console.log(
19451
+ " " + chalk39.dim(`Use the key from your purchase email, or try again: ${checkoutUrlFor(purpose)}`)
19452
+ );
19453
+ console.log();
19454
+ continue;
19455
+ }
19456
+ console.log();
19457
+ console.log(chalk39.green(` \u2713 ${randomProActivatedLine()}`));
19458
+ console.log();
19459
+ return true;
19460
+ }
19461
+ } finally {
19462
+ session.close();
19463
+ }
19464
+ }
19465
+ async function runUpgradeFlow(ctx, reason) {
19466
+ const lic = checkLicense();
19467
+ printCenteredLogo();
19468
+ console.log(" " + bold(headlineFor(reason, lic)));
19469
+ console.log(" " + chalk39.dim(subtitleFor(reason)));
19470
+ console.log();
19471
+ await promptOpenCheckout(ctx, "upgrade");
19472
+ console.log(" " + chalk39.dim("Paste your license key when it arrives by email"));
19473
+ console.log();
19474
+ return promptForLicenseKey(ctx, "upgrade");
19475
+ }
19476
+ function resolveUpgradeReason() {
19477
+ const lic = checkLicense();
19478
+ if (isTrialCutoff(lic)) return "expired";
19479
+ if (isTrialGrace(lic)) return "grace";
19480
+ return "convert";
19481
+ }
19482
+ function hasStoredLicenseKey() {
19483
+ return Boolean(getConfigValue("license-key"));
19484
+ }
19485
+ var init_upgrade = __esm({
19486
+ "src/license/upgrade.ts"() {
19487
+ "use strict";
19488
+ init_prompts();
18861
19489
  init_store();
19490
+ init_banner();
19491
+ init_theme();
18862
19492
  init_verify();
19493
+ init_trial_policy();
19494
+ init_upgrade_whimsy();
19495
+ init_open_browser();
19496
+ }
19497
+ });
19498
+
19499
+ // src/commands/upgrade.ts
19500
+ var upgrade_exports2 = {};
19501
+ __export(upgrade_exports2, {
19502
+ handler: () => handler25
19503
+ });
19504
+ import chalk40 from "chalk";
19505
+ async function handler25(args, ctx) {
19506
+ const { flags } = parseArgs2(args);
19507
+ const lic = await refreshLicenseOnline();
19508
+ if (getBool(flags, "url", "checkout")) {
19509
+ console.log(getUpgradeUrl());
19510
+ return;
19511
+ }
19512
+ if (lic.valid && lic.edition !== "trial" && lic.trialPhase !== "grace") {
19513
+ console.log();
19514
+ console.log(chalk40.green(" You're already on a paid license."));
19515
+ console.log(" " + chalk40.dim(`${lic.message}`));
19516
+ console.log(" " + chalk40.dim(`Need another seat? ${getUpgradeUrl()}`));
19517
+ console.log();
19518
+ return;
19519
+ }
19520
+ if (!process.stdin.isTTY) {
19521
+ console.error(chalk40.red("\n /upgrade requires an interactive terminal.\n"));
19522
+ console.error(chalk40.dim(` Purchase at ${getUpgradeUrl()}
19523
+ `));
19524
+ console.error(chalk40.dim(" Then run: ntrp activate <your-pro-key>\n"));
19525
+ process.exit(1);
19526
+ }
19527
+ const reason = resolveUpgradeReason();
19528
+ const activated = await runUpgradeFlow(ctx, reason);
19529
+ if (!activated) {
19530
+ process.exit(1);
19531
+ }
19532
+ }
19533
+ var init_upgrade2 = __esm({
19534
+ "src/commands/upgrade.ts"() {
19535
+ "use strict";
18863
19536
  init_argparse();
19537
+ init_upgrade();
19538
+ init_verify();
19539
+ }
19540
+ });
19541
+
19542
+ // src/commands/checkout.ts
19543
+ var checkout_exports = {};
19544
+ __export(checkout_exports, {
19545
+ handler: () => handler26
19546
+ });
19547
+ async function handler26(_args, _ctx) {
19548
+ await openCheckoutInBrowser();
19549
+ }
19550
+ var init_checkout = __esm({
19551
+ "src/commands/checkout.ts"() {
19552
+ "use strict";
19553
+ init_upgrade();
18864
19554
  }
18865
19555
  });
18866
19556
 
@@ -18903,7 +19593,9 @@ function setupCheck() {
18903
19593
  },
18904
19594
  license: {
18905
19595
  valid: license.valid,
18906
- message: license.message
19596
+ message: license.message,
19597
+ trial_phase: license.trialPhase ?? null,
19598
+ days_until_lockout: license.daysUntilLockout ?? null
18907
19599
  }
18908
19600
  };
18909
19601
  }
@@ -18957,10 +19649,22 @@ var init_setup = __esm({
18957
19649
  // src/commands/setup.ts
18958
19650
  var setup_exports = {};
18959
19651
  __export(setup_exports, {
18960
- handler: () => handler25
19652
+ handler: () => handler27
18961
19653
  });
18962
- import chalk39 from "chalk";
18963
- async function handler25(args, ctx) {
19654
+ import chalk41 from "chalk";
19655
+ function formatLicenseSetupLine(license) {
19656
+ if (!license.valid) {
19657
+ return `missing/invalid \u2014 ${license.message}`;
19658
+ }
19659
+ if (license.trial_phase === "grace" && license.days_until_lockout != null) {
19660
+ return `valid \u2014 trial grace (${license.days_until_lockout} day${license.days_until_lockout === 1 ? "" : "s"} until lockout)`;
19661
+ }
19662
+ if (license.trial_phase === "active") {
19663
+ return `valid \u2014 ${license.message}`;
19664
+ }
19665
+ return `valid \u2014 ${license.message}`;
19666
+ }
19667
+ async function handler27(args, ctx) {
18964
19668
  const { positional, flags } = parseArgs2(args);
18965
19669
  const sub = positional[0] ?? "check";
18966
19670
  try {
@@ -18972,7 +19676,7 @@ async function handler25(args, ctx) {
18972
19676
  return;
18973
19677
  }
18974
19678
  console.log();
18975
- console.log(chalk39.bold(" Setup Check"));
19679
+ console.log(chalk41.bold(" Setup Check"));
18976
19680
  console.log(` NTRP home: ${result.ntrp_home}`);
18977
19681
  console.log(` Writable: ${result.writable ? "yes" : "no"}`);
18978
19682
  console.log(` Profile: ${result.profile.exists ? "ready" : "missing"} (${result.profile.path})`);
@@ -18985,7 +19689,7 @@ async function handler25(args, ctx) {
18985
19689
  } else {
18986
19690
  console.log(" Engines: missing");
18987
19691
  }
18988
- console.log(` License: ${result.license.valid ? "valid" : "missing/invalid"} - ${result.license.message}`);
19692
+ console.log(` License: ${formatLicenseSetupLine(result.license)}`);
18989
19693
  console.log();
18990
19694
  return;
18991
19695
  }
@@ -19018,7 +19722,7 @@ async function handler25(args, ctx) {
19018
19722
  emitResult("setup", result);
19019
19723
  return;
19020
19724
  }
19021
- console.log(chalk39.green(`
19725
+ console.log(chalk41.green(`
19022
19726
  Agent setup written for ${profile.company_name || "NTRP"}.
19023
19727
  `));
19024
19728
  return;
@@ -19030,7 +19734,7 @@ async function handler25(args, ctx) {
19030
19734
  if (isStructuredOutput(ctx.execution)) {
19031
19735
  emitError("setup", err);
19032
19736
  }
19033
- console.error(chalk39.red(String(err)));
19737
+ console.error(chalk41.red(String(err)));
19034
19738
  process.exit(err instanceof NtrpError ? err.exitCode : 1);
19035
19739
  }
19036
19740
  }
@@ -19046,25 +19750,25 @@ var init_setup2 = __esm({
19046
19750
  });
19047
19751
 
19048
19752
  // src/conversation/orchestrator.ts
19049
- import chalk40 from "chalk";
19753
+ import chalk42 from "chalk";
19050
19754
  import { writeFileSync as writeFileSync12 } from "fs";
19051
19755
  import { join as join17 } from "path";
19052
19756
  function printScopeProposal(ctx) {
19053
19757
  if (!ctx.scope) return;
19054
19758
  const lens = ctx.scope.primary_lens === "revenue_metrics" ? "SaaS metrics" : "pipeline health";
19055
19759
  console.log();
19056
- console.log(" " + chalk40.bold("Proposed focus"));
19057
- console.log(" " + chalk40.dim(`Lens: `) + paint("accent", lens));
19058
- console.log(" " + chalk40.dim(`Intent: ${ctx.scope.intent_summary}`));
19760
+ console.log(" " + chalk42.bold("Proposed focus"));
19761
+ console.log(" " + chalk42.dim(`Lens: `) + paint("accent", lens));
19762
+ console.log(" " + chalk42.dim(`Intent: ${ctx.scope.intent_summary}`));
19059
19763
  if (ctx.scope.audience) {
19060
- console.log(" " + chalk40.dim(`Audience: ${ctx.scope.audience}`));
19764
+ console.log(" " + chalk42.dim(`Audience: ${ctx.scope.audience}`));
19061
19765
  }
19062
19766
  if (ctx.scope.time_horizon) {
19063
- console.log(" " + chalk40.dim(`Period: ${ctx.scope.time_horizon}`));
19767
+ console.log(" " + chalk42.dim(`Period: ${ctx.scope.time_horizon}`));
19064
19768
  }
19065
19769
  console.log();
19066
19770
  console.log(
19067
- " " + chalk40.dim("Confirm? ") + chalk40.cyan("yes") + chalk40.dim(" \xB7 ") + chalk40.cyan("adjust")
19771
+ " " + chalk42.dim("Confirm? ") + chalk42.cyan("yes") + chalk42.dim(" \xB7 ") + chalk42.cyan("adjust")
19068
19772
  );
19069
19773
  console.log();
19070
19774
  }
@@ -19075,7 +19779,7 @@ async function handleDeterministic(input, ctx) {
19075
19779
  if (!ctx[ORIENT_HINT_PRINTED]) {
19076
19780
  console.log();
19077
19781
  console.log(
19078
- " " + chalk40.dim("What do you want to look at? ") + chalk40.dim('(e.g. "pipeline health", "is NRR real?", "board deck on Q3")')
19782
+ " " + chalk42.dim("What do you want to look at? ") + chalk42.dim('(e.g. "pipeline health", "is NRR real?", "board deck on Q3")')
19079
19783
  );
19080
19784
  console.log();
19081
19785
  ctx[ORIENT_HINT_PRINTED] = true;
@@ -19088,7 +19792,7 @@ async function handleDeterministic(input, ctx) {
19088
19792
  saveSessionState(ctx);
19089
19793
  recordMessage(ctx, "user", line);
19090
19794
  if (proposal.clarifying_question) {
19091
- console.log(" " + chalk40.dim(proposal.clarifying_question));
19795
+ console.log(" " + chalk42.dim(proposal.clarifying_question));
19092
19796
  recordMessage(ctx, "agent", proposal.clarifying_question);
19093
19797
  return "Scope proposed";
19094
19798
  }
@@ -19100,7 +19804,7 @@ async function handleDeterministic(input, ctx) {
19100
19804
  recordMessage(ctx, "user", line);
19101
19805
  if (isScopeAdjustInput(line)) {
19102
19806
  console.log();
19103
- console.log(" " + chalk40.dim("What should we focus on instead?"));
19807
+ console.log(" " + chalk42.dim("What should we focus on instead?"));
19104
19808
  ctx.scope = void 0;
19105
19809
  saveSessionState(ctx);
19106
19810
  return "Scope cleared";
@@ -19173,25 +19877,25 @@ async function handleDeliverFlow(input, ctx) {
19173
19877
  const draft = await buildDeliverableDraft(ctx, target);
19174
19878
  if (!draft) {
19175
19879
  console.log();
19176
- console.log(" " + chalk40.red("Nothing to ship yet \u2014 load data and run analysis first."));
19880
+ console.log(" " + chalk42.red("Nothing to ship yet \u2014 load data and run analysis first."));
19177
19881
  console.log();
19178
19882
  ctx.deliverIntent = false;
19179
19883
  return;
19180
19884
  }
19181
19885
  console.log();
19182
- console.log(" " + chalk40.bold("Deliverable preview"));
19183
- console.log(" " + chalk40.dim("\u2500".repeat(56)));
19886
+ console.log(" " + chalk42.bold("Deliverable preview"));
19887
+ console.log(" " + chalk42.dim("\u2500".repeat(56)));
19184
19888
  const preview = draft.markdown.split("\n").slice(0, 24);
19185
19889
  for (const l of preview) {
19186
- console.log(" " + chalk40.dim(l));
19890
+ console.log(" " + chalk42.dim(l));
19187
19891
  }
19188
19892
  if (draft.markdown.split("\n").length > 24) {
19189
- console.log(" " + chalk40.dim("\u2026"));
19893
+ console.log(" " + chalk42.dim("\u2026"));
19190
19894
  }
19191
- console.log(" " + chalk40.dim("\u2500".repeat(56)));
19895
+ console.log(" " + chalk42.dim("\u2500".repeat(56)));
19192
19896
  console.log();
19193
19897
  if (!ctx.rl) {
19194
- console.log(" " + chalk40.dim("Run interactively to confirm write."));
19898
+ console.log(" " + chalk42.dim("Run interactively to confirm write."));
19195
19899
  return;
19196
19900
  }
19197
19901
  const prompts = createPromptSession(ctx.rl, ctx);
@@ -19199,7 +19903,7 @@ async function handleDeliverFlow(input, ctx) {
19199
19903
  const ok = await prompts.confirm("Write handoff prompt to exports and mark delivered?", true);
19200
19904
  if (!ok) {
19201
19905
  ctx.deliverIntent = false;
19202
- console.log(" " + chalk40.dim("Kept as preview only \u2014 session not marked delivered."));
19906
+ console.log(" " + chalk42.dim("Kept as preview only \u2014 session not marked delivered."));
19203
19907
  return "Preview only";
19204
19908
  }
19205
19909
  } finally {
@@ -19219,8 +19923,8 @@ async function handleDeliverFlow(input, ctx) {
19219
19923
  saveSessionState(ctx);
19220
19924
  console.log();
19221
19925
  console.log(" " + paint("accent", `Handoff prompt ready (${target})`));
19222
- console.log(" " + chalk40.dim(out));
19223
- console.log(" " + chalk40.dim("Paste into another agent to build the deliverable."));
19926
+ console.log(" " + chalk42.dim(out));
19927
+ console.log(" " + chalk42.dim("Paste into another agent to build the deliverable."));
19224
19928
  console.log();
19225
19929
  recordMessage(ctx, "user", input);
19226
19930
  recordMessage(ctx, "agent", `Wrote ${target} handoff prompt to ${out}`);
@@ -19228,11 +19932,11 @@ async function handleDeliverFlow(input, ctx) {
19228
19932
  }
19229
19933
  async function handleExploreWithoutKey(ctx) {
19230
19934
  console.log();
19231
- console.log(" " + chalk40.red("AI interpretation needs an LLM API key saved in config."));
19935
+ console.log(" " + chalk42.red("AI interpretation needs an LLM API key saved in config."));
19232
19936
  console.log(
19233
- " " + chalk40.dim("Set with: ") + paint("accent", "/config set api-key") + chalk40.dim(" (Anthropic) or ") + paint("accent", "/config set openai-api-key")
19937
+ " " + chalk42.dim("Set with: ") + paint("accent", "/config set api-key") + chalk42.dim(" (Anthropic) or ") + paint("accent", "/config set openai-api-key")
19234
19938
  );
19235
- console.log(" " + chalk40.dim("Number crunching works without a key \u2014 only Q&A in the REPL needs one."));
19939
+ console.log(" " + chalk42.dim("Number crunching works without a key \u2014 only Q&A in the REPL needs one."));
19236
19940
  if (ctx.gapAudit) {
19237
19941
  printGapCard(ctx.gapAudit);
19238
19942
  }
@@ -19999,7 +20703,7 @@ __export(nl_exports, {
19999
20703
  runNaturalLanguage: () => runNaturalLanguage
20000
20704
  });
20001
20705
  import ora10 from "ora";
20002
- import chalk41 from "chalk";
20706
+ import chalk43 from "chalk";
20003
20707
  async function runNaturalLanguage(input, ctx) {
20004
20708
  if (isSmokeProtocolTrigger(input)) {
20005
20709
  recordMessage(ctx, "user", input);
@@ -20014,7 +20718,7 @@ async function runNaturalLanguage(input, ctx) {
20014
20718
  return extractSummary(result.answer);
20015
20719
  } catch (err) {
20016
20720
  spinner2.fail("Smoke protocol failed");
20017
- console.error(" " + chalk41.red(String(err.message ?? err)));
20721
+ console.error(" " + chalk43.red(String(err.message ?? err)));
20018
20722
  console.log();
20019
20723
  return;
20020
20724
  }
@@ -20048,8 +20752,8 @@ async function runNaturalLanguage(input, ctx) {
20048
20752
  spinner2.succeed(metricsFirst ? "Session context ready" : "Health snapshot ready");
20049
20753
  } catch (err) {
20050
20754
  spinner2.fail("Could not compute health snapshot");
20051
- console.error(" " + chalk41.red(String(err.message ?? err)));
20052
- console.log(" " + chalk41.dim("Run ") + paint("accent", "/new") + chalk41.dim(" \u2192 pick Demo to load sample data."));
20755
+ console.error(" " + chalk43.red(String(err.message ?? err)));
20756
+ console.log(" " + chalk43.dim("Run ") + paint("accent", "/new") + chalk43.dim(" \u2192 pick Demo to load sample data."));
20053
20757
  console.log();
20054
20758
  return;
20055
20759
  }
@@ -20087,7 +20791,7 @@ async function runNaturalLanguage(input, ctx) {
20087
20791
  break;
20088
20792
  case "thinking":
20089
20793
  spinner.stop();
20090
- console.log(" " + chalk41.dim.italic(event.text));
20794
+ console.log(" " + chalk43.dim.italic(event.text));
20091
20795
  spinner.start("Thinking\u2026");
20092
20796
  break;
20093
20797
  case "answer":
@@ -20107,7 +20811,7 @@ async function runNaturalLanguage(input, ctx) {
20107
20811
  }
20108
20812
  } catch (err) {
20109
20813
  spinner.fail("Error while investigating");
20110
- console.error(" " + chalk41.red(String(err.message ?? err)));
20814
+ console.error(" " + chalk43.red(String(err.message ?? err)));
20111
20815
  console.log();
20112
20816
  return;
20113
20817
  } finally {
@@ -20117,7 +20821,7 @@ async function runNaturalLanguage(input, ctx) {
20117
20821
  ctx.conversation = distillThread(rawHistory);
20118
20822
  }
20119
20823
  if (!lastAnswer) {
20120
- console.log(" " + chalk41.dim("(no answer returned)"));
20824
+ console.log(" " + chalk43.dim("(no answer returned)"));
20121
20825
  } else {
20122
20826
  recordMessage(ctx, "agent", lastAnswer);
20123
20827
  saveSessionState(ctx);
@@ -20140,12 +20844,12 @@ function extractSummary(text) {
20140
20844
  }
20141
20845
  function printFindingInline(finding) {
20142
20846
  const sev = finding.severity;
20143
- const color = sev === "critical" ? chalk41.red : sev === "warning" ? chalk41.yellow : chalk41.blue;
20847
+ const color = sev === "critical" ? chalk43.red : sev === "warning" ? chalk43.yellow : chalk43.blue;
20144
20848
  console.log();
20145
- console.log(" " + color(`[${sev}]`) + " " + chalk41.bold(finding.segment));
20849
+ console.log(" " + color(`[${sev}]`) + " " + chalk43.bold(finding.segment));
20146
20850
  printMarkdown(finding.finding, { indent: 2 });
20147
20851
  const play = finding.recommended_plays?.[0];
20148
- if (play) console.log(" " + chalk41.dim("\u2192 " + play.play_name + " \u2014 " + play.rationale));
20852
+ if (play) console.log(" " + chalk43.dim("\u2192 " + play.play_name + " \u2014 " + play.rationale));
20149
20853
  }
20150
20854
  var init_nl = __esm({
20151
20855
  "src/cli/nl.ts"() {
@@ -20269,21 +20973,21 @@ var init_ask = __esm({
20269
20973
  // src/commands/ask.ts
20270
20974
  var ask_exports = {};
20271
20975
  __export(ask_exports, {
20272
- handler: () => handler26
20976
+ handler: () => handler28
20273
20977
  });
20274
- import chalk42 from "chalk";
20275
- async function handler26(args, ctx) {
20978
+ import chalk44 from "chalk";
20979
+ async function handler28(args, ctx) {
20276
20980
  const question = args.join(" ").trim();
20277
20981
  if (!question) {
20278
20982
  if (isStructuredOutput(ctx.execution)) {
20279
20983
  emitError("ask", new NtrpError("question_required", "Ask requires a question.", 2 /* Usage */));
20280
20984
  }
20281
20985
  console.log();
20282
- console.log(" " + chalk42.dim("Ask a question about your pipeline in plain English."));
20986
+ console.log(" " + chalk44.dim("Ask a question about your pipeline in plain English."));
20283
20987
  console.log(
20284
- " " + chalk42.dim("Example: ") + paint("accent", "/ask which deals are stuck the longest?")
20988
+ " " + chalk44.dim("Example: ") + paint("accent", "/ask which deals are stuck the longest?")
20285
20989
  );
20286
- console.log(" " + chalk42.dim("Or just type your question at the prompt \u2014 no slash needed."));
20990
+ console.log(" " + chalk44.dim("Or just type your question at the prompt \u2014 no slash needed."));
20287
20991
  console.log();
20288
20992
  return;
20289
20993
  }
@@ -20295,8 +20999,8 @@ async function handler26(args, ctx) {
20295
20999
  return;
20296
21000
  }
20297
21001
  console.log();
20298
- console.log(" " + chalk42.red("Ask runs only in the interactive REPL."));
20299
- console.log(" " + chalk42.dim("Start with ") + paint("accent", "ntrp") + chalk42.dim(", set LLM keys via /config, then ask in plain English."));
21002
+ console.log(" " + chalk44.red("Ask runs only in the interactive REPL."));
21003
+ console.log(" " + chalk44.dim("Start with ") + paint("accent", "ntrp") + chalk44.dim(", set LLM keys via /config, then ask in plain English."));
20300
21004
  console.log();
20301
21005
  return;
20302
21006
  }
@@ -20342,20 +21046,20 @@ var init_ask2 = __esm({
20342
21046
  // src/commands/metrics.ts
20343
21047
  var metrics_exports = {};
20344
21048
  __export(metrics_exports, {
20345
- handler: () => handler27
21049
+ handler: () => handler29
20346
21050
  });
20347
- import chalk43 from "chalk";
21051
+ import chalk45 from "chalk";
20348
21052
  import ora11 from "ora";
20349
- async function handler27(args, ctx) {
21053
+ async function handler29(args, ctx) {
20350
21054
  await hydrateAnalysisFromPersistedState(ctx);
20351
21055
  const { flags } = parseArgs2(args, ["findings"]);
20352
21056
  const segmentFilter = getString(flags, "segment");
20353
21057
  const withFindings = getBool(flags, "findings");
20354
21058
  if (withFindings && !canUseReplAi(ctx)) {
20355
21059
  console.log();
20356
- console.log(" " + chalk43.red("AI findings run only in the interactive REPL."));
20357
- console.log(" " + chalk43.dim("Metrics numbers compute without a key \u2014 omit --findings for numbers only."));
20358
- console.log(" " + chalk43.dim("Start with ") + paint("accent", "ntrp") + chalk43.dim(", set LLM keys via /config, then /metrics --findings."));
21060
+ console.log(" " + chalk45.red("AI findings run only in the interactive REPL."));
21061
+ console.log(" " + chalk45.dim("Metrics numbers compute without a key \u2014 omit --findings for numbers only."));
21062
+ console.log(" " + chalk45.dim("Start with ") + paint("accent", "ntrp") + chalk45.dim(", set LLM keys via /config, then /metrics --findings."));
20359
21063
  console.log();
20360
21064
  return;
20361
21065
  }
@@ -20421,7 +21125,7 @@ async function handler27(args, ctx) {
20421
21125
  }
20422
21126
  } else if (segmentFilter) {
20423
21127
  console.log();
20424
- console.log(chalk43.red(` No segment matching "${segmentFilter}".`));
21128
+ console.log(chalk45.red(` No segment matching "${segmentFilter}".`));
20425
21129
  console.log();
20426
21130
  } else {
20427
21131
  renderMetricsReport(ctx, result.metrics.aggregate.metrics, result.coverage, result.data_source_type, {
@@ -20433,7 +21137,7 @@ async function handler27(args, ctx) {
20433
21137
  }
20434
21138
  } catch (err) {
20435
21139
  spinner.fail("Metrics computation failed");
20436
- console.error(chalk43.red(String(err)));
21140
+ console.error(chalk45.red(String(err)));
20437
21141
  process.exit(1);
20438
21142
  }
20439
21143
  }
@@ -20581,17 +21285,17 @@ OUTPUT FORMAT \u2014 STRICT JSON only, no preamble, no markdown fences:
20581
21285
  // src/commands/feedback.ts
20582
21286
  var feedback_exports = {};
20583
21287
  __export(feedback_exports, {
20584
- handler: () => handler28
21288
+ handler: () => handler30
20585
21289
  });
20586
- import chalk44 from "chalk";
21290
+ import chalk46 from "chalk";
20587
21291
  import ora12 from "ora";
20588
- async function handler28(args, ctx) {
21292
+ async function handler30(args, ctx) {
20589
21293
  const feedbackText = args.join(" ").trim();
20590
21294
  if (!feedbackText) {
20591
21295
  console.log();
20592
- console.log(" " + chalk44.dim("Tell NTRP something it got wrong or doesn't know yet."));
21296
+ console.log(" " + chalk46.dim("Tell NTRP something it got wrong or doesn't know yet."));
20593
21297
  console.log(
20594
- " " + chalk44.dim("Example: ") + paint("accent", '/feedback "We have SDRs, not BDRs"')
21298
+ " " + chalk46.dim("Example: ") + paint("accent", '/feedback "We have SDRs, not BDRs"')
20595
21299
  );
20596
21300
  console.log();
20597
21301
  return;
@@ -20599,8 +21303,8 @@ async function handler28(args, ctx) {
20599
21303
  const profile = loadProfile();
20600
21304
  if (!profile) {
20601
21305
  console.log();
20602
- console.log(" " + chalk44.red("No company profile found."));
20603
- console.log(" " + chalk44.dim("Run ") + paint("accent", "/onboard") + chalk44.dim(" first to create one."));
21306
+ console.log(" " + chalk46.red("No company profile found."));
21307
+ console.log(" " + chalk46.dim("Run ") + paint("accent", "/onboard") + chalk46.dim(" first to create one."));
20604
21308
  console.log();
20605
21309
  return;
20606
21310
  }
@@ -20608,7 +21312,7 @@ async function handler28(args, ctx) {
20608
21312
  assertReplAi(ctx);
20609
21313
  } catch (err) {
20610
21314
  console.log();
20611
- console.log(" " + chalk44.red(String(err.message ?? err)));
21315
+ console.log(" " + chalk46.red(String(err.message ?? err)));
20612
21316
  console.log();
20613
21317
  return;
20614
21318
  }
@@ -20624,7 +21328,7 @@ async function handler28(args, ctx) {
20624
21328
  ${result.change_summary}`);
20625
21329
  } catch (err) {
20626
21330
  spinner.fail("Couldn't apply feedback");
20627
- console.log(" " + chalk44.dim(String(err.message ?? err)));
21331
+ console.log(" " + chalk46.dim(String(err.message ?? err)));
20628
21332
  }
20629
21333
  }
20630
21334
  var init_feedback = __esm({
@@ -20642,15 +21346,15 @@ var init_feedback = __esm({
20642
21346
  // src/commands/recap.ts
20643
21347
  var recap_exports = {};
20644
21348
  __export(recap_exports, {
20645
- handler: () => handler29
21349
+ handler: () => handler31
20646
21350
  });
20647
21351
  import ora13 from "ora";
20648
- import chalk45 from "chalk";
20649
- async function handler29(_args, ctx) {
21352
+ import chalk47 from "chalk";
21353
+ async function handler31(_args, ctx) {
20650
21354
  if (ctx.messages.length === 0) {
20651
21355
  console.log();
20652
- console.log(" " + chalk45.dim("Nothing to recap \u2014 no NL exchanges this session."));
20653
- console.log(" " + chalk45.dim("Ask a plain-English question first, then run /recap."));
21356
+ console.log(" " + chalk47.dim("Nothing to recap \u2014 no NL exchanges this session."));
21357
+ console.log(" " + chalk47.dim("Ask a plain-English question first, then run /recap."));
20654
21358
  console.log();
20655
21359
  return;
20656
21360
  }
@@ -20658,7 +21362,7 @@ async function handler29(_args, ctx) {
20658
21362
  assertReplAi(ctx);
20659
21363
  } catch (err) {
20660
21364
  console.log();
20661
- console.log(" " + chalk45.red(String(err.message ?? err)));
21365
+ console.log(" " + chalk47.red(String(err.message ?? err)));
20662
21366
  console.log();
20663
21367
  return;
20664
21368
  }
@@ -20700,7 +21404,7 @@ ${conversationLines.join("\n\n")}`,
20700
21404
  return `${exchangeCount} exchange${exchangeCount === 1 ? "" : "s"} summarized`;
20701
21405
  } catch (err) {
20702
21406
  spinner.fail("Recap failed");
20703
- console.error(" " + chalk45.red(String(err.message ?? err)));
21407
+ console.error(" " + chalk47.red(String(err.message ?? err)));
20704
21408
  console.log();
20705
21409
  }
20706
21410
  }
@@ -20717,16 +21421,16 @@ var init_recap = __esm({
20717
21421
  // src/commands/remember.ts
20718
21422
  var remember_exports = {};
20719
21423
  __export(remember_exports, {
20720
- handler: () => handler30
21424
+ handler: () => handler32
20721
21425
  });
20722
- import chalk46 from "chalk";
20723
- async function handler30(args, ctx) {
21426
+ import chalk48 from "chalk";
21427
+ async function handler32(args, ctx) {
20724
21428
  let text = args.join(" ").trim();
20725
21429
  if (!text) {
20726
21430
  console.log();
20727
- console.log(" " + chalk46.dim("Teach me something durable about the business."));
20728
- console.log(" " + chalk46.dim("Example: ") + paint("accent", "/remember we only sell to FinServ above 500 employees"));
20729
- console.log(" " + chalk46.dim("Prefix with ") + paint("accent", "decision:") + chalk46.dim(" or ") + paint("accent", "preference:") + chalk46.dim(" to tag it."));
21431
+ console.log(" " + chalk48.dim("Teach me something durable about the business."));
21432
+ console.log(" " + chalk48.dim("Example: ") + paint("accent", "/remember we only sell to FinServ above 500 employees"));
21433
+ console.log(" " + chalk48.dim("Prefix with ") + paint("accent", "decision:") + chalk48.dim(" or ") + paint("accent", "preference:") + chalk48.dim(" to tag it."));
20730
21434
  console.log();
20731
21435
  return;
20732
21436
  }
@@ -20738,8 +21442,8 @@ async function handler30(args, ctx) {
20738
21442
  }
20739
21443
  const fact = addFact({ text, kind, source: "user", session_id: ctx.sessionId });
20740
21444
  console.log();
20741
- console.log(" " + paint("accent", "Noted.") + " " + chalk46.dim(`I'll carry this into future analyses${kind !== "fact" ? ` (${kind})` : ""}.`));
20742
- console.log(" " + chalk46.dim("\u2022 " + fact.text));
21445
+ console.log(" " + paint("accent", "Noted.") + " " + chalk48.dim(`I'll carry this into future analyses${kind !== "fact" ? ` (${kind})` : ""}.`));
21446
+ console.log(" " + chalk48.dim("\u2022 " + fact.text));
20743
21447
  console.log();
20744
21448
  return "Saved to memory";
20745
21449
  }
@@ -20754,16 +21458,16 @@ var init_remember = __esm({
20754
21458
  // src/commands/recall.ts
20755
21459
  var recall_exports = {};
20756
21460
  __export(recall_exports, {
20757
- handler: () => handler31
21461
+ handler: () => handler33
20758
21462
  });
20759
- import chalk47 from "chalk";
20760
- async function handler31(args, _ctx) {
21463
+ import chalk49 from "chalk";
21464
+ async function handler33(args, _ctx) {
20761
21465
  const query = args.join(" ").trim();
20762
21466
  if (query) {
20763
21467
  const block = await buildMemoryBlock(query, { maxFacts: 6, maxLedger: 5, maxStrategies: 3, maxWins: 3, maxKnowledge: 3 });
20764
21468
  console.log();
20765
21469
  if (!block) {
20766
- console.log(" " + chalk47.dim(`Nothing in memory about "${query}" yet.`));
21470
+ console.log(" " + chalk49.dim(`Nothing in memory about "${query}" yet.`));
20767
21471
  console.log();
20768
21472
  return;
20769
21473
  }
@@ -20777,22 +21481,22 @@ async function handler31(args, _ctx) {
20777
21481
  const ledger = listLedger().slice(-8).reverse();
20778
21482
  console.log();
20779
21483
  if (facts.length === 0 && ledger.length === 0) {
20780
- console.log(" " + chalk47.dim("Memory is empty. Teach me with ") + paint("accent", "/remember <fact>") + chalk47.dim("."));
21484
+ console.log(" " + chalk49.dim("Memory is empty. Teach me with ") + paint("accent", "/remember <fact>") + chalk49.dim("."));
20781
21485
  console.log();
20782
21486
  return;
20783
21487
  }
20784
21488
  if (facts.length > 0) {
20785
21489
  console.log(" " + paint("accent", "What I know about your business"));
20786
21490
  for (const f of facts) {
20787
- const tag = f.kind !== "fact" ? chalk47.dim(` (${f.kind})`) : "";
20788
- console.log(" " + chalk47.dim("\u2022 ") + f.text + tag);
21491
+ const tag = f.kind !== "fact" ? chalk49.dim(` (${f.kind})`) : "";
21492
+ console.log(" " + chalk49.dim("\u2022 ") + f.text + tag);
20789
21493
  }
20790
21494
  console.log();
20791
21495
  }
20792
21496
  if (ledger.length > 0) {
20793
21497
  console.log(" " + paint("accent", "Analyses I've already run"));
20794
21498
  for (const l of ledger) {
20795
- console.log(" " + chalk47.dim("\u2022 ") + chalk47.dim(`${l.question} \u2192 ${l.summary}`));
21499
+ console.log(" " + chalk49.dim("\u2022 ") + chalk49.dim(`${l.question} \u2192 ${l.summary}`));
20796
21500
  }
20797
21501
  console.log();
20798
21502
  }
@@ -20856,29 +21560,29 @@ var init_feedback2 = __esm({
20856
21560
  // src/commands/rate.ts
20857
21561
  var rate_exports = {};
20858
21562
  __export(rate_exports, {
20859
- handler: () => handler32
21563
+ handler: () => handler34
20860
21564
  });
20861
- import chalk48 from "chalk";
20862
- async function handler32(args, ctx) {
21565
+ import chalk50 from "chalk";
21566
+ async function handler34(args, ctx) {
20863
21567
  const verdict = (args[0] ?? "").toLowerCase();
20864
21568
  const note = args.slice(1).join(" ").trim();
20865
21569
  if (!verdict || !POSITIVE.has(verdict) && !NEGATIVE.has(verdict)) {
20866
21570
  console.log();
20867
- console.log(" " + chalk48.dim("Tell me how the last answer landed so I improve."));
20868
- console.log(" " + paint("accent", "/rate good") + chalk48.dim(" or ") + paint("accent", "/rate bad <what was off>"));
21571
+ console.log(" " + chalk50.dim("Tell me how the last answer landed so I improve."));
21572
+ console.log(" " + paint("accent", "/rate good") + chalk50.dim(" or ") + paint("accent", "/rate bad <what was off>"));
20869
21573
  console.log();
20870
21574
  return;
20871
21575
  }
20872
21576
  if (!ctx.lastExchange) {
20873
21577
  console.log();
20874
- console.log(" " + chalk48.dim("Nothing to rate yet \u2014 ask a question first, then rate the answer."));
21578
+ console.log(" " + chalk50.dim("Nothing to rate yet \u2014 ask a question first, then rate the answer."));
20875
21579
  console.log();
20876
21580
  return;
20877
21581
  }
20878
21582
  const rating = POSITIVE.has(verdict) ? "positive" : "negative";
20879
21583
  if (rating === "negative" && !note) {
20880
21584
  console.log();
20881
- console.log(" " + chalk48.yellow("Add a quick note so I know what to fix:"));
21585
+ console.log(" " + chalk50.yellow("Add a quick note so I know what to fix:"));
20882
21586
  console.log(" " + paint("accent", "/rate bad you ignored the enterprise segment"));
20883
21587
  console.log();
20884
21588
  return;
@@ -20892,9 +21596,9 @@ async function handler32(args, ctx) {
20892
21596
  });
20893
21597
  console.log();
20894
21598
  if (rating === "positive") {
20895
- console.log(" " + paint("accent", "Noted \u2014 glad that helped.") + " " + chalk48.dim("I'll keep that approach for similar questions."));
21599
+ console.log(" " + paint("accent", "Noted \u2014 glad that helped.") + " " + chalk50.dim("I'll keep that approach for similar questions."));
20896
21600
  } else {
20897
- console.log(" " + paint("accent", "Got it \u2014 thank you.") + " " + chalk48.dim("I'll adjust and won't repeat that."));
21601
+ console.log(" " + paint("accent", "Got it \u2014 thank you.") + " " + chalk50.dim("I'll adjust and won't repeat that."));
20898
21602
  }
20899
21603
  console.log();
20900
21604
  return rating === "positive" ? "Feedback: helpful" : "Feedback: needs adjustment";
@@ -20913,18 +21617,18 @@ var init_rate = __esm({
20913
21617
  // src/commands/knowledge.ts
20914
21618
  var knowledge_exports = {};
20915
21619
  __export(knowledge_exports, {
20916
- handler: () => handler33
21620
+ handler: () => handler35
20917
21621
  });
20918
- import chalk49 from "chalk";
21622
+ import chalk51 from "chalk";
20919
21623
  import ora14 from "ora";
20920
- async function handler33(args, ctx) {
21624
+ async function handler35(args, ctx) {
20921
21625
  const sub = (args[0] ?? "list").toLowerCase();
20922
21626
  if (sub === "add") {
20923
21627
  const path = args.slice(1).join(" ").trim();
20924
21628
  if (!path) {
20925
21629
  console.log();
20926
- console.log(" " + chalk49.red("knowledge add requires a file path."));
20927
- console.log(" " + chalk49.dim("Example: ") + paint("accent", "/knowledge add ~/Downloads/plg-benchmarks-2026.pdf"));
21630
+ console.log(" " + chalk51.red("knowledge add requires a file path."));
21631
+ console.log(" " + chalk51.dim("Example: ") + paint("accent", "/knowledge add ~/Downloads/plg-benchmarks-2026.pdf"));
20928
21632
  console.log();
20929
21633
  return;
20930
21634
  }
@@ -20933,12 +21637,12 @@ async function handler33(args, ctx) {
20933
21637
  const result = await addKnowledgeFile(path);
20934
21638
  spin?.succeed(`Indexed "${result.title}"`);
20935
21639
  console.log();
20936
- console.log(" " + chalk49.dim(`${result.chunks} passage${result.chunks === 1 ? "" : "s"} indexed and available to the analyst.`));
21640
+ console.log(" " + chalk51.dim(`${result.chunks} passage${result.chunks === 1 ? "" : "s"} indexed and available to the analyst.`));
20937
21641
  console.log();
20938
21642
  return `Indexed ${result.chunks} passages`;
20939
21643
  } catch (err) {
20940
21644
  spin?.fail("Knowledge ingest failed");
20941
- console.error(" " + chalk49.red(String(err.message ?? err)));
21645
+ console.error(" " + chalk51.red(String(err.message ?? err)));
20942
21646
  console.log();
20943
21647
  return;
20944
21648
  }
@@ -20948,26 +21652,26 @@ async function handler33(args, ctx) {
20948
21652
  const staged = listKnowledgeDirFiles(getKnowledgeDir());
20949
21653
  console.log();
20950
21654
  if (docs.length === 0) {
20951
- console.log(" " + chalk49.dim("No knowledge indexed yet."));
21655
+ console.log(" " + chalk51.dim("No knowledge indexed yet."));
20952
21656
  } else {
20953
21657
  console.log(" " + paint("accent", "Indexed Knowledge"));
20954
21658
  for (const d of docs) {
20955
21659
  console.log(
20956
- " " + chalk49.dim("\u2022 ") + chalk49.bold(d.title) + chalk49.dim(` (${d.chunks} passage${d.chunks === 1 ? "" : "s"}${d.source_path ? `, ${d.source_path.split("/").pop()}` : ""})`)
21660
+ " " + chalk51.dim("\u2022 ") + chalk51.bold(d.title) + chalk51.dim(` (${d.chunks} passage${d.chunks === 1 ? "" : "s"}${d.source_path ? `, ${d.source_path.split("/").pop()}` : ""})`)
20957
21661
  );
20958
21662
  }
20959
21663
  }
20960
21664
  if (staged.length > 0) {
20961
21665
  console.log();
20962
- console.log(" " + chalk49.dim("Staged in ~/.ntrp/knowledge (run ") + paint("accent", "/knowledge add <file>") + chalk49.dim(" to index):"));
20963
- for (const f of staged) console.log(" " + chalk49.dim(" - " + f));
21666
+ console.log(" " + chalk51.dim("Staged in ~/.ntrp/knowledge (run ") + paint("accent", "/knowledge add <file>") + chalk51.dim(" to index):"));
21667
+ for (const f of staged) console.log(" " + chalk51.dim(" - " + f));
20964
21668
  }
20965
21669
  console.log();
20966
21670
  return `${docs.length} doc${docs.length === 1 ? "" : "s"} indexed`;
20967
21671
  }
20968
21672
  console.log();
20969
- console.log(" " + chalk49.red(`Unknown knowledge subcommand: ${sub}`));
20970
- console.log(" " + chalk49.dim("Use ") + paint("accent", "/knowledge add <file>") + chalk49.dim(" or ") + paint("accent", "/knowledge list") + chalk49.dim("."));
21673
+ console.log(" " + chalk51.red(`Unknown knowledge subcommand: ${sub}`));
21674
+ console.log(" " + chalk51.dim("Use ") + paint("accent", "/knowledge add <file>") + chalk51.dim(" or ") + paint("accent", "/knowledge list") + chalk51.dim("."));
20971
21675
  console.log();
20972
21676
  return;
20973
21677
  }
@@ -20983,10 +21687,10 @@ var init_knowledge2 = __esm({
20983
21687
  // src/commands/sessions.ts
20984
21688
  var sessions_exports = {};
20985
21689
  __export(sessions_exports, {
20986
- handler: () => handler34
21690
+ handler: () => handler36
20987
21691
  });
20988
- import chalk50 from "chalk";
20989
- async function handler34(args, _ctx) {
21692
+ import chalk52 from "chalk";
21693
+ async function handler36(args, _ctx) {
20990
21694
  const sub = args[0] ?? "list";
20991
21695
  if (sub === "list" || !args[0]) {
20992
21696
  return showList();
@@ -20995,8 +21699,8 @@ async function handler34(args, _ctx) {
20995
21699
  const idArg = args[1];
20996
21700
  if (!idArg) {
20997
21701
  console.log();
20998
- console.log(" " + chalk50.red("Usage: /sessions show <id>"));
20999
- console.log(" " + chalk50.dim("Use a full session ID or 4-char suffix."));
21702
+ console.log(" " + chalk52.red("Usage: /sessions show <id>"));
21703
+ console.log(" " + chalk52.dim("Use a full session ID or 4-char suffix."));
21000
21704
  console.log();
21001
21705
  return;
21002
21706
  }
@@ -21008,24 +21712,24 @@ function showList() {
21008
21712
  const sessions = listSessions({ limit: 10 });
21009
21713
  if (sessions.length === 0) {
21010
21714
  console.log();
21011
- console.log(" " + chalk50.dim("No sessions yet. Ask a question to start your first session."));
21715
+ console.log(" " + chalk52.dim("No sessions yet. Ask a question to start your first session."));
21012
21716
  console.log();
21013
21717
  return;
21014
21718
  }
21015
21719
  console.log();
21016
21720
  console.log(" " + paint("accent", bold("Session History")));
21017
- console.log(" " + chalk50.dim("\u2500".repeat(58)));
21721
+ console.log(" " + chalk52.dim("\u2500".repeat(58)));
21018
21722
  for (const s of sessions) {
21019
21723
  const date = s.created_at?.slice(0, 10) ?? s.id.slice(0, 10);
21020
21724
  const shortId = s.id.slice(-4);
21021
21725
  const nameTag = s.name ? paint("accent", `[${s.name}]`) + " " : "";
21022
- const summary = s.summary ?? chalk50.dim("(no summary)");
21023
- const exch = chalk50.dim(`${s.exchange_count} exch.`);
21024
- console.log(` ${chalk50.dim(date)} ${shortId} ${nameTag}${padRight(summary, 36)} ${exch}`);
21726
+ const summary = s.summary ?? chalk52.dim("(no summary)");
21727
+ const exch = chalk52.dim(`${s.exchange_count} exch.`);
21728
+ console.log(` ${chalk52.dim(date)} ${shortId} ${nameTag}${padRight(summary, 36)} ${exch}`);
21025
21729
  }
21026
- console.log(" " + chalk50.dim("\u2500".repeat(58)));
21730
+ console.log(" " + chalk52.dim("\u2500".repeat(58)));
21027
21731
  console.log(
21028
- " " + chalk50.dim(`${sessions.length} session${sessions.length === 1 ? "" : "s"} \xB7 `) + paint("accent", "/sessions show <id>") + chalk50.dim(" to review \xB7 ") + paint("accent", "/resume") + chalk50.dim(" to continue")
21732
+ " " + chalk52.dim(`${sessions.length} session${sessions.length === 1 ? "" : "s"} \xB7 `) + paint("accent", "/sessions show <id>") + chalk52.dim(" to review \xB7 ") + paint("accent", "/resume") + chalk52.dim(" to continue")
21029
21733
  );
21030
21734
  console.log();
21031
21735
  return `${sessions.length} session${sessions.length === 1 ? "" : "s"} listed`;
@@ -21038,18 +21742,18 @@ function showSession(idArg) {
21038
21742
  }
21039
21743
  if (matches.length === 0) {
21040
21744
  console.log();
21041
- console.log(" " + chalk50.red(`No session found matching "${idArg}".`));
21042
- console.log(" " + chalk50.dim("Use /sessions to see available session IDs."));
21745
+ console.log(" " + chalk52.red(`No session found matching "${idArg}".`));
21746
+ console.log(" " + chalk52.dim("Use /sessions to see available session IDs."));
21043
21747
  console.log();
21044
21748
  return;
21045
21749
  }
21046
21750
  if (matches.length > 1) {
21047
21751
  console.log();
21048
- console.log(" " + chalk50.red(`Ambiguous ID "${idArg}" matches ${matches.length} sessions:`));
21752
+ console.log(" " + chalk52.red(`Ambiguous ID "${idArg}" matches ${matches.length} sessions:`));
21049
21753
  for (const m of matches) {
21050
- console.log(" " + chalk50.dim(` ${m.id}`));
21754
+ console.log(" " + chalk52.dim(` ${m.id}`));
21051
21755
  }
21052
- console.log(" " + chalk50.dim("Use a longer ID to disambiguate."));
21756
+ console.log(" " + chalk52.dim("Use a longer ID to disambiguate."));
21053
21757
  console.log();
21054
21758
  return;
21055
21759
  }
@@ -21057,18 +21761,18 @@ function showSession(idArg) {
21057
21761
  const session = loadSessionFile(entry.id);
21058
21762
  if (!session) {
21059
21763
  console.log();
21060
- console.log(" " + chalk50.red(`Could not read session file for ${entry.id}.`));
21764
+ console.log(" " + chalk52.red(`Could not read session file for ${entry.id}.`));
21061
21765
  console.log();
21062
21766
  return;
21063
21767
  }
21064
21768
  const shortId = session.id.slice(-4);
21065
21769
  const dateStr = session.created_at?.slice(0, 10) ?? session.id.slice(0, 10);
21066
21770
  console.log();
21067
- console.log(" " + paint("accent", bold(`Session ${session.id}`)) + chalk50.dim(` \xB7 ${dateStr}`));
21771
+ console.log(" " + paint("accent", bold(`Session ${session.id}`)) + chalk52.dim(` \xB7 ${dateStr}`));
21068
21772
  if (session.summary) {
21069
- console.log(" " + chalk50.dim("Summary: ") + session.summary);
21773
+ console.log(" " + chalk52.dim("Summary: ") + session.summary);
21070
21774
  }
21071
- console.log(" " + chalk50.dim("\u2500".repeat(40)));
21775
+ console.log(" " + chalk52.dim("\u2500".repeat(40)));
21072
21776
  let exchangeNum = 0;
21073
21777
  for (let i = 0; i < session.messages.length; i++) {
21074
21778
  const msg = session.messages[i];
@@ -21076,14 +21780,14 @@ function showSession(idArg) {
21076
21780
  if (msg.role === "user") {
21077
21781
  exchangeNum++;
21078
21782
  console.log();
21079
- console.log(" " + chalk50.dim(`[${exchangeNum}]`) + " " + chalk50.bold("USER") + chalk50.dim(` (${time})`));
21783
+ console.log(" " + chalk52.dim(`[${exchangeNum}]`) + " " + chalk52.bold("USER") + chalk52.dim(` (${time})`));
21080
21784
  console.log(" " + msg.content);
21081
21785
  } else {
21082
21786
  console.log();
21083
- console.log(" " + chalk50.bold("AGENT") + chalk50.dim(` (${time})`));
21787
+ console.log(" " + chalk52.bold("AGENT") + chalk52.dim(` (${time})`));
21084
21788
  if (msg.content.length > 200) {
21085
21789
  console.log(" " + msg.content.slice(0, 200) + "\u2026");
21086
- console.log(" " + chalk50.dim(`(truncated \u2014 ${msg.content.length.toLocaleString()} chars)`));
21790
+ console.log(" " + chalk52.dim(`(truncated \u2014 ${msg.content.length.toLocaleString()} chars)`));
21087
21791
  } else {
21088
21792
  console.log(" " + msg.content);
21089
21793
  }
@@ -21105,22 +21809,22 @@ var init_sessions = __esm({
21105
21809
  // src/commands/resume.ts
21106
21810
  var resume_exports = {};
21107
21811
  __export(resume_exports, {
21108
- handler: () => handler35
21812
+ handler: () => handler37
21109
21813
  });
21110
- import chalk51 from "chalk";
21111
- async function handler35(args, ctx) {
21814
+ import chalk53 from "chalk";
21815
+ async function handler37(args, ctx) {
21112
21816
  if (ctx.resumedFromId && !args[0]) {
21113
21817
  console.log();
21114
- console.log(" " + chalk51.yellow("Already resumed session ") + paint("accent", ctx.resumedFromId.slice(-4)));
21115
- console.log(" " + chalk51.dim("Context: " + (ctx.resumedSessionSummary ?? "(no summary)")));
21116
- console.log(" " + chalk51.dim("Use ") + paint("accent", "/resume <id>") + chalk51.dim(" to resume a specific session."));
21818
+ console.log(" " + chalk53.yellow("Already resumed session ") + paint("accent", ctx.resumedFromId.slice(-4)));
21819
+ console.log(" " + chalk53.dim("Context: " + (ctx.resumedSessionSummary ?? "(no summary)")));
21820
+ console.log(" " + chalk53.dim("Use ") + paint("accent", "/resume <id>") + chalk53.dim(" to resume a specific session."));
21117
21821
  console.log();
21118
21822
  return;
21119
21823
  }
21120
21824
  const all2 = listSessions().filter((s) => s.exchange_count > 0 && s.id !== ctx.sessionId);
21121
21825
  if (all2.length === 0) {
21122
21826
  console.log();
21123
- console.log(" " + chalk51.dim("No prior sessions with NL exchanges to resume."));
21827
+ console.log(" " + chalk53.dim("No prior sessions with NL exchanges to resume."));
21124
21828
  console.log();
21125
21829
  return;
21126
21830
  }
@@ -21133,15 +21837,15 @@ async function handler35(args, ctx) {
21133
21837
  }
21134
21838
  if (matches.length === 0) {
21135
21839
  console.log();
21136
- console.log(" " + chalk51.red(`No session found matching "${idArg}".`));
21137
- console.log(" " + chalk51.dim("Use /sessions to see available IDs."));
21840
+ console.log(" " + chalk53.red(`No session found matching "${idArg}".`));
21841
+ console.log(" " + chalk53.dim("Use /sessions to see available IDs."));
21138
21842
  console.log();
21139
21843
  return;
21140
21844
  }
21141
21845
  if (matches.length > 1) {
21142
21846
  console.log();
21143
- console.log(" " + chalk51.red(`Ambiguous ID "${idArg}" \u2014 matches ${matches.length} sessions.`));
21144
- console.log(" " + chalk51.dim("Use a longer ID to disambiguate."));
21847
+ console.log(" " + chalk53.red(`Ambiguous ID "${idArg}" \u2014 matches ${matches.length} sessions.`));
21848
+ console.log(" " + chalk53.dim("Use a longer ID to disambiguate."));
21145
21849
  console.log();
21146
21850
  return;
21147
21851
  }
@@ -21152,7 +21856,7 @@ async function handler35(args, ctx) {
21152
21856
  const session = loadSessionFile(targetId);
21153
21857
  if (!session) {
21154
21858
  console.log();
21155
- console.log(" " + chalk51.red(`Could not read session file for ${targetId}.`));
21859
+ console.log(" " + chalk53.red(`Could not read session file for ${targetId}.`));
21156
21860
  console.log();
21157
21861
  return;
21158
21862
  }
@@ -21173,7 +21877,7 @@ async function handler35(args, ctx) {
21173
21877
  const shortId = targetId.slice(-4);
21174
21878
  console.log();
21175
21879
  console.log(" " + paint("accent", `Resumed session ${shortId}`));
21176
- console.log(" " + chalk51.dim("Context: ") + summary);
21880
+ console.log(" " + chalk53.dim("Context: ") + summary);
21177
21881
  console.log();
21178
21882
  return `Resumed ${shortId}`;
21179
21883
  }
@@ -21188,16 +21892,16 @@ var init_resume = __esm({
21188
21892
  // src/commands/name.ts
21189
21893
  var name_exports = {};
21190
21894
  __export(name_exports, {
21191
- handler: () => handler36
21895
+ handler: () => handler38
21192
21896
  });
21193
- import chalk52 from "chalk";
21194
- async function handler36(args, ctx) {
21897
+ import chalk54 from "chalk";
21898
+ async function handler38(args, ctx) {
21195
21899
  if (args.length === 0) {
21196
21900
  console.log();
21197
21901
  if (ctx.sessionName) {
21198
- console.log(" " + chalk52.dim("Session name: ") + paint("accent", ctx.sessionName));
21902
+ console.log(" " + chalk54.dim("Session name: ") + paint("accent", ctx.sessionName));
21199
21903
  } else {
21200
- console.log(" " + chalk52.dim("No name set. Usage: ") + paint("accent", "/name <label>"));
21904
+ console.log(" " + chalk54.dim("No name set. Usage: ") + paint("accent", "/name <label>"));
21201
21905
  }
21202
21906
  console.log();
21203
21907
  return;
@@ -21205,15 +21909,15 @@ async function handler36(args, ctx) {
21205
21909
  const label = args.join(" ").trim();
21206
21910
  if (label.length > MAX_NAME_LENGTH) {
21207
21911
  console.log();
21208
- console.log(" " + chalk52.red(`Name too long (${label.length} chars). Max is ${MAX_NAME_LENGTH}.`));
21912
+ console.log(" " + chalk54.red(`Name too long (${label.length} chars). Max is ${MAX_NAME_LENGTH}.`));
21209
21913
  console.log();
21210
21914
  return `Too long (max ${MAX_NAME_LENGTH})`;
21211
21915
  }
21212
21916
  const existing = findSessionByName(label);
21213
21917
  if (existing && existing.id !== ctx.sessionId) {
21214
21918
  console.log();
21215
- console.log(" " + chalk52.yellow(`"${label}" is already used by session ${existing.id.slice(-4)}.`));
21216
- console.log(" " + chalk52.dim("Use ") + paint("accent", `/switch ${label}`) + chalk52.dim(" to jump to it instead."));
21919
+ console.log(" " + chalk54.yellow(`"${label}" is already used by session ${existing.id.slice(-4)}.`));
21920
+ console.log(" " + chalk54.dim("Use ") + paint("accent", `/switch ${label}`) + chalk54.dim(" to jump to it instead."));
21217
21921
  console.log();
21218
21922
  return `"${label}" taken \u2014 use /switch`;
21219
21923
  }
@@ -21236,19 +21940,19 @@ var init_name = __esm({
21236
21940
  // src/commands/switch.ts
21237
21941
  var switch_exports = {};
21238
21942
  __export(switch_exports, {
21239
- handler: () => handler37
21943
+ handler: () => handler39
21240
21944
  });
21241
21945
  import { join as join22 } from "path";
21242
21946
  import ora15 from "ora";
21243
- import chalk53 from "chalk";
21244
- async function handler37(args, ctx) {
21947
+ import chalk55 from "chalk";
21948
+ async function handler39(args, ctx) {
21245
21949
  if (args.length === 0) {
21246
21950
  return listNamedSessions(ctx);
21247
21951
  }
21248
21952
  const targetName = args.join(" ").trim();
21249
21953
  if (ctx.sessionName && ctx.sessionName.toLowerCase() === targetName.toLowerCase()) {
21250
21954
  console.log();
21251
- console.log(" " + chalk53.dim("Already in session ") + paint("accent", ctx.sessionName));
21955
+ console.log(" " + chalk55.dim("Already in session ") + paint("accent", ctx.sessionName));
21252
21956
  console.log();
21253
21957
  return;
21254
21958
  }
@@ -21263,7 +21967,7 @@ async function handler37(args, ctx) {
21263
21967
  if (existing) {
21264
21968
  const session = loadSessionFile(existing.id);
21265
21969
  if (!session) {
21266
- console.log(" " + chalk53.red(`Could not read session file for ${existing.id}.`));
21970
+ console.log(" " + chalk55.red(`Could not read session file for ${existing.id}.`));
21267
21971
  console.log();
21268
21972
  return;
21269
21973
  }
@@ -21287,10 +21991,10 @@ async function handler37(args, ctx) {
21287
21991
  console.log();
21288
21992
  console.log(" " + paint("accent", `Switched to "${targetName}"`));
21289
21993
  if (session.summary) {
21290
- console.log(" " + chalk53.dim("Context: ") + session.summary);
21994
+ console.log(" " + chalk55.dim("Context: ") + session.summary);
21291
21995
  }
21292
21996
  const exch = session.exchange_count ?? Math.floor(session.messages.length / 2);
21293
- console.log(" " + chalk53.dim(`${exch} prior exchange${exch === 1 ? "" : "s"} loaded`));
21997
+ console.log(" " + chalk55.dim(`${exch} prior exchange${exch === 1 ? "" : "s"} loaded`));
21294
21998
  console.log();
21295
21999
  return `Switched to "${targetName}"`;
21296
22000
  } else {
@@ -21313,13 +22017,13 @@ function listNamedSessions(ctx) {
21313
22017
  const named = all2.filter((s) => s.name);
21314
22018
  if (named.length === 0) {
21315
22019
  console.log();
21316
- console.log(" " + chalk53.dim("No named sessions. Use ") + paint("accent", "/name <label>") + chalk53.dim(" to name one."));
22020
+ console.log(" " + chalk55.dim("No named sessions. Use ") + paint("accent", "/name <label>") + chalk55.dim(" to name one."));
21317
22021
  console.log();
21318
22022
  return;
21319
22023
  }
21320
22024
  console.log();
21321
22025
  console.log(" " + paint("accent", bold("Named Sessions")));
21322
- console.log(" " + chalk53.dim("\u2500".repeat(50)));
22026
+ console.log(" " + chalk55.dim("\u2500".repeat(50)));
21323
22027
  const byName = /* @__PURE__ */ new Map();
21324
22028
  for (const s of named) {
21325
22029
  const key = s.name.toLowerCase();
@@ -21328,12 +22032,12 @@ function listNamedSessions(ctx) {
21328
22032
  for (const [, s] of byName) {
21329
22033
  const isActive = ctx.sessionName?.toLowerCase() === s.name.toLowerCase();
21330
22034
  const marker2 = isActive ? paint("accent", " \u25C0") : "";
21331
- const summary = s.summary ?? chalk53.dim("(no summary)");
21332
- const exch = chalk53.dim(`${s.exchange_count} exch.`);
22035
+ const summary = s.summary ?? chalk55.dim("(no summary)");
22036
+ const exch = chalk55.dim(`${s.exchange_count} exch.`);
21333
22037
  console.log(` ${paint("accent", s.name)} ${summary} ${exch}${marker2}`);
21334
22038
  }
21335
- console.log(" " + chalk53.dim("\u2500".repeat(50)));
21336
- console.log(" " + paint("accent", "/switch <name>") + chalk53.dim(" to jump to a session"));
22039
+ console.log(" " + chalk55.dim("\u2500".repeat(50)));
22040
+ console.log(" " + paint("accent", "/switch <name>") + chalk55.dim(" to jump to a session"));
21337
22041
  console.log();
21338
22042
  return `${byName.size} named session${byName.size === 1 ? "" : "s"}`;
21339
22043
  }
@@ -21348,10 +22052,10 @@ var init_switch = __esm({
21348
22052
  // src/commands/provider.ts
21349
22053
  var provider_exports = {};
21350
22054
  __export(provider_exports, {
21351
- handler: () => handler38
22055
+ handler: () => handler40
21352
22056
  });
21353
- import chalk54 from "chalk";
21354
- async function handler38(args, ctx) {
22057
+ import chalk56 from "chalk";
22058
+ async function handler40(args, ctx) {
21355
22059
  const { positional, flags } = parseArgs2(args, ["default"]);
21356
22060
  const sub = positional[0]?.toLowerCase();
21357
22061
  if (!sub || sub === "list") {
@@ -21363,7 +22067,7 @@ async function handler38(args, ctx) {
21363
22067
  if (!ctx.oneShot) saveSessionState(ctx);
21364
22068
  console.log();
21365
22069
  console.log(" " + paint("success", "\u2713") + " Session engine reset \u2014 using config defaults.");
21366
- console.log(" " + chalk54.dim(`Default: ${loadLlmConfig().primary}`));
22070
+ console.log(" " + chalk56.dim(`Default: ${loadLlmConfig().primary}`));
21367
22071
  console.log();
21368
22072
  return;
21369
22073
  }
@@ -21376,7 +22080,7 @@ async function handler38(args, ctx) {
21376
22080
  setConfigValue("llm-auto-failover", session.autoFailover ? "on" : "off");
21377
22081
  }
21378
22082
  console.log();
21379
- console.log(" " + paint("success", "\u2713") + ` Saved ${chalk54.bold(active)} as default engine.`);
22083
+ console.log(" " + paint("success", "\u2713") + ` Saved ${chalk56.bold(active)} as default engine.`);
21380
22084
  console.log();
21381
22085
  return;
21382
22086
  }
@@ -21395,16 +22099,16 @@ async function handler38(args, ctx) {
21395
22099
  }
21396
22100
  console.log();
21397
22101
  console.log(
21398
- " " + paint("success", "\u2713") + ` Auto-failover ${session.autoFailover ? chalk54.bold("on") : chalk54.bold("off")} for this session.`
22102
+ " " + paint("success", "\u2713") + ` Auto-failover ${session.autoFailover ? chalk56.bold("on") : chalk56.bold("off")} for this session.`
21399
22103
  );
21400
- if (persist) console.log(" " + chalk54.dim("Also saved as config default."));
22104
+ if (persist) console.log(" " + chalk56.dim("Also saved as config default."));
21401
22105
  console.log();
21402
22106
  return;
21403
22107
  }
21404
22108
  if (!PROVIDERS.includes(sub)) {
21405
22109
  console.log();
21406
- console.log(" " + chalk54.red(`Unknown engine: ${sub}`));
21407
- console.log(" " + chalk54.dim("Usage: /provider [anthropic|openai|list|reset|save|failover on|off]"));
22110
+ console.log(" " + chalk56.red(`Unknown engine: ${sub}`));
22111
+ console.log(" " + chalk56.dim("Usage: /provider [anthropic|openai|list|reset|save|failover on|off]"));
21408
22112
  console.log();
21409
22113
  return;
21410
22114
  }
@@ -21412,19 +22116,19 @@ async function handler38(args, ctx) {
21412
22116
  if (!hasProviderKey(provider)) {
21413
22117
  const keyHint = provider === "anthropic" ? "api-key" : "openai-api-key";
21414
22118
  console.log();
21415
- console.log(" " + chalk54.red(`No ${provider} key configured.`));
21416
- console.log(" " + chalk54.dim(`Run `) + paint("accent", `/config set ${keyHint}`) + chalk54.dim(" to add one."));
22119
+ console.log(" " + chalk56.red(`No ${provider} key configured.`));
22120
+ console.log(" " + chalk56.dim(`Run `) + paint("accent", `/config set ${keyHint}`) + chalk56.dim(" to add one."));
21417
22121
  console.log();
21418
22122
  return;
21419
22123
  }
21420
22124
  ensureLlmSession(ctx).provider = provider;
21421
22125
  if (!ctx.oneShot) saveSessionState(ctx);
21422
22126
  console.log();
21423
- console.log(" " + paint("success", "\u2713") + ` Active engine: ${chalk54.bold(provider)}`);
21424
- console.log(" " + chalk54.dim(`Stack: ${formatActiveStack(ctx)}`));
22127
+ console.log(" " + paint("success", "\u2713") + ` Active engine: ${chalk56.bold(provider)}`);
22128
+ console.log(" " + chalk56.dim(`Stack: ${formatActiveStack(ctx)}`));
21425
22129
  const others = availableEngineLabels().filter((p) => p !== provider);
21426
22130
  if (others.length > 0) {
21427
- console.log(" " + chalk54.dim(`Also available: ${others.join(", ")}`));
22131
+ console.log(" " + chalk56.dim(`Also available: ${others.join(", ")}`));
21428
22132
  }
21429
22133
  console.log();
21430
22134
  }
@@ -21435,26 +22139,26 @@ function printStatus(ctx) {
21435
22139
  const autoFailover = resolveAutoFailoverEnabled(ctx);
21436
22140
  const engines = countAvailableEngines();
21437
22141
  console.log();
21438
- console.log(chalk54.bold(" LLM engines"));
22142
+ console.log(chalk56.bold(" LLM engines"));
21439
22143
  console.log(` Available: ${engines} engine${engines === 1 ? "" : "s"}`);
21440
22144
  for (const p of PROVIDERS) {
21441
- const key = hasProviderKey(p) ? paint("success", "\u2713") : chalk54.dim("\xB7");
22145
+ const key = hasProviderKey(p) ? paint("success", "\u2713") : chalk56.dim("\xB7");
21442
22146
  const marker2 = p === active ? paint("accent", " \u25BA active") : "";
21443
22147
  console.log(` ${key} ${p}${marker2}`);
21444
22148
  }
21445
22149
  console.log();
21446
- console.log(chalk54.bold(" Active stack"));
22150
+ console.log(chalk56.bold(" Active stack"));
21447
22151
  console.log(` ${formatActiveStack(ctx)}`);
21448
22152
  if (sessionOverride) {
21449
- console.log(chalk54.dim(" (session override \u2014 /provider reset to use default)"));
22153
+ console.log(chalk56.dim(" (session override \u2014 /provider reset to use default)"));
21450
22154
  } else {
21451
- console.log(chalk54.dim(` (config default: ${cfg.primary})`));
22155
+ console.log(chalk56.dim(` (config default: ${cfg.primary})`));
21452
22156
  }
21453
22157
  console.log();
21454
- console.log(` Auto-failover: ${autoFailover ? paint("success", "on") : chalk54.dim("off")}`);
21455
- console.log(chalk54.dim(" /provider anthropic|openai \u2014 switch engine"));
21456
- console.log(chalk54.dim(" /provider failover on|off \u2014 rate-limit safety net"));
21457
- console.log(chalk54.dim(" /provider save \u2014 persist active engine to config"));
22158
+ console.log(` Auto-failover: ${autoFailover ? paint("success", "on") : chalk56.dim("off")}`);
22159
+ console.log(chalk56.dim(" /provider anthropic|openai \u2014 switch engine"));
22160
+ console.log(chalk56.dim(" /provider failover on|off \u2014 rate-limit safety net"));
22161
+ console.log(chalk56.dim(" /provider save \u2014 persist active engine to config"));
21458
22162
  console.log();
21459
22163
  }
21460
22164
  var PROVIDERS;
@@ -21474,10 +22178,10 @@ var init_provider = __esm({
21474
22178
  // src/commands/tier.ts
21475
22179
  var tier_exports = {};
21476
22180
  __export(tier_exports, {
21477
- handler: () => handler39
22181
+ handler: () => handler41
21478
22182
  });
21479
- import chalk55 from "chalk";
21480
- async function handler39(args, ctx) {
22183
+ import chalk57 from "chalk";
22184
+ async function handler41(args, ctx) {
21481
22185
  const { positional, flags } = parseArgs2(args, ["default"]);
21482
22186
  const sub = positional[0]?.toLowerCase();
21483
22187
  if (!sub || sub === "list") {
@@ -21486,8 +22190,8 @@ async function handler39(args, ctx) {
21486
22190
  }
21487
22191
  if (!TIERS.includes(sub)) {
21488
22192
  console.log();
21489
- console.log(" " + chalk55.red(`Unknown tier: ${sub}`));
21490
- console.log(" " + chalk55.dim("Usage: /tier [high|medium|low|list] [--default]"));
22193
+ console.log(" " + chalk57.red(`Unknown tier: ${sub}`));
22194
+ console.log(" " + chalk57.dim("Usage: /tier [high|medium|low|list] [--default]"));
21491
22195
  console.log();
21492
22196
  return;
21493
22197
  }
@@ -21501,9 +22205,9 @@ async function handler39(args, ctx) {
21501
22205
  }
21502
22206
  console.log();
21503
22207
  console.log(
21504
- " " + paint("success", "\u2713") + ` Inference tier set to ${chalk55.bold(tier.toUpperCase())}` + (persist ? chalk55.dim(" (saved as default)") : chalk55.dim(" (this session)"))
22208
+ " " + paint("success", "\u2713") + ` Inference tier set to ${chalk57.bold(tier.toUpperCase())}` + (persist ? chalk57.dim(" (saved as default)") : chalk57.dim(" (this session)"))
21505
22209
  );
21506
- console.log(" " + chalk55.dim(`Stack: ${formatActiveStack(ctx)}`));
22210
+ console.log(" " + chalk57.dim(`Stack: ${formatActiveStack(ctx)}`));
21507
22211
  console.log();
21508
22212
  }
21509
22213
  function printCatalog(ctx) {
@@ -21511,30 +22215,30 @@ function printCatalog(ctx) {
21511
22215
  const active = resolveModelForActive(ctx, "agentic_investigation");
21512
22216
  const sessionTier = ctx.llm?.tier;
21513
22217
  console.log();
21514
- console.log(chalk55.bold(" Inference settings"));
22218
+ console.log(chalk57.bold(" Inference settings"));
21515
22219
  console.log(` Active: ${paint("accent", formatActiveStack(ctx))}`);
21516
22220
  if (sessionTier) {
21517
- console.log(chalk55.dim(" (session tier override)"));
22221
+ console.log(chalk57.dim(" (session tier override)"));
21518
22222
  } else {
21519
- console.log(chalk55.dim(` Config default tier: ${cfg.tier.toUpperCase()}`));
22223
+ console.log(chalk57.dim(` Config default tier: ${cfg.tier.toUpperCase()}`));
21520
22224
  }
21521
22225
  console.log();
21522
22226
  for (const tier of TIERS) {
21523
- console.log(chalk55.bold(` ${tier.toUpperCase()}`));
22227
+ console.log(chalk57.bold(` ${tier.toUpperCase()}`));
21524
22228
  for (const provider of ["anthropic", "openai"]) {
21525
22229
  const models = listCatalogEntries(provider).filter((m) => m.tier === tier);
21526
22230
  for (const m of models) {
21527
22231
  const isActive = provider === active.provider && tier === active.tier && m.id === active.modelId;
21528
22232
  const marker2 = isActive ? paint("accent", "\u25BA ") : " ";
21529
- const status = m.status === "active" ? "" : chalk55.yellow(` [${m.status}]`);
22233
+ const status = m.status === "active" ? "" : chalk57.yellow(` [${m.status}]`);
21530
22234
  console.log(`${marker2}${provider}/${m.id}${status} \u2014 ${m.display_name}`);
21531
22235
  }
21532
22236
  }
21533
22237
  console.log();
21534
22238
  }
21535
- console.log(chalk55.dim(" /tier high|medium|low \u2014 set tier for this session"));
21536
- console.log(chalk55.dim(" /tier high --default \u2014 also save as config default"));
21537
- console.log(chalk55.dim(" /provider anthropic|openai \u2014 switch engine"));
22239
+ console.log(chalk57.dim(" /tier high|medium|low \u2014 set tier for this session"));
22240
+ console.log(chalk57.dim(" /tier high --default \u2014 also save as config default"));
22241
+ console.log(chalk57.dim(" /provider anthropic|openai \u2014 switch engine"));
21538
22242
  console.log();
21539
22243
  }
21540
22244
  var TIERS;
@@ -21555,10 +22259,10 @@ var init_tier = __esm({
21555
22259
  // src/commands/model.ts
21556
22260
  var model_exports = {};
21557
22261
  __export(model_exports, {
21558
- handler: () => handler40
22262
+ handler: () => handler42
21559
22263
  });
21560
- import chalk56 from "chalk";
21561
- async function handler40(args, ctx) {
22264
+ import chalk58 from "chalk";
22265
+ async function handler42(args, ctx) {
21562
22266
  const { positional, flags } = parseArgs2(args, ["default"]);
21563
22267
  const sub = positional[0]?.toLowerCase();
21564
22268
  if (sub === "clear") {
@@ -21568,7 +22272,7 @@ async function handler40(args, ctx) {
21568
22272
  if (!ctx.oneShot) saveSessionState(ctx);
21569
22273
  console.log();
21570
22274
  console.log(" " + paint("success", "\u2713") + " Model override cleared \u2014 using tier defaults.");
21571
- console.log(" " + chalk56.dim(`Stack: ${formatActiveStack(ctx)}`));
22275
+ console.log(" " + chalk58.dim(`Stack: ${formatActiveStack(ctx)}`));
21572
22276
  console.log();
21573
22277
  return;
21574
22278
  }
@@ -21576,7 +22280,7 @@ async function handler40(args, ctx) {
21576
22280
  const modelId = positional[1];
21577
22281
  if (!modelId) {
21578
22282
  console.log();
21579
- console.log(" " + chalk56.red("Usage: /model set <model-id> [--default]"));
22283
+ console.log(" " + chalk58.red("Usage: /model set <model-id> [--default]"));
21580
22284
  console.log();
21581
22285
  return;
21582
22286
  }
@@ -21585,13 +22289,13 @@ async function handler40(args, ctx) {
21585
22289
  const entry = getCatalogEntry(modelId);
21586
22290
  if (providerErr) {
21587
22291
  console.log();
21588
- console.log(" " + chalk56.red(providerErr));
22292
+ console.log(" " + chalk58.red(providerErr));
21589
22293
  console.log();
21590
22294
  return;
21591
22295
  }
21592
22296
  if (!entry) {
21593
22297
  console.log();
21594
- console.log(" " + chalk56.yellow("\u26A0") + ` Unknown model ${modelId} \u2014 saving for active engine anyway.`);
22298
+ console.log(" " + chalk58.yellow("\u26A0") + ` Unknown model ${modelId} \u2014 saving for active engine anyway.`);
21595
22299
  }
21596
22300
  const persist = getBool(flags, "default");
21597
22301
  if (persist) {
@@ -21602,25 +22306,25 @@ async function handler40(args, ctx) {
21602
22306
  }
21603
22307
  console.log();
21604
22308
  console.log(
21605
- " " + paint("success", "\u2713") + ` Model: ${chalk56.bold(modelId)}` + (persist ? chalk56.dim(" (saved as default)") : chalk56.dim(" (this session)"))
22309
+ " " + paint("success", "\u2713") + ` Model: ${chalk58.bold(modelId)}` + (persist ? chalk58.dim(" (saved as default)") : chalk58.dim(" (this session)"))
21606
22310
  );
21607
- console.log(" " + chalk56.dim(`Stack: ${formatActiveStack(ctx)}`));
22311
+ console.log(" " + chalk58.dim(`Stack: ${formatActiveStack(ctx)}`));
21608
22312
  console.log();
21609
22313
  return;
21610
22314
  }
21611
22315
  const sessionOverride = ctx.llm?.modelOverride;
21612
22316
  const globalOverride = getConfigValue("llm-model-override");
21613
22317
  console.log();
21614
- console.log(chalk56.bold(" Model"));
22318
+ console.log(chalk58.bold(" Model"));
21615
22319
  if (sessionOverride) {
21616
22320
  console.log(` Session override: ${paint("accent", sessionOverride)}`);
21617
22321
  } else if (globalOverride) {
21618
22322
  console.log(` Config default: ${paint("accent", globalOverride)}`);
21619
22323
  } else {
21620
- console.log(" " + chalk56.dim("No override \u2014 tier defaults apply."));
22324
+ console.log(" " + chalk58.dim("No override \u2014 tier defaults apply."));
21621
22325
  }
21622
22326
  console.log(` Active stack: ${formatActiveStack(ctx)}`);
21623
- console.log(chalk56.dim(" /model set <id> \xB7 /model clear \xB7 /tier list \xB7 /provider list"));
22327
+ console.log(chalk58.dim(" /model set <id> \xB7 /model clear \xB7 /tier list \xB7 /provider list"));
21624
22328
  console.log();
21625
22329
  }
21626
22330
  var init_model = __esm({
@@ -21795,10 +22499,10 @@ var init_registry = __esm({
21795
22499
  // src/commands/update.ts
21796
22500
  var update_exports = {};
21797
22501
  __export(update_exports, {
21798
- handler: () => handler41
22502
+ handler: () => handler43
21799
22503
  });
21800
22504
  import { spawnSync } from "child_process";
21801
- import chalk57 from "chalk";
22505
+ import chalk59 from "chalk";
21802
22506
  function tailLines(text, count = 5) {
21803
22507
  return text.split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0).slice(-count).join("\n");
21804
22508
  }
@@ -21814,19 +22518,19 @@ function runGlobalInstall() {
21814
22518
  const output = [result.stdout, result.stderr].filter(Boolean).join("\n");
21815
22519
  return { ok: result.status === 0, output };
21816
22520
  }
21817
- async function handler41(_args, _ctx) {
22521
+ async function handler43(_args, _ctx) {
21818
22522
  const current = getInstalledVersion();
21819
22523
  const latest = await fetchLatestVersion(1e4);
21820
22524
  if (!latest) {
21821
22525
  console.log();
21822
- console.log(chalk57.yellow(" Could not reach the npm registry."));
21823
- console.log(chalk57.dim(` Try manually: npm install -g ${NPM_PACKAGE}`));
22526
+ console.log(chalk59.yellow(" Could not reach the npm registry."));
22527
+ console.log(chalk59.dim(` Try manually: npm install -g ${NPM_PACKAGE}`));
21824
22528
  console.log();
21825
22529
  return;
21826
22530
  }
21827
22531
  if (!isNewerVersion(latest, current)) {
21828
22532
  console.log();
21829
- console.log(chalk57.green(` \u2713 You're on the latest version (v${current})`));
22533
+ console.log(chalk59.green(` \u2713 You're on the latest version (v${current})`));
21830
22534
  console.log();
21831
22535
  return;
21832
22536
  }
@@ -21835,24 +22539,24 @@ async function handler41(_args, _ctx) {
21835
22539
  const { ok, output } = runGlobalInstall();
21836
22540
  if (ok) {
21837
22541
  invalidateUpdateCheckCache();
21838
- console.log(chalk57.green(` \u2713 Updated! Restart NTRP to use v${latest}`));
22542
+ console.log(chalk59.green(` \u2713 Updated! Restart NTRP to use v${latest}`));
21839
22543
  console.log();
21840
22544
  return;
21841
22545
  }
21842
22546
  const lower = output.toLowerCase();
21843
22547
  if (lower.includes("eacces") || lower.includes("permission denied") || lower.includes("eperm")) {
21844
- console.log(chalk57.red(` Could not install ${NPM_PACKAGE} (permission denied).`));
21845
- console.log(chalk57.dim(` Try: sudo npm install -g ${NPM_PACKAGE}`));
21846
- console.log(chalk57.dim(` Or fix npm global permissions: ${PERMISSIONS_URL}`));
22548
+ console.log(chalk59.red(` Could not install ${NPM_PACKAGE} (permission denied).`));
22549
+ console.log(chalk59.dim(` Try: sudo npm install -g ${NPM_PACKAGE}`));
22550
+ console.log(chalk59.dim(` Or fix npm global permissions: ${PERMISSIONS_URL}`));
21847
22551
  console.log();
21848
22552
  return;
21849
22553
  }
21850
22554
  const detail = tailLines(output);
21851
- console.log(chalk57.red(` Could not install ${NPM_PACKAGE}.`));
22555
+ console.log(chalk59.red(` Could not install ${NPM_PACKAGE}.`));
21852
22556
  if (detail) {
21853
- console.log(chalk57.dim(` ${detail.split("\n").join("\n ")}`));
22557
+ console.log(chalk59.dim(` ${detail.split("\n").join("\n ")}`));
21854
22558
  }
21855
- console.log(chalk57.dim(` Try manually: npm install -g ${NPM_PACKAGE}`));
22559
+ console.log(chalk59.dim(` Try manually: npm install -g ${NPM_PACKAGE}`));
21856
22560
  console.log();
21857
22561
  }
21858
22562
  var PERMISSIONS_URL;
@@ -21955,10 +22659,10 @@ async function resolveHandler(name) {
21955
22659
  try {
21956
22660
  const mod = await importHandler(runtimePath);
21957
22661
  if (!mod) return null;
21958
- const handler42 = mod.handler;
21959
- if (typeof handler42 !== "function") return null;
21960
- entry.handler = handler42;
21961
- return handler42;
22662
+ const handler44 = mod.handler;
22663
+ if (typeof handler44 !== "function") return null;
22664
+ entry.handler = handler44;
22665
+ return handler44;
21962
22666
  } catch (err) {
21963
22667
  console.error(`Failed to load handler for /${name}:`, err);
21964
22668
  return null;
@@ -22010,6 +22714,10 @@ async function importHandler(runtimePath) {
22010
22714
  return Promise.resolve().then(() => (init_config(), config_exports));
22011
22715
  case "../commands/activate.js":
22012
22716
  return Promise.resolve().then(() => (init_activate(), activate_exports));
22717
+ case "../commands/upgrade.js":
22718
+ return Promise.resolve().then(() => (init_upgrade2(), upgrade_exports2));
22719
+ case "../commands/checkout.js":
22720
+ return Promise.resolve().then(() => (init_checkout(), checkout_exports));
22013
22721
  case "../commands/onboard.js":
22014
22722
  return Promise.resolve().then(() => (init_onboard(), onboard_exports));
22015
22723
  case "../commands/setup.js":
@@ -22655,6 +23363,30 @@ handler: ../commands/activate.ts
22655
23363
 
22656
23364
  Activate NTRP with your license key (format: NTRP-XXXX-XXXX-XXXX). Most
22657
23365
  commands require a valid license.`
23366
+ },
23367
+ {
23368
+ name: "upgrade",
23369
+ raw: `---
23370
+ name: upgrade
23371
+ description: Upgrade trial to Pro \u2014 checkout + paste key
23372
+ section: Settings
23373
+ handler: ../commands/upgrade.ts
23374
+ ---
23375
+
23376
+ Open the Pro checkout page and paste your new license key without leaving
23377
+ the REPL. Use during trial grace or after cutoff. Flags: --url (print checkout URL only).`
23378
+ },
23379
+ {
23380
+ name: "checkout",
23381
+ raw: `---
23382
+ name: checkout
23383
+ description: Open signup checkout in your browser
23384
+ section: Settings
23385
+ handler: ../commands/checkout.ts
23386
+ ---
23387
+
23388
+ Opens the Lemon Squeezy checkout page in your default browser. Use anytime
23389
+ you need a trial or Pro license key.`
22658
23390
  },
22659
23391
  {
22660
23392
  name: "feedback",
@@ -22676,7 +23408,7 @@ paragraph that flows into all AI surfaces.`
22676
23408
  });
22677
23409
 
22678
23410
  // src/license/activation.ts
22679
- import chalk58 from "chalk";
23411
+ import chalk60 from "chalk";
22680
23412
  function hasValidLicense() {
22681
23413
  return checkLicense().valid;
22682
23414
  }
@@ -22684,54 +23416,32 @@ async function ensureLicenseActivated(ctx) {
22684
23416
  if (hasValidLicense()) return false;
22685
23417
  if (!process.stdin.isTTY) {
22686
23418
  console.error();
22687
- console.error(chalk58.red(" A license key is required."));
22688
- console.error(chalk58.dim(` Purchase at ${PURCHASE_URL}`));
22689
- console.error(chalk58.dim(" Then run: ntrp activate <key>"));
22690
- console.error(chalk58.dim(" Or set NTRP_LICENSE_KEY for headless use."));
23419
+ console.error(chalk60.red(" A license key is required."));
23420
+ console.error(chalk60.dim(` Sign up: ${getCheckoutUrl()}`));
23421
+ console.error(chalk60.dim(" Then run: ntrp activate <key>"));
23422
+ console.error(chalk60.dim(" Or set NTRP_LICENSE_KEY for headless use."));
22691
23423
  console.error();
22692
23424
  process.exit(1);
22693
23425
  }
23426
+ const lic = checkLicense();
23427
+ if (hasStoredLicenseKey() && isTrialCutoff(lic)) {
23428
+ return runUpgradeFlow(ctx, "expired");
23429
+ }
22694
23430
  printCenteredLogo();
22695
23431
  console.log(" " + bold("Activate your license"));
22696
- console.log(
22697
- " " + chalk58.dim("Purchase at ") + paint("accent", PURCHASE_URL) + chalk58.dim(" \u2014 your key is delivered after checkout.")
22698
- );
23432
+ console.log(" " + chalk60.dim("Don't have a key yet? Sign up (free trial or Pro), then paste it below."));
22699
23433
  console.log();
22700
- const session = createPromptSession(ctx.rl, ctx);
22701
- try {
22702
- for (; ; ) {
22703
- const key = await session.askSecret("Paste your license key", { confirm: false });
22704
- if (!key.trim()) {
22705
- console.log(" " + chalk58.red("A license key is required to use NTRP."));
22706
- continue;
22707
- }
22708
- const result = validateLicenseKey(key.trim());
22709
- if (!result.valid) {
22710
- console.log(" " + chalk58.red(result.message));
22711
- console.log(" " + chalk58.dim(`Check the key from your purchase email or ${PURCHASE_URL}`));
22712
- console.log();
22713
- continue;
22714
- }
22715
- setConfigValue("license-key", key.trim());
22716
- console.log();
22717
- console.log(chalk58.green(` \u2713 License activated: ${result.message}`));
22718
- console.log();
22719
- return true;
22720
- }
22721
- } finally {
22722
- session.close();
22723
- }
23434
+ await promptOpenCheckout(ctx);
23435
+ return promptForLicenseKey(ctx);
22724
23436
  }
22725
- var PURCHASE_URL;
22726
23437
  var init_activation = __esm({
22727
23438
  "src/license/activation.ts"() {
22728
23439
  "use strict";
22729
- init_prompts();
22730
- init_store();
22731
23440
  init_banner();
22732
23441
  init_theme();
22733
23442
  init_verify();
22734
- PURCHASE_URL = "https://ntrp.sonnechasser.com";
23443
+ init_trial_policy();
23444
+ init_upgrade();
22735
23445
  }
22736
23446
  });
22737
23447
 
@@ -22757,7 +23467,9 @@ var init_gate2 = __esm({
22757
23467
  "scratch",
22758
23468
  "cleanup",
22759
23469
  "deactivate-demo",
22760
- "update"
23470
+ "update",
23471
+ "upgrade",
23472
+ "checkout"
22761
23473
  ]);
22762
23474
  }
22763
23475
  });
@@ -22767,7 +23479,7 @@ var router_exports = {};
22767
23479
  __export(router_exports, {
22768
23480
  conversationRouter: () => conversationRouter
22769
23481
  });
22770
- import chalk59 from "chalk";
23482
+ import chalk61 from "chalk";
22771
23483
  async function conversationRouter(input, ctx) {
22772
23484
  if (ctx.oneShot || (ctx.wizardDepth ?? 0) > 0) {
22773
23485
  return { handled: false };
@@ -22777,7 +23489,7 @@ async function conversationRouter(input, ctx) {
22777
23489
  if (FRESH_START_RE.test(line)) {
22778
23490
  console.log();
22779
23491
  console.log(
22780
- " " + chalk59.dim("Start a fresh analysis? This keeps prior sessions \u2014 say ") + chalk59.cyan("yes") + chalk59.dim(" to confirm or ") + chalk59.cyan("/home") + chalk59.dim(" for the dashboard.")
23492
+ " " + chalk61.dim("Start a fresh analysis? This keeps prior sessions \u2014 say ") + chalk61.cyan("yes") + chalk61.dim(" to confirm or ") + chalk61.cyan("/home") + chalk61.dim(" for the dashboard.")
22781
23493
  );
22782
23494
  console.log();
22783
23495
  return { handled: true };
@@ -22811,7 +23523,7 @@ async function conversationRouter(input, ctx) {
22811
23523
  }
22812
23524
  if (phase === "compute") {
22813
23525
  console.log();
22814
- console.log(" " + chalk59.dim("Analysis running \u2014 wait for it to finish before typing another question."));
23526
+ console.log(" " + chalk61.dim("Analysis running \u2014 wait for it to finish before typing another question."));
22815
23527
  console.log();
22816
23528
  return { handled: true };
22817
23529
  }
@@ -22851,12 +23563,9 @@ var init_router = __esm({
22851
23563
  });
22852
23564
 
22853
23565
  // src/cli/dispatch.ts
22854
- import chalk60 from "chalk";
23566
+ import chalk62 from "chalk";
22855
23567
  function printLicenseRequired(command) {
22856
- console.log();
22857
- console.log(chalk60.red(` A license is required for ${command}.`));
22858
- console.log(chalk60.dim(` Purchase at ${PURCHASE_URL2} or run /activate <key>.`));
22859
- console.log();
23568
+ printLicenseBlocked(command);
22860
23569
  }
22861
23570
  function handledResult(command, summary, ctx) {
22862
23571
  return {
@@ -22920,7 +23629,7 @@ async function dispatch(input, ctx) {
22920
23629
  if (tokens.length === 1) {
22921
23630
  if (/^\d$/.test(first)) {
22922
23631
  console.log(
22923
- " " + chalk60.dim("Looks like a menu pick \u2014 run ") + paint("accent", "/new") + chalk60.dim(" to start (pick Demo, then choose your analysis type).")
23632
+ " " + chalk62.dim("Looks like a menu pick \u2014 run ") + paint("accent", "/new") + chalk62.dim(" to start (pick Demo, then choose your analysis type).")
22924
23633
  );
22925
23634
  return { kind: "handled" };
22926
23635
  }
@@ -22943,22 +23652,22 @@ async function dispatch(input, ctx) {
22943
23652
  return { kind: "handled", summary };
22944
23653
  }
22945
23654
  console.log(
22946
- " " + chalk60.dim("Not in Q&A yet \u2014 confirm scope, load data, and run analysis first. Type ") + paint("accent", "/home") + chalk60.dim(" for status.")
23655
+ " " + chalk62.dim("Not in Q&A yet \u2014 confirm scope, load data, and run analysis first. Type ") + paint("accent", "/home") + chalk62.dim(" for status.")
22947
23656
  );
22948
23657
  return { kind: "handled" };
22949
23658
  }
22950
23659
  console.log(
22951
- " " + chalk60.dim("Natural-language questions run in the interactive REPL. Start with ") + paint("accent", "ntrp") + chalk60.dim(" and ask after analysis.")
23660
+ " " + chalk62.dim("Natural-language questions run in the interactive REPL. Start with ") + paint("accent", "ntrp") + chalk62.dim(" and ask after analysis.")
22952
23661
  );
22953
23662
  return { kind: "handled" };
22954
23663
  }
22955
23664
  async function runSlashCommand(name, args, ctx) {
22956
- const handler42 = await resolveHandler(name);
22957
- if (!handler42) {
22958
- console.error(chalk60.red(` Unknown command: /${name}`));
23665
+ const handler44 = await resolveHandler(name);
23666
+ if (!handler44) {
23667
+ console.error(chalk62.red(` Unknown command: /${name}`));
22959
23668
  return void 0;
22960
23669
  }
22961
- const result = await handler42(args, ctx);
23670
+ const result = await handler44(args, ctx);
22962
23671
  return result ?? void 0;
22963
23672
  }
22964
23673
  async function runNaturalLanguage2(input, ctx) {
@@ -22966,7 +23675,6 @@ async function runNaturalLanguage2(input, ctx) {
22966
23675
  const result = await mod.runNaturalLanguage(input, ctx);
22967
23676
  return result ?? void 0;
22968
23677
  }
22969
- var PURCHASE_URL2;
22970
23678
  var init_dispatch = __esm({
22971
23679
  "src/cli/dispatch.ts"() {
22972
23680
  "use strict";
@@ -22978,7 +23686,7 @@ var init_dispatch = __esm({
22978
23686
  init_theme();
22979
23687
  init_activation();
22980
23688
  init_gate2();
22981
- PURCHASE_URL2 = "https://ntrp.sonnechasser.com";
23689
+ init_upgrade();
22982
23690
  }
22983
23691
  });
22984
23692
 
@@ -22988,7 +23696,7 @@ __export(welcome_exports, {
22988
23696
  GRADIENT: () => GRADIENT,
22989
23697
  printWelcome: () => printWelcome
22990
23698
  });
22991
- import chalk61 from "chalk";
23699
+ import chalk63 from "chalk";
22992
23700
  function resolveSessionSummary(input) {
22993
23701
  if (input.scope?.intent_summary?.trim()) return input.scope.intent_summary.trim();
22994
23702
  if (input.summary?.trim()) return input.summary.trim();
@@ -23022,19 +23730,19 @@ function sessionSummaryText(s) {
23022
23730
  summary: s.summary,
23023
23731
  dataset: s.dataset
23024
23732
  });
23025
- return summary === NO_SUMMARY ? chalk61.dim(summary) : summary;
23733
+ return summary === NO_SUMMARY ? chalk63.dim(summary) : summary;
23026
23734
  }
23027
23735
  function formatLastSessionLine(s, colW, ctx, opts) {
23028
23736
  const phase = sessionPhaseLabel(s, ctx);
23029
- const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk61.dim(" \xB7 current") : "";
23030
- const meta = `${formatSessionId(s.id, s.name)} ${chalk61.dim("\xB7")} ${chalk61.dim(lensBadgeLabel(s.analysis))} ${chalk61.dim("\xB7")} ${paint("accent", phase)} ${chalk61.dim("\xB7")} ${sessionSummaryText(s)}${current}`;
23737
+ const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk63.dim(" \xB7 current") : "";
23738
+ const meta = `${formatSessionId(s.id, s.name)} ${chalk63.dim("\xB7")} ${chalk63.dim(lensBadgeLabel(s.analysis))} ${chalk63.dim("\xB7")} ${paint("accent", phase)} ${chalk63.dim("\xB7")} ${sessionSummaryText(s)}${current}`;
23031
23739
  return truncateVisible(` ${meta}`, colW);
23032
23740
  }
23033
23741
  function formatActiveSessionLine(s, colW, ctx, opts) {
23034
23742
  const indent = " ";
23035
23743
  const idPart = formatSessionId(s.id, s.name);
23036
- const status = chalk61.dim(` \xB7 ${sessionStatusSuffix(s)}`);
23037
- const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk61.dim(" \xB7 current") : "";
23744
+ const status = chalk63.dim(` \xB7 ${sessionStatusSuffix(s)}`);
23745
+ const current = opts?.markCurrent && s.id === ctx?.sessionId ? chalk63.dim(" \xB7 current") : "";
23038
23746
  const suffix = `${status}${current}`;
23039
23747
  const summaryBudget = Math.max(8, colW - visibleWidth(indent) - visibleWidth(idPart) - visibleWidth(suffix) - 2);
23040
23748
  const summaryPart = truncateVisible(sessionSummaryText(s), summaryBudget);
@@ -23071,13 +23779,13 @@ function buildSystemLines(colW, statusRows, recent) {
23071
23779
  const lines = [""];
23072
23780
  lines.push(sectionHeading("System"));
23073
23781
  for (const item of statusRows) {
23074
- const label = chalk61.dim(padRight(item.label, 8));
23782
+ const label = chalk63.dim(padRight(item.label, 8));
23075
23783
  const state = padRight(item.state, 10);
23076
23784
  const detailW = Math.max(1, colW - 21);
23077
- lines.push(`${label} ${state} ${chalk61.dim(truncateVisible(item.detail, detailW))}`);
23785
+ lines.push(`${label} ${state} ${chalk63.dim(truncateVisible(item.detail, detailW))}`);
23078
23786
  }
23079
23787
  if (recent) {
23080
- lines.push(`${chalk61.dim(padRight("last used", 8))} ${chalk61.dim(recent)}`);
23788
+ lines.push(`${chalk63.dim(padRight("last used", 8))} ${chalk63.dim(recent)}`);
23081
23789
  }
23082
23790
  return lines;
23083
23791
  }
@@ -23087,7 +23795,7 @@ function buildHelpLines(colW, unfinishedCount) {
23087
23795
  lines.push(sectionHeading(section.heading));
23088
23796
  for (const entry of section.entries) {
23089
23797
  const desc = entry.dynamicDescription ? entry.dynamicDescription(unfinishedCount) : entry.description;
23090
- const text = ` ${paint("accent", entry.command)} ${chalk61.dim(desc)}`;
23798
+ const text = ` ${paint("accent", entry.command)} ${chalk63.dim(desc)}`;
23091
23799
  lines.push(truncateVisible(text, colW));
23092
23800
  }
23093
23801
  }
@@ -23097,10 +23805,10 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
23097
23805
  const lines = [""];
23098
23806
  lines.push(sectionHeading("Last Session"));
23099
23807
  if (!lastSession) {
23100
- lines.push(` ${chalk61.dim("(none yet)")}`);
23808
+ lines.push(` ${chalk63.dim("(none yet)")}`);
23101
23809
  lines.push(
23102
23810
  truncateVisible(
23103
- ` ${nextAction.command ? actionHint(nextAction.label, nextAction.command, nextAction.detail) : `${chalk61.dim(nextAction.label)} ${chalk61.dim(nextAction.detail)}`}`,
23811
+ ` ${nextAction.command ? actionHint(nextAction.label, nextAction.command, nextAction.detail) : `${chalk63.dim(nextAction.label)} ${chalk63.dim(nextAction.detail)}`}`,
23104
23812
  colW
23105
23813
  )
23106
23814
  );
@@ -23111,7 +23819,7 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
23111
23819
  if (!isCurrent) {
23112
23820
  lines.push(
23113
23821
  truncateVisible(
23114
- ` ${chalk61.dim("Resume:")} ${paint("accent", `/session ${lastSession.id.slice(-4)}`)}`,
23822
+ ` ${chalk63.dim("Resume:")} ${paint("accent", `/session ${lastSession.id.slice(-4)}`)}`,
23115
23823
  colW
23116
23824
  )
23117
23825
  );
@@ -23120,7 +23828,7 @@ function buildLastSessionLines(colW, ctx, lastSession, nextAction, emptyDataHint
23120
23828
  truncateVisible(` ${actionHint(nextAction.label, nextAction.command, nextAction.detail)}`, colW)
23121
23829
  );
23122
23830
  } else {
23123
- lines.push(truncateVisible(` ${chalk61.dim(nextAction.label)} ${chalk61.dim(nextAction.detail)}`, colW));
23831
+ lines.push(truncateVisible(` ${chalk63.dim(nextAction.label)} ${chalk63.dim(nextAction.detail)}`, colW));
23124
23832
  }
23125
23833
  if (isCurrent && emptyDataHint) {
23126
23834
  lines.push(truncateVisible(` ${emptyDataHint}`, colW));
@@ -23131,14 +23839,14 @@ function buildActiveSessionsLines(colW, ctx, activeSessions) {
23131
23839
  const lines = [""];
23132
23840
  lines.push(sectionHeading("Active Sessions"));
23133
23841
  if (activeSessions.length === 0) {
23134
- lines.push(` ${chalk61.dim("(none in progress)")}`);
23842
+ lines.push(` ${chalk63.dim("(none in progress)")}`);
23135
23843
  return lines;
23136
23844
  }
23137
23845
  for (const s of activeSessions.slice(0, 5)) {
23138
23846
  lines.push(formatActiveSessionLine(s, colW, ctx, { markCurrent: true }));
23139
23847
  }
23140
23848
  if (activeSessions.length > 5) {
23141
- lines.push(` ${chalk61.dim(`+${activeSessions.length - 5} more \xB7 `)}${paint("accent", "/session")}`);
23849
+ lines.push(` ${chalk63.dim(`+${activeSessions.length - 5} more \xB7 `)}${paint("accent", "/session")}`);
23142
23850
  }
23143
23851
  return lines;
23144
23852
  }
@@ -23148,7 +23856,7 @@ async function printWelcome(ctx, version) {
23148
23856
  const innerW = cardW - 2;
23149
23857
  const contentW = innerW - 2;
23150
23858
  const outerPad = " ".repeat(Math.max(0, Math.floor((width - cardW) / 2)));
23151
- const border = (ch) => chalk61.dim(ch);
23859
+ const border = (ch) => chalk63.dim(ch);
23152
23860
  const push = (line) => console.log(outerPad + line);
23153
23861
  const fitCell = (content, width2) => {
23154
23862
  if (visibleWidth(content) > width2) return truncateVisible(content, width2);
@@ -23193,7 +23901,32 @@ async function printWelcome(ctx, version) {
23193
23901
  const llmDetail = engineCount === 0 ? "needs key" : engineCount === 1 ? `1 engine \xB7 ${availableEngineLabels2()[0]}` : `${engineCount} engines`;
23194
23902
  const llmState = engineCount >= 2 ? badge("READY", "success") : engineCount === 1 ? badge("READY", "success") : badge("MISSING", "warning");
23195
23903
  const inferenceDetail = engineCount > 0 ? `active: ${formatActiveStack2(ctx)}` : "not configured";
23904
+ const license = checkLicense();
23905
+ let licenseState;
23906
+ let licenseDetail;
23907
+ if (!license.valid) {
23908
+ licenseState = badge("MISSING", "warning");
23909
+ licenseDetail = "run /checkout";
23910
+ } else if (license.edition === "trial" && license.trialPhase === "grace") {
23911
+ licenseState = badge("GRACE", "warning");
23912
+ licenseDetail = `${license.daysUntilLockout ?? 0} day${license.daysUntilLockout === 1 ? "" : "s"} until lockout`;
23913
+ } else if (license.edition === "trial") {
23914
+ licenseState = badge("TRIAL", "success");
23915
+ const days = license.trialDaysRemaining;
23916
+ licenseDetail = days !== void 0 && days > 0 ? `${days} day${days === 1 ? "" : "s"} remaining` : license.message.replace(/^trial license\s*/i, "");
23917
+ } else if (license.edition === "team") {
23918
+ licenseState = badge("TEAM", "success");
23919
+ licenseDetail = license.message;
23920
+ } else {
23921
+ licenseState = badge("PRO", "success");
23922
+ licenseDetail = license.message;
23923
+ }
23196
23924
  const statusRows = [
23925
+ {
23926
+ label: "license",
23927
+ state: licenseState,
23928
+ detail: licenseDetail
23929
+ },
23197
23930
  {
23198
23931
  label: "engines",
23199
23932
  state: llmState,
@@ -23221,7 +23954,7 @@ async function printWelcome(ctx, version) {
23221
23954
  ctx,
23222
23955
  unfinishedCount: unfinishedSessions.length
23223
23956
  });
23224
- const emptyDataHint = !hasData ? savedSessions.length > 0 ? chalk61.dim("Run ") + paint("accent", "/session") + chalk61.dim(" to resume a saved analysis, or ") + paint("accent", "/new") + chalk61.dim(" for a fresh start") : chalk61.dim("Run ") + paint("accent", "/new") + chalk61.dim(" \u2192 pick Demo to explore sample data") : null;
23957
+ const emptyDataHint = !hasData ? savedSessions.length > 0 ? chalk63.dim("Run ") + paint("accent", "/session") + chalk63.dim(" to resume a saved analysis, or ") + paint("accent", "/new") + chalk63.dim(" for a fresh start") : chalk63.dim("Run ") + paint("accent", "/new") + chalk63.dim(" \u2192 pick Demo to explore sample data") : null;
23225
23958
  const colW = useWideLayout ? leftW : contentW;
23226
23959
  const rightColW = useWideLayout ? rightW : contentW;
23227
23960
  const systemLines = buildSystemLines(colW, statusRows, recent);
@@ -23236,14 +23969,14 @@ async function printWelcome(ctx, version) {
23236
23969
  const logoOffset = " ".repeat(Math.max(0, Math.floor((cardW - maxLogoW) / 2)));
23237
23970
  for (const line of logo) push(logoOffset + line);
23238
23971
  const taglineOffset = " ".repeat(Math.max(0, Math.floor((cardW - visibleWidth(TAGLINE)) / 2)));
23239
- push(taglineOffset + chalk61.dim(TAGLINE));
23972
+ push(taglineOffset + chalk63.dim(TAGLINE));
23240
23973
  push("");
23241
23974
  }
23242
23975
  const versionTag = ` v${version} `;
23243
23976
  const gap = Math.max(0, innerW - versionTag.length);
23244
23977
  const gapL = Math.floor(gap / 2);
23245
23978
  push(
23246
- border(`\u256D${"\u2500".repeat(gapL)}`) + chalk61.dim(versionTag) + border(`${"\u2500".repeat(gap - gapL)}\u256E`)
23979
+ border(`\u256D${"\u2500".repeat(gapL)}`) + chalk63.dim(versionTag) + border(`${"\u2500".repeat(gap - gapL)}\u256E`)
23247
23980
  );
23248
23981
  if (useWideLayout) {
23249
23982
  const leftLines = [...systemLines, ...helpLines];
@@ -23286,6 +24019,7 @@ var init_welcome = __esm({
23286
24019
  init_store();
23287
24020
  init_profile();
23288
24021
  init_profile2();
24022
+ init_verify();
23289
24023
  init_queries();
23290
24024
  init_schema();
23291
24025
  TAGLINE = "Pipeline intelligence for GTM operators";
@@ -23337,7 +24071,7 @@ __export(repl_exports, {
23337
24071
  import { createInterface as createInterface2 } from "readline/promises";
23338
24072
  import { clearLine as clearLine2, cursorTo as cursorTo2 } from "readline";
23339
24073
  import ora16 from "ora";
23340
- import chalk62 from "chalk";
24074
+ import chalk64 from "chalk";
23341
24075
  function buildPrompt(ctx) {
23342
24076
  return buildConversationPrompt(ctx);
23343
24077
  }
@@ -23372,12 +24106,12 @@ function renderInlineSuggestion(rl, prompt) {
23372
24106
  const suffix = cursor === line.length ? inlineCommandSuggestion(line) : null;
23373
24107
  clearLine2(process.stdout, 0);
23374
24108
  cursorTo2(process.stdout, 0);
23375
- process.stdout.write(prompt + line + (suffix ? chalk62.dim(suffix) : ""));
24109
+ process.stdout.write(prompt + line + (suffix ? chalk64.dim(suffix) : ""));
23376
24110
  cursorTo2(process.stdout, visibleLength(prompt) + cursor);
23377
24111
  }
23378
24112
  function appendTurnLine(current, promptLabel, currentSummary) {
23379
- const currentLine = currentSummary ? `${promptLabel} ${current} ${chalk62.white("\u2192")} ${currentSummary}` : `${promptLabel} ${current}`;
23380
- console.log(" " + chalk62.dim(currentLine));
24113
+ const currentLine = currentSummary ? `${promptLabel} ${current} ${chalk64.white("\u2192")} ${currentSummary}` : `${promptLabel} ${current}`;
24114
+ console.log(" " + chalk64.dim(currentLine));
23381
24115
  console.log();
23382
24116
  }
23383
24117
  async function goHome(ctx, version, history, opts) {
@@ -23387,7 +24121,7 @@ async function goHome(ctx, version, history, opts) {
23387
24121
  process.stdout.write("\x1B[2J\x1B[H");
23388
24122
  if (opts?.banner) {
23389
24123
  console.log();
23390
- console.log(" " + paint("accent", "\u2713") + " " + chalk62.dim(opts.banner));
24124
+ console.log(" " + paint("accent", "\u2713") + " " + chalk64.dim(opts.banner));
23391
24125
  }
23392
24126
  await printWelcome(ctx, version);
23393
24127
  }
@@ -23410,11 +24144,11 @@ async function handleDispatchResult(result, ctx, version, history) {
23410
24144
  case "unknown":
23411
24145
  if (result.suggestion) {
23412
24146
  console.log(
23413
- " " + chalk62.red(`Unknown command: ${result.token}.`) + chalk62.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk62.dim("?")
24147
+ " " + chalk64.red(`Unknown command: ${result.token}.`) + chalk64.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk64.dim("?")
23414
24148
  );
23415
24149
  } else {
23416
24150
  console.log(
23417
- " " + chalk62.red(`Unknown command: ${result.token}`) + chalk62.dim(" Type ") + paint("accent", "/help") + chalk62.dim(" to see available commands.")
24151
+ " " + chalk64.red(`Unknown command: ${result.token}`) + chalk64.dim(" Type ") + paint("accent", "/help") + chalk64.dim(" to see available commands.")
23418
24152
  );
23419
24153
  }
23420
24154
  break;
@@ -23438,7 +24172,7 @@ async function runRepl(ctx, version) {
23438
24172
  ctx.rl = rl;
23439
24173
  console.log();
23440
24174
  console.log(
23441
- " " + chalk62.dim("What do you want to look at? ") + chalk62.dim('(e.g. "pipeline health", "is NRR real?", "board deck on Q3")')
24175
+ " " + chalk64.dim("What do you want to look at? ") + chalk64.dim('(e.g. "pipeline health", "is NRR real?", "board deck on Q3")')
23442
24176
  );
23443
24177
  console.log();
23444
24178
  if (ctx.pendingUpdateCheck) {
@@ -23468,7 +24202,7 @@ async function runRepl(ctx, version) {
23468
24202
  return;
23469
24203
  }
23470
24204
  sigintPrimed = true;
23471
- console.log("\n " + chalk62.dim("Type /exit to quit, or press Ctrl+C again."));
24205
+ console.log("\n " + chalk64.dim("Type /exit to quit, or press Ctrl+C again."));
23472
24206
  };
23473
24207
  rl.on("SIGINT", sigintHandler);
23474
24208
  function shutdownRepl() {
@@ -23539,7 +24273,7 @@ async function runRepl(ctx, version) {
23539
24273
  }
23540
24274
  }
23541
24275
  } else {
23542
- console.error(" " + chalk62.red("Error: " + String(err.message ?? err)));
24276
+ console.error(" " + chalk64.red("Error: " + String(err.message ?? err)));
23543
24277
  }
23544
24278
  }
23545
24279
  history.push({ input: line, summary });
@@ -23557,7 +24291,7 @@ async function runRepl(ctx, version) {
23557
24291
  } else {
23558
24292
  await closeSession(ctx);
23559
24293
  }
23560
- console.log(" " + chalk62.dim(randomGoodbye()));
24294
+ console.log(" " + chalk64.dim(randomGoodbye()));
23561
24295
  }
23562
24296
  function printHelpOneShot() {
23563
24297
  printHelp();
@@ -23565,14 +24299,16 @@ function printHelpOneShot() {
23565
24299
  function printHelp() {
23566
24300
  console.log();
23567
24301
  console.log(" " + sectionHeading("Conversation"));
23568
- console.log(" " + chalk62.dim("Type what you want to investigate \u2014 no slash needed."));
23569
- console.log(" " + chalk62.dim("Paste a CSV path or say ") + paint("accent", '"use demo data"') + chalk62.dim(" to load data."));
23570
- console.log(" " + chalk62.dim("After analysis, ask questions in plain English."));
23571
- console.log(" " + chalk62.dim("Say ") + paint("accent", '"ship a board deck"') + chalk62.dim(" to draft a handoff prompt."));
24302
+ console.log(" " + chalk64.dim("Type what you want to investigate \u2014 no slash needed."));
24303
+ console.log(" " + chalk64.dim("Paste a CSV path or say ") + paint("accent", '"use demo data"') + chalk64.dim(" to load data."));
24304
+ console.log(" " + chalk64.dim("After analysis, ask questions in plain English."));
24305
+ console.log(" " + chalk64.dim("Say ") + paint("accent", '"ship a board deck"') + chalk64.dim(" to draft a handoff prompt."));
23572
24306
  console.log();
23573
24307
  console.log(" " + sectionHeading("Shortcuts"));
23574
24308
  const shortcuts = [
23575
24309
  ["/home", "Status dashboard"],
24310
+ ["/upgrade", "Trial \u2192 Pro checkout + key paste"],
24311
+ ["/checkout", "Open signup in browser"],
23576
24312
  ["/update", "Upgrade to the latest version"],
23577
24313
  ["/handoff", "Export or agent prompts"],
23578
24314
  ["/demo", "Load demo data"],
@@ -23581,7 +24317,7 @@ function printHelp() {
23581
24317
  ];
23582
24318
  const maxW = Math.max(...shortcuts.map(([c]) => c.length)) + 2;
23583
24319
  for (const [cmd, desc] of shortcuts) {
23584
- console.log(` ${paint("accent", padRight(cmd, maxW))} ${chalk62.dim(desc)}`);
24320
+ console.log(` ${paint("accent", padRight(cmd, maxW))} ${chalk64.dim(desc)}`);
23585
24321
  }
23586
24322
  console.log();
23587
24323
  console.log(" " + sectionHeading("Admin"));
@@ -23592,10 +24328,10 @@ function printHelp() {
23592
24328
  ];
23593
24329
  const adminMaxW = Math.max(...admin.map(([c]) => c.length)) + 2;
23594
24330
  for (const [cmd, desc] of admin) {
23595
- console.log(` ${paint("accent", padRight(cmd, adminMaxW))} ${chalk62.dim(desc)}`);
24331
+ console.log(` ${paint("accent", padRight(cmd, adminMaxW))} ${chalk64.dim(desc)}`);
23596
24332
  }
23597
24333
  console.log();
23598
- console.log(" " + chalk62.dim("Power-user commands (") + paint("accent", "/new") + chalk62.dim(", ") + paint("accent", "/diagnose") + chalk62.dim(", ") + paint("accent", "/metrics") + chalk62.dim(") remain available."));
24334
+ console.log(" " + chalk64.dim("Power-user commands (") + paint("accent", "/new") + chalk64.dim(", ") + paint("accent", "/diagnose") + chalk64.dim(", ") + paint("accent", "/metrics") + chalk64.dim(") remain available."));
23599
24335
  console.log();
23600
24336
  }
23601
24337
  var REPL_BUILTINS, ANSI_PATTERN, GOODBYES;
@@ -23677,7 +24413,7 @@ init_emit();
23677
24413
  init_errors2();
23678
24414
  init_types2();
23679
24415
  init_version();
23680
- import chalk63 from "chalk";
24416
+ import chalk65 from "chalk";
23681
24417
  var VERSION = getInstalledVersion();
23682
24418
  var UNGATED = UNGATED_COMMANDS;
23683
24419
  var DB_COMMANDS = /* @__PURE__ */ new Set(["actions", "ask", "backmeup", "demo", "diagnose", "export", "handoff", "ingest", "metrics", "new", "playbook", "publish", "report", "reset", "segment", "session", "status", "strategy"]);
@@ -23704,7 +24440,7 @@ async function main() {
23704
24440
  quiet: args.globals.quiet
23705
24441
  });
23706
24442
  if (!ctx.execution.color) {
23707
- chalk63.level = 0;
24443
+ chalk65.level = 0;
23708
24444
  }
23709
24445
  if (args.globals.stdin) {
23710
24446
  args.input = (await readStdin()).trim();
@@ -23712,21 +24448,21 @@ async function main() {
23712
24448
  if (args.oneShot) {
23713
24449
  const cmd = firstToken(args.input);
23714
24450
  if (!UNGATED.has(cmd)) {
23715
- const lic = checkLicense();
23716
- if (!lic.valid) {
24451
+ const lic2 = await refreshLicenseOnline();
24452
+ if (!lic2.valid) {
23717
24453
  if (isStructuredOutput(ctx.execution)) {
23718
- emitError(cmd || "ntrp", new NtrpError("license_invalid", lic.message, 3 /* Auth */));
24454
+ emitError(cmd || "ntrp", new NtrpError("license_invalid", lic2.message, 3 /* Auth */));
23719
24455
  }
23720
- console.error(chalk63.red(`
23721
- ${lic.message}`));
23722
- console.error(chalk63.dim(" Purchase a license at https://ntrp.sonnechasser.com\n"));
24456
+ console.error(chalk65.red(`
24457
+ ${lic2.message}`));
24458
+ console.error(chalk65.dim(" Trial's over \u2014 /upgrade and paste your key.\n"));
23723
24459
  process.exit(1);
23724
24460
  }
23725
24461
  }
23726
24462
  const PROFILE_HINT_SKIP = /* @__PURE__ */ new Set(["onboard", "setup", "config", "activate", "help", "home", "exit", "quit", "clear", "profile"]);
23727
24463
  if (!isProfileConfigured() && !PROFILE_HINT_SKIP.has(cmd) && !ctx.execution.quiet) {
23728
24464
  console.error(
23729
- " " + chalk63.dim("Tip: run ") + paint("accent", "ntrp") + chalk63.dim(" interactively to set up your company profile for richer answers.")
24465
+ " " + chalk65.dim("Tip: run ") + paint("accent", "ntrp") + chalk65.dim(" interactively to set up your company profile for richer answers.")
23730
24466
  );
23731
24467
  }
23732
24468
  const result = await dispatch(args.input, ctx);
@@ -23738,12 +24474,12 @@ async function main() {
23738
24474
  }
23739
24475
  if (result.suggestion) {
23740
24476
  console.error(
23741
- chalk63.red(` Unknown command: ${result.token}.`) + chalk63.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk63.dim("?")
24477
+ chalk65.red(` Unknown command: ${result.token}.`) + chalk65.dim(" Did you mean ") + paint("accent", result.suggestion) + chalk65.dim("?")
23742
24478
  );
23743
24479
  } else {
23744
- console.error(chalk63.red(` Unknown command: ${result.token}`));
24480
+ console.error(chalk65.red(` Unknown command: ${result.token}`));
23745
24481
  }
23746
- console.error(chalk63.dim(" Run 'ntrp' for the interactive prompt."));
24482
+ console.error(chalk65.dim(" Run 'ntrp' for the interactive prompt."));
23747
24483
  process.exit(1);
23748
24484
  break;
23749
24485
  case "help":
@@ -23765,6 +24501,11 @@ async function main() {
23765
24501
  return DB_COMMANDS.has(cmd);
23766
24502
  }
23767
24503
  const showedActivation = await ensureLicenseActivated(ctx);
24504
+ const lic = await refreshLicenseOnline();
24505
+ if (lic.shouldNudgeUpgrade) {
24506
+ const { printTrialNudge: printTrialNudge2 } = await Promise.resolve().then(() => (init_upgrade(), upgrade_exports));
24507
+ printTrialNudge2(lic);
24508
+ }
23768
24509
  if (!isProfileConfigured()) {
23769
24510
  try {
23770
24511
  const { handler: onboard } = await Promise.resolve().then(() => (init_onboard(), onboard_exports));