@sonnechasser/ntrp 0.1.3 → 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/README.md CHANGED
@@ -14,17 +14,35 @@ NTRP sits on top of your CRM exports and activity data, computes five vital sign
14
14
  npm install -g @sonnechasser/ntrp
15
15
  ```
16
16
 
17
- ## Activate your license
17
+ ## License & trial
18
18
 
19
- NTRP requires a license key from purchase. Keys are delivered after checkout via [ntrp.sonnechasser.com](https://ntrp.sonnechasser.com) (Lemon Squeezy).
19
+ NTRP requires a license key from [Lemon Squeezy](https://sonnechasser.lemonsqueezy.com). Customer keys are UUID format (e.g. `36150FCC-711E-4BCA-...`) delivered by email after checkout.
20
20
 
21
- **On first launch**, `ntrp` will prompt you to paste your key. You can also activate manually:
21
+ **On first launch**, `ntrp` opens the signup checkout (free trial or Pro), then prompts you to paste your key.
22
+
23
+ | Flow | Command | Checkout |
24
+ |------|---------|----------|
25
+ | New signup (trial or Pro) | First launch, `/checkout` | [Signup](https://sonnechasser.lemonsqueezy.com/checkout/buy/d62d35a2-a369-4cf5-a88b-328223866b5f) |
26
+ | Trial → Pro upgrade | `/upgrade` | [Pro only](https://sonnechasser.lemonsqueezy.com/checkout/buy/3bd1da42-936f-49a6-a6c3-d11eee213884) |
27
+
28
+ **Trial policy:** 11 days full access, then grace through day 30. After day 30, run `/upgrade` and paste your Pro key.
29
+
30
+ Activate manually if you already have a key:
22
31
 
23
32
  ```bash
24
- ntrp activate NTRP-XXXX-XXXX-XXXX
33
+ ntrp activate <your-license-key>
25
34
  ```
26
35
 
27
- In the REPL: `/activate NTRP-XXXX-XXXX-XXXX`
36
+ In the REPL: `/activate <your-license-key>`
37
+
38
+ ### Test as a new user
39
+
40
+ ```bash
41
+ npm uninstall -g @sonnechasser/ntrp
42
+ rm -rf ~/.ntrp
43
+ npm install -g @sonnechasser/ntrp@latest
44
+ ntrp
45
+ ```
28
46
 
29
47
  ## Quick start
30
48
 
@@ -66,11 +84,13 @@ ntrp setup check --json
66
84
  | Command | Description |
67
85
  |---------|-------------|
68
86
  | `ntrp` | Open the interactive REPL |
69
- | `/home` | Status dashboard |
87
+ | `/home` | Status dashboard (license, profile, dataset) |
88
+ | `/checkout` | Open signup checkout in browser |
89
+ | `/upgrade` | Trial → Pro checkout + paste key |
70
90
  | `/onboard` | Company profile wizard |
71
91
  | `/demo` | Load demo scenario data |
72
92
  | `/handoff` | Export or agent prompts |
73
- | `/update` | Upgrade to the latest version |
93
+ | `/update` | Upgrade to the latest npm version |
74
94
  | `ntrp setup check` | Validate local configuration |
75
95
 
76
96
  Type `/help` inside the REPL for shortcuts.
@@ -97,13 +117,18 @@ Inside the REPL:
97
117
  Or reinstall:
98
118
 
99
119
  ```bash
100
- npm install -g @sonnechasser/ntrp
120
+ npm install -g @sonnechasser/ntrp@latest
101
121
  ```
102
122
 
103
123
  ## Data & config
104
124
 
105
125
  Local state lives in `~/.ntrp/` (config, sessions, DuckDB datasets). Override with `NTRP_HOME` if needed.
106
126
 
127
+ Checkout URL overrides (optional):
128
+
129
+ - `NTRP_CHECKOUT_URL` — signup / first-run
130
+ - `NTRP_UPGRADE_URL` — Pro upgrade (`/upgrade`)
131
+
107
132
  ## Links
108
133
 
109
134
  - **Website:** [ntrp.sonnechasser.com](https://ntrp.sonnechasser.com)
package/dist/index.js CHANGED
@@ -18779,7 +18779,10 @@ var init_config = __esm({
18779
18779
 
18780
18780
  // src/license/trial-policy.ts
18781
18781
  function getCheckoutUrl() {
18782
- return process.env.NTRP_UPGRADE_URL ?? process.env.NTRP_PURCHASE_URL ?? process.env.NTRP_CHECKOUT_URL ?? PRO_CHECKOUT_URL;
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();
18783
18786
  }
18784
18787
  function evaluateTrial(activatedAt, now2 = /* @__PURE__ */ new Date()) {
18785
18788
  const daysSince = Math.floor((now2.getTime() - activatedAt.getTime()) / 864e5);
@@ -18788,6 +18791,7 @@ function evaluateTrial(activatedAt, now2 = /* @__PURE__ */ new Date()) {
18788
18791
  phase: "expired",
18789
18792
  daysSinceActivation: daysSince,
18790
18793
  daysUntilLockout: 0,
18794
+ trialDaysRemaining: 0,
18791
18795
  shouldNudge: false
18792
18796
  };
18793
18797
  }
@@ -18796,14 +18800,17 @@ function evaluateTrial(activatedAt, now2 = /* @__PURE__ */ new Date()) {
18796
18800
  phase: "grace",
18797
18801
  daysSinceActivation: daysSince,
18798
18802
  daysUntilLockout: TRIAL_GRACE_END_DAYS - daysSince,
18803
+ trialDaysRemaining: 0,
18799
18804
  shouldNudge: true
18800
18805
  };
18801
18806
  }
18807
+ const trialDaysRemaining = TRIAL_FULL_DAYS - daysSince;
18802
18808
  return {
18803
18809
  phase: "active",
18804
18810
  daysSinceActivation: daysSince,
18805
18811
  daysUntilLockout: TRIAL_GRACE_END_DAYS - daysSince,
18806
- shouldNudge: false
18812
+ trialDaysRemaining,
18813
+ shouldNudge: daysSince >= TRIAL_ACTIVE_NUDGE_FROM_DAY
18807
18814
  };
18808
18815
  }
18809
18816
  function formatTrialActiveMessage(daysSince) {
@@ -18812,13 +18819,15 @@ function formatTrialActiveMessage(daysSince) {
18812
18819
  const dayWord = daysLeft === 1 ? "day" : "days";
18813
18820
  return `trial license (${daysLeft} ${dayWord} remaining)`;
18814
18821
  }
18815
- var TRIAL_FULL_DAYS, TRIAL_GRACE_END_DAYS, PRO_CHECKOUT_URL;
18822
+ var TRIAL_FULL_DAYS, TRIAL_GRACE_END_DAYS, TRIAL_ACTIVE_NUDGE_FROM_DAY, SIGNUP_CHECKOUT_URL, PRO_UPGRADE_CHECKOUT_URL;
18816
18823
  var init_trial_policy = __esm({
18817
18824
  "src/license/trial-policy.ts"() {
18818
18825
  "use strict";
18819
18826
  TRIAL_FULL_DAYS = 11;
18820
18827
  TRIAL_GRACE_END_DAYS = 30;
18821
- PRO_CHECKOUT_URL = "https://sonnechasser.lemonsqueezy.com/checkout/buy/d62d35a2-a369-4cf5-a88b-328223866b5f";
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";
18822
18831
  }
18823
18832
  });
18824
18833
 
@@ -18829,6 +18838,9 @@ function pick(items) {
18829
18838
  function randomGraceNudge(daysLeft) {
18830
18839
  return pick(GRACE_NUDGES)(daysLeft);
18831
18840
  }
18841
+ function randomActiveTrialNudge(daysLeft) {
18842
+ return pick(ACTIVE_TRIAL_NUDGES)(daysLeft);
18843
+ }
18832
18844
  function randomCutoffNudge() {
18833
18845
  return pick(CUTOFF_NUDGES);
18834
18846
  }
@@ -18844,7 +18856,7 @@ function randomUpgradeSubtitle(reason) {
18844
18856
  function randomProActivatedLine() {
18845
18857
  return pick(PRO_ACTIVATED_LINES);
18846
18858
  }
18847
- var GRACE_NUDGES, CUTOFF_NUDGES, BLOCKED_WHILE_CUTOFF, UPGRADE_HEADLINES, UPGRADE_SUBTITLES, PRO_ACTIVATED_LINES;
18859
+ var GRACE_NUDGES, ACTIVE_TRIAL_NUDGES, CUTOFF_NUDGES, BLOCKED_WHILE_CUTOFF, UPGRADE_HEADLINES, UPGRADE_SUBTITLES, PRO_ACTIVATED_LINES;
18848
18860
  var init_upgrade_whimsy = __esm({
18849
18861
  "src/license/upgrade-whimsy.ts"() {
18850
18862
  "use strict";
@@ -18865,6 +18877,13 @@ var init_upgrade_whimsy = __esm({
18865
18877
  (d) => `If you're still into it, cool. ${d} day${d === 1 ? "" : "s"} \u2014 /upgrade.`,
18866
18878
  (d) => `Last friendly ping. ${d} day${d === 1 ? "" : "s"}. /upgrade.`
18867
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
+ ];
18868
18887
  CUTOFF_NUDGES = [
18869
18888
  "Okay \u2014 that's the line. /upgrade and you're back.",
18870
18889
  "We're paused until you say yes. /upgrade.",
@@ -19103,7 +19122,8 @@ function applyTrialPolicy(result) {
19103
19122
  message: randomCutoffNudge(),
19104
19123
  trialPhase: "expired",
19105
19124
  shouldNudgeUpgrade: false,
19106
- daysUntilLockout: 0
19125
+ daysUntilLockout: 0,
19126
+ trialDaysRemaining: 0
19107
19127
  };
19108
19128
  }
19109
19129
  const message = trial.phase === "grace" ? `trial license (grace \u2014 ${trial.daysUntilLockout} day${trial.daysUntilLockout === 1 ? "" : "s"} until lockout)` : formatTrialActiveMessage(trial.daysSinceActivation);
@@ -19112,7 +19132,8 @@ function applyTrialPolicy(result) {
19112
19132
  message,
19113
19133
  trialPhase: trial.phase,
19114
19134
  shouldNudgeUpgrade: trial.shouldNudge,
19115
- daysUntilLockout: trial.daysUntilLockout
19135
+ daysUntilLockout: trial.daysUntilLockout,
19136
+ trialDaysRemaining: trial.trialDaysRemaining
19116
19137
  };
19117
19138
  }
19118
19139
  function storedLicenseProvider(key) {
@@ -19295,21 +19316,24 @@ var init_open_browser = __esm({
19295
19316
  // src/license/upgrade.ts
19296
19317
  var upgrade_exports = {};
19297
19318
  __export(upgrade_exports, {
19319
+ getCheckoutUrl: () => getCheckoutUrl,
19298
19320
  getUpgradeUrl: () => getUpgradeUrl,
19299
19321
  hasStoredLicenseKey: () => hasStoredLicenseKey,
19300
19322
  isTrialCutoff: () => isTrialCutoff,
19301
19323
  isTrialGrace: () => isTrialGrace,
19302
19324
  openCheckoutInBrowser: () => openCheckoutInBrowser,
19325
+ printActiveTrialNudge: () => printActiveTrialNudge,
19303
19326
  printGraceNudge: () => printGraceNudge,
19304
19327
  printLicenseBlocked: () => printLicenseBlocked,
19328
+ printTrialNudge: () => printTrialNudge,
19305
19329
  promptForLicenseKey: () => promptForLicenseKey,
19306
19330
  promptOpenCheckout: () => promptOpenCheckout,
19307
19331
  resolveUpgradeReason: () => resolveUpgradeReason,
19308
19332
  runUpgradeFlow: () => runUpgradeFlow
19309
19333
  });
19310
19334
  import chalk39 from "chalk";
19311
- function getUpgradeUrl() {
19312
- return getCheckoutUrl();
19335
+ function checkoutUrlFor(purpose) {
19336
+ return purpose === "upgrade" ? getUpgradeUrl() : getCheckoutUrl();
19313
19337
  }
19314
19338
  function isTrialCutoff(lic) {
19315
19339
  return lic.trialPhase === "expired";
@@ -19335,14 +19359,31 @@ function printGraceNudge(lic) {
19335
19359
  console.log(" " + chalk39.yellow(randomGraceNudge(lic.daysUntilLockout)));
19336
19360
  console.log();
19337
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
+ }
19338
19379
  function headlineFor(reason, lic) {
19339
19380
  return randomUpgradeHeadline(lic.daysUntilLockout);
19340
19381
  }
19341
19382
  function subtitleFor(reason) {
19342
19383
  return randomUpgradeSubtitle(reason);
19343
19384
  }
19344
- async function promptOpenCheckout(ctx) {
19345
- const url = getUpgradeUrl();
19385
+ async function promptOpenCheckout(ctx, purpose = "signup") {
19386
+ const url = checkoutUrlFor(purpose);
19346
19387
  console.log(" " + chalk39.dim(url));
19347
19388
  if (!process.stdin.isTTY || process.env.NTRP_NO_BROWSER_OPEN === "1") {
19348
19389
  console.log();
@@ -19355,7 +19396,11 @@ async function promptOpenCheckout(ctx) {
19355
19396
  try {
19356
19397
  await openInBrowser(url);
19357
19398
  console.log(" " + chalk39.green("\u2713 Browser opened"));
19358
- console.log(" " + chalk39.dim("Complete signup in your browser, then paste your key below."));
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
+ );
19359
19404
  } catch {
19360
19405
  console.log(" " + chalk39.yellow("Couldn't open browser \u2014 copy the URL above."));
19361
19406
  }
@@ -19365,7 +19410,7 @@ async function promptOpenCheckout(ctx) {
19365
19410
  }
19366
19411
  }
19367
19412
  async function openCheckoutInBrowser() {
19368
- const url = getUpgradeUrl();
19413
+ const url = getCheckoutUrl();
19369
19414
  console.log();
19370
19415
  console.log(" " + chalk39.dim(url));
19371
19416
  if (!process.stdin.isTTY) {
@@ -19381,7 +19426,7 @@ async function openCheckoutInBrowser() {
19381
19426
  console.log(" " + chalk39.dim("After signup, paste your key with /activate or /upgrade."));
19382
19427
  console.log();
19383
19428
  }
19384
- async function promptForLicenseKey(ctx) {
19429
+ async function promptForLicenseKey(ctx, purpose = "signup") {
19385
19430
  const session = createPromptSession(ctx.rl, ctx);
19386
19431
  try {
19387
19432
  for (; ; ) {
@@ -19402,7 +19447,9 @@ async function promptForLicenseKey(ctx) {
19402
19447
  }
19403
19448
  if (!result.valid) {
19404
19449
  console.log(" " + chalk39.red(result.message));
19405
- console.log(" " + chalk39.dim(`Use the key from your purchase email, or try again: ${getUpgradeUrl()}`));
19450
+ console.log(
19451
+ " " + chalk39.dim(`Use the key from your purchase email, or try again: ${checkoutUrlFor(purpose)}`)
19452
+ );
19406
19453
  console.log();
19407
19454
  continue;
19408
19455
  }
@@ -19421,10 +19468,10 @@ async function runUpgradeFlow(ctx, reason) {
19421
19468
  console.log(" " + bold(headlineFor(reason, lic)));
19422
19469
  console.log(" " + chalk39.dim(subtitleFor(reason)));
19423
19470
  console.log();
19424
- await promptOpenCheckout(ctx);
19471
+ await promptOpenCheckout(ctx, "upgrade");
19425
19472
  console.log(" " + chalk39.dim("Paste your license key when it arrives by email"));
19426
19473
  console.log();
19427
- return promptForLicenseKey(ctx);
19474
+ return promptForLicenseKey(ctx, "upgrade");
19428
19475
  }
19429
19476
  function resolveUpgradeReason() {
19430
19477
  const lic = checkLicense();
@@ -19605,6 +19652,18 @@ __export(setup_exports, {
19605
19652
  handler: () => handler27
19606
19653
  });
19607
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
+ }
19608
19667
  async function handler27(args, ctx) {
19609
19668
  const { positional, flags } = parseArgs2(args);
19610
19669
  const sub = positional[0] ?? "check";
@@ -19630,7 +19689,7 @@ async function handler27(args, ctx) {
19630
19689
  } else {
19631
19690
  console.log(" Engines: missing");
19632
19691
  }
19633
- console.log(` License: ${result.license.valid ? "valid" : "missing/invalid"} - ${result.license.message}`);
19692
+ console.log(` License: ${formatLicenseSetupLine(result.license)}`);
19634
19693
  console.log();
19635
19694
  return;
19636
19695
  }
@@ -23358,7 +23417,7 @@ async function ensureLicenseActivated(ctx) {
23358
23417
  if (!process.stdin.isTTY) {
23359
23418
  console.error();
23360
23419
  console.error(chalk60.red(" A license key is required."));
23361
- console.error(chalk60.dim(` Sign up: ${getUpgradeUrl()}`));
23420
+ console.error(chalk60.dim(` Sign up: ${getCheckoutUrl()}`));
23362
23421
  console.error(chalk60.dim(" Then run: ntrp activate <key>"));
23363
23422
  console.error(chalk60.dim(" Or set NTRP_LICENSE_KEY for headless use."));
23364
23423
  console.error();
@@ -23381,6 +23440,7 @@ var init_activation = __esm({
23381
23440
  init_banner();
23382
23441
  init_theme();
23383
23442
  init_verify();
23443
+ init_trial_policy();
23384
23444
  init_upgrade();
23385
23445
  }
23386
23446
  });
@@ -23841,7 +23901,32 @@ async function printWelcome(ctx, version) {
23841
23901
  const llmDetail = engineCount === 0 ? "needs key" : engineCount === 1 ? `1 engine \xB7 ${availableEngineLabels2()[0]}` : `${engineCount} engines`;
23842
23902
  const llmState = engineCount >= 2 ? badge("READY", "success") : engineCount === 1 ? badge("READY", "success") : badge("MISSING", "warning");
23843
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
+ }
23844
23924
  const statusRows = [
23925
+ {
23926
+ label: "license",
23927
+ state: licenseState,
23928
+ detail: licenseDetail
23929
+ },
23845
23930
  {
23846
23931
  label: "engines",
23847
23932
  state: llmState,
@@ -23934,6 +24019,7 @@ var init_welcome = __esm({
23934
24019
  init_store();
23935
24020
  init_profile();
23936
24021
  init_profile2();
24022
+ init_verify();
23937
24023
  init_queries();
23938
24024
  init_schema();
23939
24025
  TAGLINE = "Pipeline intelligence for GTM operators";
@@ -24417,8 +24503,8 @@ async function main() {
24417
24503
  const showedActivation = await ensureLicenseActivated(ctx);
24418
24504
  const lic = await refreshLicenseOnline();
24419
24505
  if (lic.shouldNudgeUpgrade) {
24420
- const { printGraceNudge: printGraceNudge2 } = await Promise.resolve().then(() => (init_upgrade(), upgrade_exports));
24421
- printGraceNudge2(lic);
24506
+ const { printTrialNudge: printTrialNudge2 } = await Promise.resolve().then(() => (init_upgrade(), upgrade_exports));
24507
+ printTrialNudge2(lic);
24422
24508
  }
24423
24509
  if (!isProfileConfigured()) {
24424
24510
  try {