@sonnechasser/ntrp 1.4.2 → 1.4.3

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.
Files changed (3) hide show
  1. package/dist/index.js +167 -148
  2. package/dist/mcp/server.js +120 -101
  3. package/package.json +1 -1
@@ -685,13 +685,21 @@ var init_theme = __esm({
685
685
  });
686
686
 
687
687
  // src/services/handoff-skill.ts
688
- import { mkdirSync as mkdirSync3 } from "fs";
688
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3 } from "fs";
689
689
  import { basename, join as join2 } from "path";
690
690
  import { homedir as homedir3 } from "os";
691
691
  import chalk2 from "chalk";
692
- function defaultAiInboxDir() {
692
+ function legacyAiInboxDir() {
693
693
  return join2(homedir3(), "Documents", "Claude", "ntrp-inbox");
694
694
  }
695
+ function defaultAiInboxDirDisplay() {
696
+ return "~/Documents/ntrp-inbox";
697
+ }
698
+ function defaultAiInboxDir() {
699
+ const legacy = legacyAiInboxDir();
700
+ if (existsSync2(legacy)) return legacy;
701
+ return join2(homedir3(), "Documents", "ntrp-inbox");
702
+ }
695
703
  function handoffLocations() {
696
704
  const archiveRoot = getExportsDir();
697
705
  const archiveLatestDir = join2(archiveRoot, "latest");
@@ -784,7 +792,7 @@ function filenamePattern(ctx) {
784
792
  return `${datePrefix}*${ext}`;
785
793
  }
786
794
  function buildStandingSkillMarkdown(loc = handoffLocations()) {
787
- const inboxBlock = loc.inboxDir ? `Inbox (preferred \u2014 point Claude Desktop / a project / Cursor at this folder):
795
+ const inboxBlock = loc.inboxDir ? `Inbox (preferred \u2014 point Claude, ChatGPT, Cursor, or another desktop AI at this folder):
788
796
  \`${loc.inboxDir}\`
789
797
 
790
798
  Start with:
@@ -907,7 +915,9 @@ function maybePrintAiInboxNudge() {
907
915
  if (getConfigValue("ai-inbox-nudge-seen") === "true") return;
908
916
  setConfigValue("ai-inbox-nudge-seen", "true");
909
917
  console.log(
910
- " " + chalk2.dim("Set a pickup folder. Type /inbox set ~/Documents/Claude/ntrp-inbox then /inbox skill")
918
+ " " + chalk2.dim(
919
+ `Set a pickup folder. Type /inbox set ${defaultAiInboxDirDisplay()} then /inbox skill`
920
+ )
911
921
  );
912
922
  }
913
923
  function printStandingSkill() {
@@ -916,7 +926,9 @@ function printStandingSkill() {
916
926
  console.log();
917
927
  console.log(" " + bold("NTRP handoff finder skill"));
918
928
  console.log(
919
- " " + chalk2.dim("Paste this skill once into Claude, ChatGPT, or Cursor. Later handoffs do not print it again.")
929
+ " " + chalk2.dim(
930
+ "Paste this skill once into your desktop AI (Claude, ChatGPT, Cursor, \u2026). Later handoffs do not print it again."
931
+ )
920
932
  );
921
933
  printPlainBlock(buildStandingSkillMarkdown(loc));
922
934
  console.log(" " + chalk2.dim("Written: ") + (loc.inboxSkill ?? loc.archiveSkill));
@@ -944,7 +956,7 @@ import {
944
956
  appendFileSync,
945
957
  copyFileSync,
946
958
  cpSync,
947
- existsSync as existsSync2,
959
+ existsSync as existsSync3,
948
960
  mkdirSync as mkdirSync4,
949
961
  readFileSync as readFileSync2,
950
962
  readdirSync,
@@ -962,13 +974,13 @@ function ensureExportsLayout(root = getExportsDir()) {
962
974
  mkdirSync4(join3(root, sub), { recursive: true });
963
975
  }
964
976
  const readme = join3(root, "README.md");
965
- if (!existsSync2(readme)) {
977
+ if (!existsSync3(readme)) {
966
978
  writeFileSync3(readme, ARCHIVE_README, "utf-8");
967
979
  }
968
- if (!existsSync2(join3(root, "INDEX.md"))) {
980
+ if (!existsSync3(join3(root, "INDEX.md"))) {
969
981
  writeFileSync3(join3(root, "INDEX.md"), "# NTRP exports\n\n_No exports yet._\n", "utf-8");
970
982
  }
971
- if (!existsSync2(join3(root, "manifest.jsonl"))) {
983
+ if (!existsSync3(join3(root, "manifest.jsonl"))) {
972
984
  writeFileSync3(join3(root, "manifest.jsonl"), "", "utf-8");
973
985
  }
974
986
  return root;
@@ -990,7 +1002,7 @@ function ensureInboxLayout(inbox) {
990
1002
  mkdirSync4(join3(inbox, "archive"), { recursive: true });
991
1003
  const readme = join3(inbox, "README.md");
992
1004
  writeFileSync3(readme, buildInboxReadme(), "utf-8");
993
- if (!existsSync2(join3(inbox, "INDEX.md"))) {
1005
+ if (!existsSync3(join3(inbox, "INDEX.md"))) {
994
1006
  writeFileSync3(join3(inbox, "INDEX.md"), "# NTRP AI inbox\n\n_No exports synced yet._\n", "utf-8");
995
1007
  }
996
1008
  }
@@ -999,7 +1011,7 @@ function manifestPath(root = getExportsDir()) {
999
1011
  }
1000
1012
  function readManifestEvents(root = getExportsDir()) {
1001
1013
  const path = manifestPath(root);
1002
- if (!existsSync2(path)) return [];
1014
+ if (!existsSync3(path)) return [];
1003
1015
  const text = readFileSync2(path, "utf-8");
1004
1016
  const events = [];
1005
1017
  for (const line of text.split("\n")) {
@@ -1033,7 +1045,7 @@ function listExports(opts = {}) {
1033
1045
  }
1034
1046
  function copyPath(src, dest) {
1035
1047
  mkdirSync4(dirname2(dest), { recursive: true });
1036
- if (existsSync2(dest)) {
1048
+ if (existsSync3(dest)) {
1037
1049
  rmSync(dest, { recursive: true, force: true });
1038
1050
  }
1039
1051
  const st = statSync(src);
@@ -1053,7 +1065,7 @@ function regenerateIndex(root = getExportsDir()) {
1053
1065
  const withHistory = items.filter((e) => (e.previous_paths?.length ?? 0) > 0);
1054
1066
  const latestDir = join3(root, "latest");
1055
1067
  const latestLines = [];
1056
- if (existsSync2(latestDir)) {
1068
+ if (existsSync3(latestDir)) {
1057
1069
  for (const name of readdirSync(latestDir).sort()) {
1058
1070
  latestLines.push(`- \`latest/${name}\` \u2192 \`${join3(latestDir, name)}\``);
1059
1071
  }
@@ -1063,7 +1075,7 @@ function regenerateIndex(root = getExportsDir()) {
1063
1075
  "",
1064
1076
  `Archive root: \`${root}\``,
1065
1077
  "",
1066
- "Set an inbox with `/onboard` or `/inbox set`. Paste `SKILL.md` once into Claude. Later handoffs overwrite `latest-handoff.md`.",
1078
+ "Set an inbox with `/onboard` or `/inbox set`. Paste `SKILL.md` once into your desktop AI. Later handoffs overwrite `latest-handoff.md`.",
1067
1079
  "",
1068
1080
  "## Latest pointers",
1069
1081
  ""
@@ -1113,18 +1125,18 @@ function regenerateInboxIndex(inbox) {
1113
1125
  const lines = [
1114
1126
  "# NTRP AI inbox",
1115
1127
  "",
1116
- "Start here. Install `SKILL.md` once in Claude. Newest prompt: `latest-handoff.md`. Catalog: `INDEX.md`.",
1128
+ "Start here. Install `SKILL.md` once in your desktop AI. Newest prompt: `latest-handoff.md`. Catalog: `INDEX.md`.",
1117
1129
  "",
1118
1130
  `Canonical archive: \`${archiveRoot}\` (see \`${join3(archiveRoot, "INDEX.md")}\`).`,
1119
1131
  "",
1120
1132
  "## Latest pointers",
1121
1133
  ""
1122
1134
  ];
1123
- if (existsSync2(join3(inbox, "SKILL.md"))) {
1135
+ if (existsSync3(join3(inbox, "SKILL.md"))) {
1124
1136
  lines.push("- [`SKILL.md`](./SKILL.md) \u2014 standing finder. Paste once into your agent.");
1125
1137
  }
1126
1138
  const latestNames = readdirSync(inbox).filter((n) => n.startsWith("latest-")).sort();
1127
- if (latestNames.length === 0 && !existsSync2(join3(inbox, "SKILL.md"))) {
1139
+ if (latestNames.length === 0 && !existsSync3(join3(inbox, "SKILL.md"))) {
1128
1140
  lines.push("_None yet. Run a handoff after `/inbox set`._");
1129
1141
  } else {
1130
1142
  for (const name of latestNames) {
@@ -1152,7 +1164,7 @@ This folder is the landing folder for NTRP handoffs. Desktop AI tools read files
1152
1164
 
1153
1165
  ## Start here
1154
1166
 
1155
- 1. Install \`SKILL.md\` once in Claude, ChatGPT, or Cursor. Then tell the agent to open the latest NTRP handoff.
1167
+ 1. Install \`SKILL.md\` once in Claude, ChatGPT, Cursor, or another desktop AI. Then tell the agent to open the latest NTRP handoff.
1156
1168
  2. The newest prompt is \`latest-handoff.md\` (or \`latest-handoff-deck.md\` and similar).
1157
1169
  3. \`latest-pickup.md\` names the file that was just written.
1158
1170
 
@@ -1170,7 +1182,7 @@ Set the folder with \`/inbox set <path>\`. Print the skill with \`/inbox skill\`
1170
1182
  `;
1171
1183
  }
1172
1184
  function pruneInboxArchive(archiveDir, keep = INBOX_ARCHIVE_KEEP) {
1173
- if (!existsSync2(archiveDir)) return;
1185
+ if (!existsSync3(archiveDir)) return;
1174
1186
  const entries2 = readdirSync(archiveDir).map((name) => {
1175
1187
  const p = join3(archiveDir, name);
1176
1188
  try {
@@ -1186,7 +1198,7 @@ function pruneInboxArchive(archiveDir, keep = INBOX_ARCHIVE_KEEP) {
1186
1198
  function syncAiInbox(entry) {
1187
1199
  const inbox = getAiInboxDir();
1188
1200
  if (!inbox) return null;
1189
- if (!existsSync2(entry.path)) return null;
1201
+ if (!existsSync3(entry.path)) return null;
1190
1202
  ensureInboxLayout(inbox);
1191
1203
  const archiveDir = join3(inbox, "archive");
1192
1204
  mkdirSync4(archiveDir, { recursive: true });
@@ -1210,7 +1222,7 @@ function syncRecentToInbox(limit = 10) {
1210
1222
  const items = listExports({ limit });
1211
1223
  let n = 0;
1212
1224
  for (const item of items) {
1213
- if (!existsSync2(item.path)) continue;
1225
+ if (!existsSync3(item.path)) continue;
1214
1226
  const inboxPath = syncAiInbox(item);
1215
1227
  if (inboxPath) {
1216
1228
  appendManifestEvent({
@@ -1224,7 +1236,7 @@ function syncRecentToInbox(limit = 10) {
1224
1236
  }
1225
1237
  regenerateInboxIndex(inbox);
1226
1238
  regenerateIndex();
1227
- const newest = items.find((e) => existsSync2(e.path));
1239
+ const newest = items.find((e) => existsSync3(e.path));
1228
1240
  if (newest) persistHandoffSkillFiles(newest);
1229
1241
  return n;
1230
1242
  }
@@ -1259,10 +1271,10 @@ This archive stores handoffs, reports, notes, CSV receipts, and publish packages
1259
1271
  Set a dedicated inbox for desktop AI instead of this folder:
1260
1272
 
1261
1273
  \`\`\`
1262
- /inbox set ~/Documents/Claude/ntrp-inbox
1274
+ /inbox set ~/Documents/ntrp-inbox
1263
1275
  \`\`\`
1264
1276
 
1265
- After \`/inbox set\` or the optional \`/onboard\` step, paste \`latest/SKILL.md\` once into Claude. Later \`/handoff\` overwrites \`latest-handoff.md\`. The skill is not printed again.
1277
+ After \`/inbox set\` or the optional \`/onboard\` step, paste \`latest/SKILL.md\` once into your desktop AI. Later \`/handoff\` overwrites \`latest-handoff.md\`. The skill is not printed again.
1266
1278
  `;
1267
1279
  }
1268
1280
  });
@@ -1481,12 +1493,12 @@ var init_context_doc = __esm({
1481
1493
  });
1482
1494
 
1483
1495
  // src/services/transcript.ts
1484
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync5, rmSync as rmSync2 } from "fs";
1496
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync5, rmSync as rmSync2 } from "fs";
1485
1497
  import { join as join4 } from "path";
1486
1498
  function rebindSessionTranscript(ctx) {
1487
1499
  if (!state || state.sessionId === ctx.sessionId) return;
1488
1500
  const priorJson = join4(getSessionsDir(), `${state.sessionId}.json`);
1489
- if (existsSync3(priorJson)) {
1501
+ if (existsSync4(priorJson)) {
1490
1502
  finalizeCurrentFile("switched session");
1491
1503
  } else {
1492
1504
  discardSessionTranscript(state.sessionId);
@@ -1507,7 +1519,7 @@ function discardSessionTranscript(sessionId) {
1507
1519
  function createState(sessionId) {
1508
1520
  const filePath = transcriptPathForSession(sessionId);
1509
1521
  let base = "";
1510
- if (existsSync3(filePath)) {
1522
+ if (existsSync4(filePath)) {
1511
1523
  try {
1512
1524
  base = readFileSync3(filePath, "utf-8").trimEnd() + "\n";
1513
1525
  } catch {
@@ -1608,12 +1620,12 @@ __export(connection_exports, {
1608
1620
  run: () => run,
1609
1621
  setActiveDbPath: () => setActiveDbPath
1610
1622
  });
1611
- import { mkdirSync as mkdirSync5, existsSync as existsSync4, rmSync as rmSync3 } from "fs";
1623
+ import { mkdirSync as mkdirSync5, existsSync as existsSync5, rmSync as rmSync3 } from "fs";
1612
1624
  import { dirname as dirname3, join as join5, resolve as resolve4 } from "path";
1613
1625
  function ensureDir2() {
1614
1626
  secureNtrpHome();
1615
1627
  const dir = dirname3(activeDbPath);
1616
- if (!existsSync4(dir)) {
1628
+ if (!existsSync5(dir)) {
1617
1629
  mkdirSync5(dir, { recursive: true, mode: 448 });
1618
1630
  }
1619
1631
  }
@@ -2881,14 +2893,14 @@ CREATE INDEX IF NOT EXISTS idx_health_readings_batch ON health_readings(upload_b
2881
2893
 
2882
2894
  // src/config/install.ts
2883
2895
  import { randomUUID as randomUUID3 } from "crypto";
2884
- import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
2896
+ import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
2885
2897
  import { join as join6 } from "path";
2886
2898
  function installPath() {
2887
2899
  return join6(ntrpHome(), "install.json");
2888
2900
  }
2889
2901
  function ensureDir3() {
2890
2902
  const dir = ntrpHome();
2891
- if (!existsSync5(dir)) {
2903
+ if (!existsSync6(dir)) {
2892
2904
  mkdirSync6(dir, { recursive: true });
2893
2905
  }
2894
2906
  }
@@ -2900,7 +2912,7 @@ function isValidInstall(value) {
2900
2912
  function ensureInstall() {
2901
2913
  if (cachedInstall) return cachedInstall;
2902
2914
  const path = installPath();
2903
- if (existsSync5(path)) {
2915
+ if (existsSync6(path)) {
2904
2916
  try {
2905
2917
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
2906
2918
  if (isValidInstall(parsed)) {
@@ -2933,7 +2945,7 @@ var init_install = __esm({
2933
2945
  });
2934
2946
 
2935
2947
  // src/config/progress-migrate.ts
2936
- import { existsSync as existsSync6, readFileSync as readFileSync5, renameSync as renameSync2, writeFileSync as writeFileSync7 } from "fs";
2948
+ import { existsSync as existsSync7, readFileSync as readFileSync5, renameSync as renameSync2, writeFileSync as writeFileSync7 } from "fs";
2937
2949
  import { join as join7 } from "path";
2938
2950
  function legacyStatePath() {
2939
2951
  return join7(ntrpHome(), "state.json");
@@ -2950,9 +2962,9 @@ function isValidLegacyState(value) {
2950
2962
  return s.schema_version === 1 && typeof s.total_minutes_saved === "number" && Array.isArray(s.credits) && Array.isArray(s.milestones_unlocked);
2951
2963
  }
2952
2964
  function migrateLegacyStateIfNeeded(installId) {
2953
- if (existsSync6(progressPath())) return null;
2965
+ if (existsSync7(progressPath())) return null;
2954
2966
  const legacyPath = legacyStatePath();
2955
- if (!existsSync6(legacyPath)) return null;
2967
+ if (!existsSync7(legacyPath)) return null;
2956
2968
  try {
2957
2969
  const parsed = JSON.parse(readFileSync5(legacyPath, "utf-8"));
2958
2970
  if (!isValidLegacyState(parsed)) return null;
@@ -3069,14 +3081,14 @@ var init_usage_backfill = __esm({
3069
3081
  });
3070
3082
 
3071
3083
  // src/config/progress.ts
3072
- import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
3084
+ import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync8 } from "fs";
3073
3085
  import { join as join8 } from "path";
3074
3086
  function progressPath2() {
3075
3087
  return join8(ntrpHome(), "progress.json");
3076
3088
  }
3077
3089
  function ensureDir4() {
3078
3090
  const dir = ntrpHome();
3079
- if (!existsSync7(dir)) {
3091
+ if (!existsSync8(dir)) {
3080
3092
  mkdirSync7(dir, { recursive: true });
3081
3093
  }
3082
3094
  }
@@ -3107,7 +3119,7 @@ function reconcileInstallId(state2) {
3107
3119
  }
3108
3120
  function readProgressFile() {
3109
3121
  const path = progressPath2();
3110
- if (!existsSync7(path)) return { state: null, changed: false };
3122
+ if (!existsSync8(path)) return { state: null, changed: false };
3111
3123
  try {
3112
3124
  const parsed = JSON.parse(readFileSync6(path, "utf-8"));
3113
3125
  if (!isValidProgress(parsed)) return { state: null, changed: false };
@@ -3828,7 +3840,7 @@ var init_time_bank = __esm({
3828
3840
  });
3829
3841
 
3830
3842
  // src/ai/llm/providers.ts
3831
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
3843
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
3832
3844
  import { join as join9 } from "path";
3833
3845
  function providersPath() {
3834
3846
  return join9(ntrpHome(), "providers.json");
@@ -3836,7 +3848,7 @@ function providersPath() {
3836
3848
  function loadCustomProviders() {
3837
3849
  if (cachedEntries) return cachedEntries;
3838
3850
  const path = providersPath();
3839
- if (!existsSync8(path)) {
3851
+ if (!existsSync9(path)) {
3840
3852
  cachedEntries = [];
3841
3853
  return cachedEntries;
3842
3854
  }
@@ -4602,7 +4614,7 @@ var init_openai_compat = __esm({
4602
4614
  });
4603
4615
 
4604
4616
  // src/ai/llm/models-cache.ts
4605
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
4617
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "fs";
4606
4618
  import { join as join10 } from "path";
4607
4619
  function cachePath() {
4608
4620
  return join10(ntrpHome(), "models.json");
@@ -4610,7 +4622,7 @@ function cachePath() {
4610
4622
  function loadFile() {
4611
4623
  if (cached) return cached;
4612
4624
  const path = cachePath();
4613
- if (!existsSync9(path)) {
4625
+ if (!existsSync10(path)) {
4614
4626
  cached = { version: 1, providers: {} };
4615
4627
  return cached;
4616
4628
  }
@@ -5228,7 +5240,7 @@ __export(pseudonymize_exports, {
5228
5240
  wipePrivacyStore: () => wipePrivacyStore
5229
5241
  });
5230
5242
  import { createHmac, randomBytes } from "crypto";
5231
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync10, rmSync as rmSync4, chmodSync as chmodSync2 } from "fs";
5243
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync10, rmSync as rmSync4, chmodSync as chmodSync2 } from "fs";
5232
5244
  import { join as join11 } from "path";
5233
5245
  function privacyDir() {
5234
5246
  return join11(ntrpHome(), "privacy");
@@ -5247,7 +5259,7 @@ function chmodQuiet2(path, mode) {
5247
5259
  }
5248
5260
  function ensurePrivacyDir() {
5249
5261
  const dir = privacyDir();
5250
- if (!existsSync10(dir)) {
5262
+ if (!existsSync11(dir)) {
5251
5263
  mkdirSync8(dir, { recursive: true, mode: 448 });
5252
5264
  }
5253
5265
  chmodQuiet2(dir, 448);
@@ -5284,7 +5296,7 @@ function rebuildIndexes() {
5284
5296
  function loadSecret() {
5285
5297
  ensurePrivacyDir();
5286
5298
  const path = secretPath();
5287
- if (existsSync10(path)) {
5299
+ if (existsSync11(path)) {
5288
5300
  const raw = readFileSync10(path);
5289
5301
  const buf = raw.length >= 32 ? raw.subarray(0, 32) : Buffer.from(raw.toString("utf-8").trim(), "hex");
5290
5302
  if (buf.length >= 16) return buf.length === 32 ? buf : Buffer.concat([buf], 32);
@@ -5298,7 +5310,7 @@ function loadLexicon() {
5298
5310
  ensurePrivacyDir();
5299
5311
  secret = loadSecret();
5300
5312
  entries = [];
5301
- if (existsSync10(lexiconPath())) {
5313
+ if (existsSync11(lexiconPath())) {
5302
5314
  try {
5303
5315
  const parsed = JSON.parse(readFileSync10(lexiconPath(), "utf-8"));
5304
5316
  if (parsed?.version === 1 && Array.isArray(parsed.entries)) {
@@ -5590,7 +5602,7 @@ function wipePrivacyStore() {
5590
5602
  loaded = false;
5591
5603
  dirty = false;
5592
5604
  const dir = privacyDir();
5593
- if (existsSync10(dir)) {
5605
+ if (existsSync11(dir)) {
5594
5606
  rmSync4(dir, { recursive: true, force: true });
5595
5607
  }
5596
5608
  }
@@ -5730,20 +5742,20 @@ var init_pseudonymize = __esm({
5730
5742
  });
5731
5743
 
5732
5744
  // src/config/profile.ts
5733
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, existsSync as existsSync11, mkdirSync as mkdirSync9 } from "fs";
5745
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, existsSync as existsSync12, mkdirSync as mkdirSync9 } from "fs";
5734
5746
  import { join as join12 } from "path";
5735
5747
  function profilePath() {
5736
5748
  return PROFILE_PATH;
5737
5749
  }
5738
5750
  function profileExists() {
5739
- return existsSync11(PROFILE_PATH);
5751
+ return existsSync12(PROFILE_PATH);
5740
5752
  }
5741
5753
  function isProfileConfigured(profile = loadProfile()) {
5742
5754
  if (!profile) return false;
5743
5755
  return profile.company_name.trim().length > 0;
5744
5756
  }
5745
5757
  function loadProfile() {
5746
- if (!existsSync11(PROFILE_PATH)) return null;
5758
+ if (!existsSync12(PROFILE_PATH)) return null;
5747
5759
  try {
5748
5760
  const parsed = JSON.parse(readFileSync11(PROFILE_PATH, "utf-8"));
5749
5761
  if (!parsed || typeof parsed !== "object") return null;
@@ -5770,7 +5782,7 @@ __export(lexicon_seed_exports, {
5770
5782
  seedOperatorIdentity: () => seedOperatorIdentity,
5771
5783
  wipePrivacyStore: () => wipePrivacyStore2
5772
5784
  });
5773
- import { existsSync as existsSync12 } from "fs";
5785
+ import { existsSync as existsSync13 } from "fs";
5774
5786
  function invalidateLexiconSeed() {
5775
5787
  dbSeedGeneration = -1;
5776
5788
  }
@@ -5832,7 +5844,7 @@ function seedOperatorIdentity(name, url) {
5832
5844
  }
5833
5845
  async function seedFromDuckDB() {
5834
5846
  const dbPath = getActiveDbPath();
5835
- if (!existsSync12(dbPath)) return;
5847
+ if (!existsSync13(dbPath)) return;
5836
5848
  const { all: all2, getConnectionGeneration: getConnectionGeneration2 } = await Promise.resolve().then(() => (init_connection(), connection_exports));
5837
5849
  const gen = getConnectionGeneration2();
5838
5850
  if (dbSeedGeneration !== -1 && gen === dbSeedGeneration) return;
@@ -6511,7 +6523,7 @@ var init_errors2 = __esm({
6511
6523
 
6512
6524
  // src/strategies/readers.ts
6513
6525
  import { createHash } from "crypto";
6514
- import { existsSync as existsSync13, readFileSync as readFileSync12 } from "fs";
6526
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "fs";
6515
6527
  import { extname, resolve as resolve5 } from "path";
6516
6528
  import { parse as parseYaml } from "yaml";
6517
6529
  import { PDFParse } from "pdf-parse";
@@ -6521,7 +6533,7 @@ async function readStrategyFile(pathOrDash) {
6521
6533
  return createDocument("stdin", null, text2, {});
6522
6534
  }
6523
6535
  const sourcePath = resolve5(pathOrDash);
6524
- if (!existsSync13(sourcePath)) {
6536
+ if (!existsSync14(sourcePath)) {
6525
6537
  throw new NtrpError("strategy_file_not_found", `Strategy file not found: ${pathOrDash}`, 2 /* Usage */);
6526
6538
  }
6527
6539
  const ext = extname(sourcePath).toLowerCase();
@@ -6590,7 +6602,7 @@ var init_readers = __esm({
6590
6602
  });
6591
6603
 
6592
6604
  // src/memory/knowledge.ts
6593
- import { existsSync as existsSync14, readFileSync as readFileSync13, appendFileSync as appendFileSync2, readdirSync as readdirSync2 } from "fs";
6605
+ import { existsSync as existsSync15, readFileSync as readFileSync13, appendFileSync as appendFileSync2, readdirSync as readdirSync2 } from "fs";
6594
6606
  import { join as join13 } from "path";
6595
6607
  import { randomUUID as randomUUID4 } from "crypto";
6596
6608
  function knowledgePath() {
@@ -6598,7 +6610,7 @@ function knowledgePath() {
6598
6610
  }
6599
6611
  function loadKnowledgeChunks() {
6600
6612
  const path = knowledgePath();
6601
- if (!existsSync14(path)) return [];
6613
+ if (!existsSync15(path)) return [];
6602
6614
  const out = [];
6603
6615
  for (const line of readFileSync13(path, "utf-8").split("\n")) {
6604
6616
  const trimmed = line.trim();
@@ -6621,7 +6633,7 @@ var init_knowledge = __esm({
6621
6633
  });
6622
6634
 
6623
6635
  // src/ai/privacy.ts
6624
- import { existsSync as existsSync15, mkdirSync as mkdirSync10, appendFileSync as appendFileSync3 } from "fs";
6636
+ import { existsSync as existsSync16, mkdirSync as mkdirSync10, appendFileSync as appendFileSync3 } from "fs";
6625
6637
  import { homedir as homedir4 } from "os";
6626
6638
  import { join as join14 } from "path";
6627
6639
  function scrubSensitiveText(text) {
@@ -6642,7 +6654,7 @@ function stripPII(obj) {
6642
6654
  return out;
6643
6655
  }
6644
6656
  function ensureAuditDir() {
6645
- if (!existsSync15(AUDIT_DIR)) {
6657
+ if (!existsSync16(AUDIT_DIR)) {
6646
6658
  mkdirSync10(AUDIT_DIR, { recursive: true });
6647
6659
  }
6648
6660
  }
@@ -6758,14 +6770,14 @@ __export(playbook_exports, {
6758
6770
  matchTriggeredPlays: () => matchTriggeredPlays,
6759
6771
  withKnownRecommendedPlays: () => withKnownRecommendedPlays
6760
6772
  });
6761
- import { existsSync as existsSync16, readFileSync as readFileSync14, appendFileSync as appendFileSync4 } from "fs";
6773
+ import { existsSync as existsSync17, readFileSync as readFileSync14, appendFileSync as appendFileSync4 } from "fs";
6762
6774
  import { join as join15 } from "path";
6763
6775
  function playsPath() {
6764
6776
  return join15(getMemoryDir(), PLAYS_FILE);
6765
6777
  }
6766
6778
  function getCustomPlays() {
6767
6779
  const path = playsPath();
6768
- if (!existsSync16(path)) return [];
6780
+ if (!existsSync17(path)) return [];
6769
6781
  const out = [];
6770
6782
  for (const line of readFileSync14(path, "utf-8").split("\n")) {
6771
6783
  const trimmed = line.trim();
@@ -7653,7 +7665,7 @@ __export(store_exports2, {
7653
7665
  rewriteJsonl: () => rewriteJsonl,
7654
7666
  scrubText: () => scrubText
7655
7667
  });
7656
- import { existsSync as existsSync17, readFileSync as readFileSync15, appendFileSync as appendFileSync5, readdirSync as readdirSync4, writeFileSync as writeFileSync12 } from "fs";
7668
+ import { existsSync as existsSync18, readFileSync as readFileSync15, appendFileSync as appendFileSync5, readdirSync as readdirSync4, writeFileSync as writeFileSync12 } from "fs";
7657
7669
  import { join as join18 } from "path";
7658
7670
  import { randomUUID as randomUUID5 } from "crypto";
7659
7671
  function memPath(file) {
@@ -7661,7 +7673,7 @@ function memPath(file) {
7661
7673
  }
7662
7674
  function readJsonl(file) {
7663
7675
  const path = memPath(file);
7664
- if (!existsSync17(path)) return [];
7676
+ if (!existsSync18(path)) return [];
7665
7677
  const out = [];
7666
7678
  for (const line of readFileSync15(path, "utf-8").split("\n")) {
7667
7679
  const trimmed = line.trim();
@@ -8040,7 +8052,7 @@ __export(context_exports, {
8040
8052
  transcriptPathForSession: () => transcriptPathForSession
8041
8053
  });
8042
8054
  import { basename as basename4, join as join19, resolve as resolve7, sep as sep4 } from "path";
8043
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, writeFileSync as writeFileSync13, readFileSync as readFileSync16, readdirSync as readdirSync5, statSync as statSync3, rmSync as rmSync5 } from "fs";
8055
+ import { existsSync as existsSync19, mkdirSync as mkdirSync11, writeFileSync as writeFileSync13, readFileSync as readFileSync16, readdirSync as readdirSync5, statSync as statSync3, rmSync as rmSync5 } from "fs";
8044
8056
  import { homedir as homedir6 } from "os";
8045
8057
  import { randomUUID as randomUUID6 } from "crypto";
8046
8058
  function isSessionStale(s) {
@@ -8059,14 +8071,14 @@ function ntrpHomeDir() {
8059
8071
  }
8060
8072
  function getSessionsDir() {
8061
8073
  const dir = join19(ntrpHomeDir(), "sessions");
8062
- if (!existsSync18(dir)) {
8074
+ if (!existsSync19(dir)) {
8063
8075
  mkdirSync11(dir, { recursive: true });
8064
8076
  }
8065
8077
  return dir;
8066
8078
  }
8067
8079
  function getDatasetsDir() {
8068
8080
  const dir = join19(ntrpHomeDir(), "datasets");
8069
- if (!existsSync18(dir)) {
8081
+ if (!existsSync19(dir)) {
8070
8082
  mkdirSync11(dir, { recursive: true });
8071
8083
  }
8072
8084
  return dir;
@@ -9659,7 +9671,7 @@ __export(play_outcomes_exports, {
9659
9671
  listPlayOutcomes: () => listPlayOutcomes,
9660
9672
  recordPlayOutcomes: () => recordPlayOutcomes
9661
9673
  });
9662
- import { existsSync as existsSync19, readFileSync as readFileSync17, appendFileSync as appendFileSync6 } from "fs";
9674
+ import { existsSync as existsSync20, readFileSync as readFileSync17, appendFileSync as appendFileSync6 } from "fs";
9663
9675
  import { join as join20 } from "path";
9664
9676
  import { randomUUID as randomUUID7 } from "crypto";
9665
9677
  function outcomesPath() {
@@ -9667,7 +9679,7 @@ function outcomesPath() {
9667
9679
  }
9668
9680
  function listPlayOutcomes() {
9669
9681
  const path = outcomesPath();
9670
- if (!existsSync19(path)) return [];
9682
+ if (!existsSync20(path)) return [];
9671
9683
  const out = [];
9672
9684
  for (const line of readFileSync17(path, "utf-8").split("\n")) {
9673
9685
  const trimmed = line.trim();
@@ -9888,12 +9900,12 @@ args: [show|set <path>|skill|clear]
9888
9900
  handler: ../commands/exports.ts
9889
9901
  ---
9890
9902
 
9891
- Set a folder that Claude Desktop or any desktop AI can read.
9903
+ Set a folder that any desktop AI can read (Claude, ChatGPT, Cursor, \u2026).
9892
9904
  NTRP copies each handoff to that folder.
9893
9905
  NTRP overwrites \`latest-handoff.md\` and \`latest-handoff-deck.md\`. The app then finds the newest file.
9894
9906
  NTRP also writes \`SKILL.md\`. That file holds finder instructions with your paths.
9895
9907
  Demo setup offers this once. Loading your own data (CSV ingest or \`/onboard\`) asks again if the folder is not set. Skip on that production step and NTRP will not ask again. Type \`/inbox skill\` or \`/handoff skill\` to print the finder. Type \`/inbox set\` at any time.
9896
- Paste that skill once into Claude, ChatGPT, or Cursor. Later handoffs need no new paste.
9908
+ Paste that skill once into Claude, ChatGPT, Cursor, or another desktop AI. Later handoffs need no new paste.
9897
9909
  \`INDEX.md\` in that folder links to the archive.
9898
9910
  A path outside ~/.ntrp needs a confirm. Handoffs carry analysis text.
9899
9911
  \`clear\` does not delete files. It only removes the config pointer.`
@@ -10244,9 +10256,9 @@ args: [<metric>|guide|list|tour]
10244
10256
  handler: ../commands/deepdive.ts
10245
10257
  ---
10246
10258
 
10247
- CLI slide deck: SaaS refresher, five vital signs (definition, formula, visual, dollar translation), then a how-to section (talk, ask, ship to Claude, loop).
10248
- Bare \`/deepdive\` runs the full onboarding tour. Type \`/deepdive guide\` to jump to how to use NTRP (includes teaching Claude the inbox once).
10249
- Type \`/deepdive handoff\` for the ship-to-Claude slide. Type \`/deepdive <metric>\` to jump to one metric card.
10259
+ CLI slide deck: SaaS refresher, five vital signs (definition, formula, visual, dollar translation), then a how-to section (talk, ask, ship to your AI, loop).
10260
+ Bare \`/deepdive\` runs the full onboarding tour. Type \`/deepdive guide\` to jump to how to use NTRP (includes teaching the inbox once).
10261
+ Type \`/deepdive handoff\` for the ship-to-AI slide. Type \`/deepdive <metric>\` to jump to one metric card.
10250
10262
  Type \`/deepdive list\` to print the catalog. Works without an AI key. Re-run anytime from the homescreen.
10251
10263
  Live values overlay when an analysis exists.`
10252
10264
  },
@@ -10567,7 +10579,7 @@ Remaining nuances merge into a custom_context paragraph that flows into all AI s
10567
10579
  });
10568
10580
 
10569
10581
  // src/ai/prompt-parts.ts
10570
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
10582
+ import { existsSync as existsSync21, readFileSync as readFileSync18 } from "fs";
10571
10583
  import { join as join21 } from "path";
10572
10584
  function buildCompanyProfileBlock() {
10573
10585
  const p = loadProfile();
@@ -10588,7 +10600,7 @@ function buildCompanyProfileBlock() {
10588
10600
  function loadAnalystFile() {
10589
10601
  const path = join21(ntrpHome(), ANALYST_FILE_NAME);
10590
10602
  try {
10591
- if (!existsSync20(path)) return null;
10603
+ if (!existsSync21(path)) return null;
10592
10604
  const raw = sanitizeExternalText(readFileSync18(path, "utf-8").trim());
10593
10605
  if (!raw) return null;
10594
10606
  if (raw.length <= ANALYST_FILE_MAX_CHARS) return raw;
@@ -11110,7 +11122,7 @@ function buildUserMessage(input) {
11110
11122
  async function* streamFindings(input, ctx) {
11111
11123
  assertReplAi(ctx);
11112
11124
  const userMessage = buildUserMessage(input);
11113
- let meta = { model_used: "unknown", provider_used: "anthropic", failover: false };
11125
+ let meta = { model_used: "unknown", provider_used: "unknown", failover: false };
11114
11126
  const scanner = new StreamingJsonArrayParser();
11115
11127
  let streamed = 0;
11116
11128
  for await (const event of streamWithFailover(
@@ -14683,7 +14695,7 @@ var init_markdown = __esm({
14683
14695
  import chalk11 from "chalk";
14684
14696
  function formatLlmAttribution(meta) {
14685
14697
  if (!meta.model_used) return null;
14686
- const provider = meta.provider_used ?? "anthropic";
14698
+ const provider = meta.provider_used ?? "unknown";
14687
14699
  let line = `via ${formatModelLabel(provider, meta.model_used)}`;
14688
14700
  if (meta.failover) {
14689
14701
  line += " (auto-failover)";
@@ -18015,7 +18027,7 @@ async function* strategistPlanSession(options) {
18015
18027
  })
18016
18028
  }
18017
18029
  ];
18018
- let lastMeta = { provider_used: "anthropic", model_used: "unknown" };
18030
+ let lastMeta = { provider_used: "unknown", model_used: "unknown" };
18019
18031
  const loopGuard = new ToolLoopGuard();
18020
18032
  const allowedTools = new Set(tools2.map((t) => t.name));
18021
18033
  const callLlm = async (surface, withTools, maxTokens = STAGE_MAX_TOKENS) => {
@@ -23276,16 +23288,16 @@ var init_scenario_fit = __esm({
23276
23288
  });
23277
23289
 
23278
23290
  // src/demo/taxonomy-cache.ts
23279
- import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, existsSync as existsSync21, mkdirSync as mkdirSync13, unlinkSync as unlinkSync3 } from "fs";
23291
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, existsSync as existsSync22, mkdirSync as mkdirSync13, unlinkSync as unlinkSync3 } from "fs";
23280
23292
  import { homedir as homedir7 } from "os";
23281
23293
  import { join as join24 } from "path";
23282
23294
  function ensureDir5() {
23283
- if (!existsSync21(NTRP_DIR4)) {
23295
+ if (!existsSync22(NTRP_DIR4)) {
23284
23296
  mkdirSync13(NTRP_DIR4, { recursive: true });
23285
23297
  }
23286
23298
  }
23287
23299
  function loadCachedTaxonomy(profile) {
23288
- if (!existsSync21(TAXONOMY_PATH)) return null;
23300
+ if (!existsSync22(TAXONOMY_PATH)) return null;
23289
23301
  try {
23290
23302
  const parsed = JSON.parse(readFileSync19(TAXONOMY_PATH, "utf-8"));
23291
23303
  if (!parsed || typeof parsed !== "object") return null;
@@ -23762,7 +23774,7 @@ __export(inbox_setup_exports, {
23762
23774
  shouldOfferInboxSkillSetup: () => shouldOfferInboxSkillSetup
23763
23775
  });
23764
23776
  import chalk27 from "chalk";
23765
- import { existsSync as existsSync22 } from "fs";
23777
+ import { existsSync as existsSync23 } from "fs";
23766
23778
  function markDemoOffered() {
23767
23779
  setConfigValue("ai-inbox-nudge-seen", "true");
23768
23780
  }
@@ -23779,7 +23791,7 @@ function shouldOfferInboxSkillSetup(beat) {
23779
23791
  return !hasProductionOffered();
23780
23792
  }
23781
23793
  function printSkipHint(beat) {
23782
- const setCmd = paint("accent", "/inbox set ~/Documents/Claude/ntrp-inbox");
23794
+ const setCmd = paint("accent", `/inbox set ${defaultAiInboxDirDisplay()}`);
23783
23795
  const skillCmd = paint("accent", "/inbox skill");
23784
23796
  if (beat === "demo") {
23785
23797
  console.log(
@@ -23791,13 +23803,15 @@ function printSkipHint(beat) {
23791
23803
  " " + chalk27.dim("Skipped. NTRP will not ask again. Type ") + setCmd + chalk27.dim(" then ") + skillCmd + chalk27.dim(" at any time.")
23792
23804
  );
23793
23805
  }
23794
- async function reuseInboxFolderIfPresent(session, beat, folderPath = defaultAiInboxDir()) {
23806
+ async function reuseInboxFolderIfPresent(session, beat, folderPath) {
23795
23807
  if (getAiInboxDir()) return false;
23796
- if (!existsSync22(folderPath)) return false;
23797
- console.log(" " + chalk27.dim("Pickup folder still on disk: ") + folderPath);
23808
+ const candidates = folderPath ? [folderPath] : [.../* @__PURE__ */ new Set([defaultAiInboxDir(), legacyAiInboxDir()])];
23809
+ const existing = candidates.find((p) => existsSync23(p));
23810
+ if (!existing) return false;
23811
+ console.log(" " + chalk27.dim("Pickup folder still on disk: ") + existing);
23798
23812
  const reuse = await session.confirm("Reuse this pickup folder?", true);
23799
23813
  if (!reuse) return false;
23800
- const resolved = setAiInboxDir(folderPath);
23814
+ const resolved = setAiInboxDir(existing);
23801
23815
  markDemoOffered();
23802
23816
  if (beat === "production") markProductionOffered();
23803
23817
  console.log();
@@ -23812,7 +23826,7 @@ async function offerInboxSkillSetup(session, opts = {}) {
23812
23826
  const beat = opts.beat ?? "production";
23813
23827
  if (!shouldOfferInboxSkillSetup(beat)) return;
23814
23828
  console.log();
23815
- console.log(" " + bold("Teach Claude where handoffs live"));
23829
+ console.log(" " + bold("Teach your AI where handoffs live"));
23816
23830
  console.log(
23817
23831
  " " + chalk27.dim(
23818
23832
  "Optional. NTRP copies every handoff into one folder. You paste instructions once; later /handoff just writes the file."
@@ -23823,7 +23837,10 @@ async function offerInboxSkillSetup(session, opts = {}) {
23823
23837
  }
23824
23838
  console.log();
23825
23839
  if (await reuseInboxFolderIfPresent(session, beat)) return;
23826
- const want = await session.confirm("Set a pickup folder for Claude, ChatGPT, or Cursor?", true);
23840
+ const want = await session.confirm(
23841
+ "Set a pickup folder for Claude, ChatGPT, Cursor, or another desktop AI?",
23842
+ true
23843
+ );
23827
23844
  if (!want) {
23828
23845
  if (beat === "demo") markDemoOffered();
23829
23846
  else markProductionOffered();
@@ -23855,10 +23872,12 @@ async function offerInboxSkillSetup(session, opts = {}) {
23855
23872
  console.log(" " + chalk27.dim(`Synced ${n} recent export${n === 1 ? "" : "s"}.`));
23856
23873
  }
23857
23874
  console.log(
23858
- " " + chalk27.dim("Paste this skill into Claude once. Later, tell Claude to open the latest NTRP handoff.")
23875
+ " " + chalk27.dim(
23876
+ "Paste this skill into your desktop AI once. Later, tell it to open the latest NTRP handoff."
23877
+ )
23859
23878
  );
23860
23879
  printStandingSkill();
23861
- await session.askPressEnter("Paste the skill into Claude. Then continue");
23880
+ await session.askPressEnter("Paste the skill into your AI. Then continue");
23862
23881
  console.log(" " + chalk27.dim("Done. Later handoffs write to that folder. The skill is not printed again."));
23863
23882
  console.log();
23864
23883
  }
@@ -23893,7 +23912,7 @@ __export(ingest_exports, {
23893
23912
  handler: () => handler3
23894
23913
  });
23895
23914
  import chalk28 from "chalk";
23896
- import { readFileSync as readFileSync20, existsSync as existsSync23 } from "fs";
23915
+ import { readFileSync as readFileSync20, existsSync as existsSync24 } from "fs";
23897
23916
  import { basename as basename6 } from "path";
23898
23917
  async function handler3(args, ctx) {
23899
23918
  const { positional, flags } = parseArgs(args, [
@@ -23917,7 +23936,7 @@ async function handler3(args, ctx) {
23917
23936
  console.error(chalk28.dim(" /ingest --demo [--scenario <name>]"));
23918
23937
  process.exit(1);
23919
23938
  }
23920
- if (!existsSync23(file)) {
23939
+ if (!existsSync24(file)) {
23921
23940
  console.error(chalk28.red(` File not found: ${file}`));
23922
23941
  process.exit(1);
23923
23942
  }
@@ -24303,7 +24322,7 @@ __export(ingest_chat_exports, {
24303
24322
  loadDemoFromChat: () => loadDemoFromChat,
24304
24323
  looksLikeFilePath: () => looksLikeFilePath
24305
24324
  });
24306
- import { existsSync as existsSync24 } from "fs";
24325
+ import { existsSync as existsSync25 } from "fs";
24307
24326
  import { basename as basename7, resolve as resolve9 } from "path";
24308
24327
  import { homedir as homedir8 } from "os";
24309
24328
  import chalk30 from "chalk";
@@ -24323,11 +24342,11 @@ function extractFilePath(input) {
24323
24342
  const m = trimmed.match(re);
24324
24343
  if (m?.[1]) {
24325
24344
  const p = expandPath(m[1]);
24326
- if (existsSync24(p)) return p;
24345
+ if (existsSync25(p)) return p;
24327
24346
  }
24328
24347
  if (!m?.[1] && re.test(trimmed) && trimmed.toLowerCase().endsWith(".csv")) {
24329
24348
  const p = expandPath(trimmed.replace(/^["']|["']$/g, ""));
24330
- if (existsSync24(p)) return p;
24349
+ if (existsSync25(p)) return p;
24331
24350
  }
24332
24351
  }
24333
24352
  return null;
@@ -25246,9 +25265,9 @@ async function handleGetSessionBrief(input) {
25246
25265
  if (!target) {
25247
25266
  return { error: `No session matching "${raw}".` };
25248
25267
  }
25249
- const { existsSync: existsSync27, readFileSync: readFileSync23 } = await import("fs");
25268
+ const { existsSync: existsSync28, readFileSync: readFileSync23 } = await import("fs");
25250
25269
  const briefPath = contextDocPathForSession2(target.id);
25251
- if (!existsSync27(briefPath)) {
25270
+ if (!existsSync28(briefPath)) {
25252
25271
  return {
25253
25272
  session_id: target.id,
25254
25273
  error: "No context brief on disk for this session (created before brief storage existed).",
@@ -25819,7 +25838,7 @@ async function* agenticFindings(computeResult, divergences, options) {
25819
25838
  const priorMessages = priorRaw.length > 0 && typeof priorRaw[0] === "object" && priorRaw[0] !== null && "content" in priorRaw[0] ? normalizeThread(priorRaw) : priorRaw;
25820
25839
  const conversational = mode === "fresh" || mode === "think";
25821
25840
  const messages = conversational && priorMessages.length > 0 && options.userQuestion ? [...priorMessages, { role: "user", content: options.userQuestion }] : [{ role: "user", content: initialContext }];
25822
- let lastMeta = { provider_used: "anthropic", model_used: "unknown" };
25841
+ let lastMeta = { provider_used: "unknown", model_used: "unknown" };
25823
25842
  const loopGuard = new ToolLoopGuard();
25824
25843
  const allowedTools = new Set(tools2.map((t) => t.name));
25825
25844
  async function callLlm(msgs, tokens, withTools) {
@@ -26220,7 +26239,7 @@ var init_ask = __esm({
26220
26239
  });
26221
26240
 
26222
26241
  // src/services/setup.ts
26223
- import { existsSync as existsSync25, mkdirSync as mkdirSync14, readFileSync as readFileSync21, writeFileSync as writeFileSync16 } from "fs";
26242
+ import { existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync21, writeFileSync as writeFileSync16 } from "fs";
26224
26243
  import { join as join25 } from "path";
26225
26244
  function setupCheck() {
26226
26245
  const home = ntrpHome();
@@ -26279,11 +26298,11 @@ var init_setup = __esm({
26279
26298
  });
26280
26299
 
26281
26300
  // src/version.ts
26282
- import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
26301
+ import { existsSync as existsSync27, readFileSync as readFileSync22 } from "fs";
26283
26302
  import { dirname as dirname5, join as join26 } from "path";
26284
26303
  import { fileURLToPath } from "url";
26285
26304
  function readVersionFromPackageJson(packageJsonPath) {
26286
- if (!existsSync26(packageJsonPath)) return null;
26305
+ if (!existsSync27(packageJsonPath)) return null;
26287
26306
  try {
26288
26307
  const pkg = JSON.parse(readFileSync22(packageJsonPath, "utf-8"));
26289
26308
  if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;