@sonnechasser/ntrp 2.1.11 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1308,6 +1308,34 @@ function voiceHealthGloss(status, prefs) {
1308
1308
  }
1309
1309
  });
1310
1310
  }
1311
+ function voiceExportPickupNudge(input, prefs) {
1312
+ const v = voice(prefs);
1313
+ const phrase = EXPORT_PICKUP_PHRASE;
1314
+ if (input.inboxReady) {
1315
+ return pick(v, {
1316
+ robotic: `Open your desktop AI. Tell it to ${phrase}.`,
1317
+ composed: `Open your desktop AI and tell it to ${phrase}.`,
1318
+ casual: `This terminal is not your AI. Open it and tell it to ${phrase}.`,
1319
+ loose: {
1320
+ light: `Written. Open your desktop AI and tell it to ${phrase}.`,
1321
+ medium: `This CLI cannot see your AI. Open it. Tell it to ${phrase}.`,
1322
+ dark: `The file is on disk. Your AI is not in this window. Open it and ${phrase}.`,
1323
+ heavy: `NTRP wrote it. This window is not your AI. Open the desktop app and ${phrase}.`
1324
+ }
1325
+ });
1326
+ }
1327
+ return pick(v, {
1328
+ robotic: `Your desktop AI cannot see this folder. Type /inbox set, then tell that AI to ${phrase}.`,
1329
+ composed: `These files are on disk. Set a pickup folder (/inbox set), then tell your desktop AI to ${phrase}.`,
1330
+ casual: `Your AI cannot see this folder. Type /inbox set, then tell it to ${phrase}.`,
1331
+ loose: {
1332
+ light: `Your AI cannot see this folder yet. Type /inbox set, then tell it to ${phrase}.`,
1333
+ medium: `This folder is invisible to your AI. Type /inbox set, then tell it to ${phrase}.`,
1334
+ dark: `Your AI cannot see this terminal. Type /inbox set, then ${phrase}.`,
1335
+ heavy: `This window is not your AI. Type /inbox set, then ${phrase}.`
1336
+ }
1337
+ });
1338
+ }
1311
1339
  function voiceHandoffAddendum(prefs) {
1312
1340
  const v = voice(prefs);
1313
1341
  return [
@@ -1322,11 +1350,13 @@ function pick(prefs, map) {
1322
1350
  if (typeof entry === "string") return entry;
1323
1351
  return entry[prefs.roast];
1324
1352
  }
1353
+ var EXPORT_PICKUP_PHRASE;
1325
1354
  var init_copy = __esm({
1326
1355
  "src/voice/copy.ts"() {
1327
1356
  "use strict";
1328
1357
  init_catalog();
1329
1358
  init_prefs();
1359
+ EXPORT_PICKUP_PHRASE = "pick up the latest NTRP handoff";
1330
1360
  }
1331
1361
  });
1332
1362
 
@@ -2533,6 +2563,9 @@ function maybePrintAiInboxNudge() {
2533
2563
  )
2534
2564
  );
2535
2565
  }
2566
+ function printExportPickupNudge(opts) {
2567
+ console.log(" " + chalk7.dim(voiceExportPickupNudge(opts)));
2568
+ }
2536
2569
  function printStandingSkill() {
2537
2570
  persistStandingSkill();
2538
2571
  const loc = handoffLocations();
@@ -2558,6 +2591,7 @@ var init_handoff_skill = __esm({
2558
2591
  init_store();
2559
2592
  init_theme();
2560
2593
  init_export_kinds();
2594
+ init_copy();
2561
2595
  STANDING_SKILL_NAME = "SKILL.md";
2562
2596
  ARCHIVE_PICKUP_NAME = "pickup.md";
2563
2597
  INBOX_PICKUP_NAME = "latest-pickup.md";
@@ -9680,7 +9714,7 @@ ${strategy.objective}
9680
9714
  ` : "";
9681
9715
  const workstreamSection = strategy.workstreams.length > 0 ? `
9682
9716
  ## Workstreams
9683
- ${strategy.workstreams.map(formatWorkstream).join("\n")}
9717
+ ${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
9684
9718
  ` : "";
9685
9719
  const constraintsSection = filterOperatorLines(strategy.constraints).length > 0 ? `
9686
9720
  ## Constraints
@@ -9736,7 +9770,7 @@ ${strategy.objective}
9736
9770
  ` : "";
9737
9771
  const workstreamSection = strategy.workstreams.length > 0 ? `
9738
9772
  ## Workstreams
9739
- ${strategy.workstreams.map(formatWorkstream).join("\n")}
9773
+ ${strategy.workstreams.map(formatWorkstreamMarkdown).join("\n")}
9740
9774
  ` : "";
9741
9775
  const assumptions = filterOperatorLines(strategy.assumptions);
9742
9776
  const assumptionsSection = assumptions.length > 0 ? `
@@ -9783,7 +9817,7 @@ ${frontmatter}
9783
9817
  ].filter((p) => p != null && String(p).length > 0);
9784
9818
  return parts.join("\n\n") + "\n";
9785
9819
  }
9786
- function formatWorkstream(ws) {
9820
+ function formatWorkstreamMarkdown(ws) {
9787
9821
  const lines = [];
9788
9822
  lines.push(`### ${ws.order}. ${ws.title}`);
9789
9823
  lines.push(`- Problem: ${ws.problem}`);
@@ -11146,6 +11180,7 @@ function resetContextForSwitch(ctx, opts) {
11146
11180
  ctx.thinkState = opts.thinkState;
11147
11181
  ctx.pendingAsk = opts.pendingAsk;
11148
11182
  ctx.lastCraftJobId = opts.lastCraftJobId;
11183
+ ctx.lastStrategyBrief = void 0;
11149
11184
  ctx.gapAudit = void 0;
11150
11185
  ctx.deliverIntent = false;
11151
11186
  ctx.computeInProgress = false;
@@ -23835,20 +23870,7 @@ function renderCraftHandoffMarkdown(opts) {
23835
23870
  lines.push("## Workstreams");
23836
23871
  lines.push("");
23837
23872
  for (const ws of plan.workstreams) {
23838
- lines.push(`### ${ws.order}. ${ws.title}`);
23839
- lines.push("");
23840
- lines.push(`- Problem: ${ws.problem}`);
23841
- if (ws.rationale && !isGenericWorkstreamRationale(ws.rationale)) {
23842
- lines.push(`- Why this order: ${ws.rationale}`);
23843
- }
23844
- if (ws.actions[0]) lines.push(`- First action (48h): ${ws.actions[0]}`);
23845
- lines.push(`- Effort: ~${Math.round(ws.effort_hours)} team-hours`);
23846
- lines.push(
23847
- `- Exam: ${ws.expected_outcome.metric} ${ws.expected_outcome.baseline} \u2192 ${ws.expected_outcome.target_range} by ${ws.expected_outcome.check_date} (${ws.expected_outcome.measured_by})`
23848
- );
23849
- lines.push(
23850
- `- Contingency: if ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}) \u2192 ${ws.contingency.fallback}`
23851
- );
23873
+ lines.push(formatWorkstreamMarkdown(ws).trimEnd());
23852
23874
  lines.push("");
23853
23875
  }
23854
23876
  if (opts.roundtableDigest) {
@@ -24128,93 +24150,149 @@ var init_llm_attribution = __esm({
24128
24150
 
24129
24151
  // src/output/strategy-brief.ts
24130
24152
  import chalk17 from "chalk";
24131
- function printWrapped(text, width, prefix = INDENT, style) {
24153
+ function collectWrapped(lines, text, width, prefix = INDENT, style) {
24132
24154
  for (const line of wrapWords(text, width)) {
24133
- console.log(prefix + (style ? style(line) : line));
24155
+ lines.push(prefix + (style ? style(line) : line));
24134
24156
  }
24135
24157
  }
24136
- function outcomeLine(outcome) {
24137
- return `${chalk17.bold(outcome.metric)}: ${outcome.baseline} ${chalk17.dim("\u2192")} ${chalk17.bold(outcome.target_range)} ${chalk17.dim(`by ${outcome.check_date}`)}`;
24158
+ function outcomeLine(outcome, dateStyle) {
24159
+ const by = dateStyle === "accent" ? paint("accent", `by ${outcome.check_date}`) : chalk17.dim(`by ${outcome.check_date}`);
24160
+ return `${chalk17.bold(outcome.metric)}: ${outcome.baseline} ${chalk17.dim("\u2192")} ${chalk17.bold(outcome.target_range)} ${by}`;
24138
24161
  }
24139
- function printWorkstream(ws, width) {
24140
- console.log(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk17.bold(ws.title)}`);
24141
- printWrapped(ws.problem, width - 5, INDENT + " ", (s) => chalk17.dim(s));
24142
- console.log(`${INDENT} ${outcomeLine(ws.expected_outcome)}`);
24162
+ function soonestByDue(items) {
24163
+ if (items.length === 0) return void 0;
24164
+ return [...items].sort((a, b) => a.due.localeCompare(b.due) || 0)[0];
24165
+ }
24166
+ function altitudeLine(text) {
24167
+ const sentence = findingHeadline(text) || text.trim();
24168
+ return truncateVisible(sentence, FOH_PROSE_MAX);
24169
+ }
24170
+ function coverageLine(plan, stats) {
24171
+ const totalHours = plan.workstreams.reduce((sum, ws) => sum + ws.effort_hours, 0);
24172
+ const hours = `~${Math.round(totalHours)} total team hours across ${plan.workstreams.length} workstream${plan.workstreams.length === 1 ? "" : "s"}`;
24173
+ if (stats.total_targets <= 0) return chalk17.dim(hours);
24174
+ const coverage = `${stats.measurable_targets} of ${stats.total_targets} targets can be measured with current data`;
24175
+ const coverageStyled = stats.measurable_targets === stats.total_targets ? paint("success", coverage) : chalk17.hex("#eab308")(coverage);
24176
+ return `${coverageStyled}${chalk17.dim(` \xB7 ${hours}`)}`;
24177
+ }
24178
+ function renderFohWorkstream(ws, width) {
24179
+ const lines = [];
24180
+ lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk17.bold(ws.title)}`);
24181
+ lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "accent")}`);
24182
+ const next = soonestByDue(ws.milestones);
24183
+ if (next) {
24184
+ lines.push(`${INDENT} Next ${paint("accent", next.due)} ${next.label}`);
24185
+ }
24186
+ const ship = soonestByDue(ws.deliverables);
24187
+ if (ship) {
24188
+ lines.push(`${INDENT} Ship ${paint("accent", ship.due)} ${ship.label}`);
24189
+ }
24190
+ lines.push("");
24191
+ return lines;
24192
+ }
24193
+ function renderBohWorkstream(ws, width) {
24194
+ const lines = [];
24195
+ lines.push(`${INDENT}${paint("accent", `${ws.order}.`)} ${chalk17.bold(ws.title)}`);
24196
+ collectWrapped(lines, ws.problem, width - 5, INDENT + " ", (s) => chalk17.dim(s));
24197
+ lines.push(`${INDENT} ${outcomeLine(ws.expected_outcome, "dim")}`);
24143
24198
  for (const li of ws.leading_indicators) {
24144
- console.log(`${INDENT} ${chalk17.dim("Lead:")} ${outcomeLine(li)}`);
24199
+ lines.push(`${INDENT} ${chalk17.dim("Lead:")} ${outcomeLine(li, "dim")}`);
24145
24200
  }
24146
24201
  if (ws.actions.length > 0) {
24147
- console.log(`${INDENT} ${chalk17.dim("First steps")}`);
24202
+ lines.push(`${INDENT} ${chalk17.dim("First steps")}`);
24148
24203
  for (const action of ws.actions.slice(0, 3)) {
24149
- printWrapped(`- ${action}`, width - 7, INDENT + " ", (s) => chalk17.dim(s));
24204
+ collectWrapped(lines, `- ${action}`, width - 7, INDENT + " ", (s) => chalk17.dim(s));
24150
24205
  }
24151
24206
  }
24152
24207
  if (ws.milestones.length > 0) {
24153
- console.log(`${INDENT} ${chalk17.dim("Milestones")}`);
24208
+ lines.push(`${INDENT} ${chalk17.dim("Milestones")}`);
24154
24209
  for (const m of ws.milestones) {
24155
- console.log(`${INDENT} ${paint("accent", m.due)} ${m.label}`);
24210
+ lines.push(`${INDENT} ${paint("accent", m.due)} ${m.label}`);
24156
24211
  }
24157
24212
  }
24158
24213
  if (ws.deliverables.length > 0) {
24159
- console.log(`${INDENT} ${chalk17.dim("Deliverables")}`);
24214
+ lines.push(`${INDENT} ${chalk17.dim("Deliverables")}`);
24160
24215
  for (const d of ws.deliverables) {
24161
- console.log(`${INDENT} ${chalk17.dim("[ ]")} ${d.label} ${chalk17.dim(`due ${d.due}`)}`);
24216
+ lines.push(`${INDENT} ${chalk17.dim("[ ]")} ${d.label} ${chalk17.dim(`due ${d.due}`)}`);
24162
24217
  }
24163
24218
  }
24164
- printWrapped(
24219
+ collectWrapped(
24220
+ lines,
24165
24221
  `If ${ws.contingency.trigger} (check ${ws.contingency.trigger_check_date}), then ${ws.contingency.fallback}`,
24166
24222
  width - 5,
24167
24223
  INDENT + " ",
24168
24224
  (s) => chalk17.dim(s)
24169
24225
  );
24170
- console.log(`${INDENT} ${chalk17.dim(`~${Math.round(ws.effort_hours)} team hours`)}`);
24171
- console.log();
24226
+ lines.push(`${INDENT} ${chalk17.dim(`~${Math.round(ws.effort_hours)} team hours`)}`);
24227
+ lines.push("");
24228
+ return lines;
24229
+ }
24230
+ function renderOperatorList(title, items, width) {
24231
+ const lines = [];
24232
+ if (items.length === 0) return lines;
24233
+ lines.push(`${INDENT}${chalk17.dim(title)}`);
24234
+ for (const item of items) {
24235
+ collectWrapped(lines, `- ${item}`, width - 2, INDENT, (s) => chalk17.dim(s));
24236
+ }
24237
+ lines.push("");
24238
+ return lines;
24172
24239
  }
24173
- function printStrategyBrief(plan, stats) {
24240
+ function renderStrategyBrief(plan, stats, opts = {}) {
24241
+ const mode = opts.mode ?? "foh";
24174
24242
  const width = Math.min(termWidth() - 4, 92);
24175
- console.log();
24176
- console.log(
24243
+ const lines = [""];
24244
+ lines.push(
24177
24245
  `${INDENT}${chalk17.bold(`Strategy brief \u2014 ${plan.title}`)} ${chalk17.dim(`confidence ${plan.confidence.toFixed(2)} \xB7 ${plan.priority} priority \xB7 review ${plan.review_cadence.toLowerCase()}`)}`
24178
24246
  );
24179
- console.log(INDENT + chalk17.dim(hr(width)));
24180
- console.log(`${INDENT}${chalk17.dim("The Call")}`);
24181
- printWrapped(plan.summary_30k, width);
24182
- console.log();
24183
- printWrapped(`Objective: ${plan.objective}`, width, INDENT, (s) => paint("accent", s));
24184
- console.log();
24185
- for (const ws of plan.workstreams) {
24186
- printWorkstream(ws, width);
24187
- }
24188
- const constraints = filterOperatorLines(plan.constraints);
24189
- if (constraints.length > 0) {
24190
- console.log(`${INDENT}${chalk17.dim("Constraints")}`);
24191
- for (const c of constraints) {
24192
- printWrapped(`- ${c}`, width - 2, INDENT, (s) => chalk17.dim(s));
24247
+ if (mode === "foh") {
24248
+ collectWrapped(lines, altitudeLine(plan.summary_30k), width, INDENT);
24249
+ lines.push("");
24250
+ collectWrapped(lines, altitudeLine(plan.objective), width, INDENT, (s) => paint("accent", s));
24251
+ lines.push("");
24252
+ for (const ws of plan.workstreams) {
24253
+ lines.push(...renderFohWorkstream(ws, width));
24193
24254
  }
24194
- console.log();
24195
- }
24196
- const assumptions = filterOperatorLines(plan.assumptions);
24197
- if (assumptions.length > 0) {
24198
- console.log(`${INDENT}${chalk17.dim("Assumptions (not verified, not targets)")}`);
24199
- for (const a of assumptions) {
24200
- printWrapped(`- ${a}`, width - 2, INDENT, (s) => chalk17.dim(s));
24255
+ } else {
24256
+ lines.push(INDENT + chalk17.dim(hr(width)));
24257
+ lines.push(`${INDENT}${chalk17.dim("The Call")}`);
24258
+ collectWrapped(lines, plan.summary_30k, width);
24259
+ lines.push("");
24260
+ collectWrapped(lines, `Objective: ${plan.objective}`, width, INDENT, (s) => paint("accent", s));
24261
+ lines.push("");
24262
+ for (const ws of plan.workstreams) {
24263
+ lines.push(...renderBohWorkstream(ws, width));
24201
24264
  }
24202
- console.log();
24265
+ lines.push(
24266
+ ...renderOperatorList("Constraints", filterOperatorLines(plan.constraints), width)
24267
+ );
24268
+ lines.push(
24269
+ ...renderOperatorList(
24270
+ "Assumptions (not verified, not targets)",
24271
+ filterOperatorLines(plan.assumptions),
24272
+ width
24273
+ )
24274
+ );
24275
+ lines.push(...renderOperatorList("Risks", filterOperatorLines(plan.risks), width));
24203
24276
  }
24204
- const risks = filterOperatorLines(plan.risks);
24205
- if (risks.length > 0) {
24206
- console.log(`${INDENT}${chalk17.dim("Risks")}`);
24207
- for (const r of risks) {
24208
- printWrapped(`- ${r}`, width - 2, INDENT, (s) => chalk17.dim(s));
24209
- }
24210
- console.log();
24277
+ lines.push(INDENT + chalk17.dim(hr(width)));
24278
+ lines.push(`${INDENT}${coverageLine(plan, stats)}`);
24279
+ if (opts.hint) {
24280
+ lines.push(`${INDENT}${chalk17.dim(STRATEGY_BRIEF_EXPAND_HINT)}`);
24211
24281
  }
24212
- const totalHours = plan.workstreams.reduce((sum, ws) => sum + ws.effort_hours, 0);
24213
- console.log(INDENT + chalk17.dim(hr(width)));
24214
- const coverage = stats.total_targets > 0 ? `${stats.measurable_targets} of ${stats.total_targets} targets can be measured with current data` : "No measured targets";
24215
- const coverageStyled = stats.total_targets > 0 && stats.measurable_targets === stats.total_targets ? paint("success", coverage) : chalk17.hex("#eab308")(coverage);
24216
- console.log(`${INDENT}${coverageStyled}${chalk17.dim(` \xB7 ~${Math.round(totalHours)} total team hours across ${plan.workstreams.length} workstream${plan.workstreams.length === 1 ? "" : "s"}`)}`);
24217
- console.log();
24282
+ lines.push("");
24283
+ return lines.join("\n");
24284
+ }
24285
+ function printStrategyBrief(plan, stats, opts = {}) {
24286
+ console.log(renderStrategyBrief(plan, stats, opts));
24287
+ }
24288
+ function resolveStrategyBriefMode(host) {
24289
+ return isVerbose(host.execution) ? "boh" : "foh";
24290
+ }
24291
+ function presentStrategyBrief(host, plan, stats, notices = [], meta = {}) {
24292
+ const mode = resolveStrategyBriefMode(host);
24293
+ printStrategyBrief(plan, stats, { mode, hint: mode === "foh" && !host.oneShot });
24294
+ printStrategyBriefFooter(notices, meta);
24295
+ host.lastStrategyBrief = { plan, stats, notices, meta };
24218
24296
  }
24219
24297
  function printStrategyBriefFooter(notices, meta) {
24220
24298
  if (usedGroundedFallback(notices)) {
@@ -24233,7 +24311,10 @@ function printCraftWrapUp(opts) {
24233
24311
  );
24234
24312
  }
24235
24313
  const handoff = opts.inbox_path ?? opts.handoff_path;
24236
- if (handoff) console.log(INDENT + chalk17.dim(handoff));
24314
+ if (handoff) {
24315
+ console.log(INDENT + chalk17.dim(handoff));
24316
+ printExportPickupNudge({ inboxReady: Boolean(opts.inbox_path) });
24317
+ }
24237
24318
  } else {
24238
24319
  console.log(INDENT + paint("accent", "Best so far."));
24239
24320
  const path = opts.library_path ?? opts.handoff_path ?? opts.inbox_path;
@@ -24253,15 +24334,20 @@ function printCraftWrapUp(opts) {
24253
24334
  }
24254
24335
  console.log();
24255
24336
  }
24256
- var INDENT;
24337
+ var STRATEGY_BRIEF_EXPAND_HINT, INDENT, FOH_PROSE_MAX;
24257
24338
  var init_strategy_brief = __esm({
24258
24339
  "src/output/strategy-brief.ts"() {
24259
24340
  "use strict";
24260
24341
  init_theme();
24261
24342
  init_layout();
24343
+ init_formatters();
24262
24344
  init_strategy_signal();
24263
24345
  init_llm_attribution();
24346
+ init_handoff_skill();
24347
+ init_verbosity();
24348
+ STRATEGY_BRIEF_EXPAND_HINT = "Type more to show the full brief.";
24264
24349
  INDENT = " ";
24350
+ FOH_PROSE_MAX = 220;
24265
24351
  }
24266
24352
  });
24267
24353
 
@@ -24622,8 +24708,7 @@ async function runStrategistSession(ctx) {
24622
24708
  console.log();
24623
24709
  return;
24624
24710
  }
24625
- printStrategyBrief(plan, stats);
24626
- printStrategyBriefFooter(notices, meta);
24711
+ presentStrategyBrief(ctx, plan, stats, notices, meta);
24627
24712
  console.log();
24628
24713
  let saved = false;
24629
24714
  if (ctx.rl) {
@@ -24682,14 +24767,14 @@ async function ensureSnapshot(ctx) {
24682
24767
  }
24683
24768
  function printCraftReplResult(ctx, result, objective) {
24684
24769
  if (result.plan) {
24685
- printStrategyBrief(result.plan, {
24770
+ presentStrategyBrief(ctx, result.plan, {
24686
24771
  measurable_targets: result.measurable_targets,
24687
24772
  total_targets: result.total_targets
24688
- });
24773
+ }, result.notices, result.usage);
24689
24774
  } else {
24690
24775
  console.log(" " + chalk18.dim("(No plan produced)"));
24776
+ printStrategyBriefFooter(result.notices, result.usage);
24691
24777
  }
24692
- printStrategyBriefFooter(result.notices, result.usage);
24693
24778
  if (result.library_path) creditStrategySession(ctx);
24694
24779
  printCraftWrapUp({
24695
24780
  status: result.status,
@@ -25542,7 +25627,7 @@ function matchDefinitionExplainer(input) {
25542
25627
  }
25543
25628
  return getMetricExplainer(id);
25544
25629
  }
25545
- function printWrapped2(text, indent = " ") {
25630
+ function printWrapped(text, indent = " ") {
25546
25631
  for (const line of wrapWords(text, 78)) {
25547
25632
  console.log(indent + line);
25548
25633
  }
@@ -25559,10 +25644,10 @@ function tryKeylessDefinitionAnswer(ctx, input) {
25559
25644
  console.log(" " + chalk23.dim(explainer.tagline));
25560
25645
  console.log();
25561
25646
  console.log(" " + bold("Meaning"));
25562
- printWrapped2(explainer.meaning, " ");
25647
+ printWrapped(explainer.meaning, " ");
25563
25648
  console.log();
25564
25649
  console.log(" " + bold("How NTRP calculates it"));
25565
- printWrapped2(explainer.how_computed, " ");
25650
+ printWrapped(explainer.how_computed, " ");
25566
25651
  for (const f of explainer.formula_lines) {
25567
25652
  console.log(" " + paint("accent", f));
25568
25653
  }
@@ -26310,6 +26395,7 @@ var init_smoke_protocol = __esm({
26310
26395
  // src/cli/nl.ts
26311
26396
  var nl_exports = {};
26312
26397
  __export(nl_exports, {
26398
+ runExploreExpandAnswer: () => runExploreExpandAnswer,
26313
26399
  runNaturalLanguage: () => runNaturalLanguage
26314
26400
  });
26315
26401
  import chalk25 from "chalk";
@@ -26317,16 +26403,16 @@ async function runNaturalLanguage(input, ctx) {
26317
26403
  if (isSmokeProtocolTrigger(input)) {
26318
26404
  recordMessage(ctx, "user", input);
26319
26405
  console.log();
26320
- const spinner2 = makeSpinner("Running smoke protocol\u2026");
26406
+ const spinner = makeSpinner("Running smoke protocol\u2026");
26321
26407
  try {
26322
26408
  const result = await runSmokeProtocol(input, ctx);
26323
- spinner2.succeed("Smoke protocol complete");
26409
+ spinner.succeed("Smoke protocol complete");
26324
26410
  printAnswer(result.answer);
26325
26411
  recordMessage(ctx, "agent", result.answer);
26326
26412
  console.log();
26327
26413
  return extractSummary2(result.answer);
26328
26414
  } catch (err) {
26329
- spinner2.fail("Smoke protocol failed");
26415
+ spinner.fail("Smoke protocol failed");
26330
26416
  console.error(" " + chalk25.red(String(err.message ?? err)));
26331
26417
  console.log();
26332
26418
  return;
@@ -26341,6 +26427,22 @@ async function runNaturalLanguage(input, ctx) {
26341
26427
  return;
26342
26428
  }
26343
26429
  recordMessage(ctx, "user", input);
26430
+ const responseMode = resolveExploreResponseMode(input, ctx, ctx.conversation.length);
26431
+ return runExploreAgent(ctx, {
26432
+ userQuestion: input,
26433
+ responseMode,
26434
+ showExpandHint: responseMode === "brief"
26435
+ });
26436
+ }
26437
+ async function runExploreExpandAnswer(ctx, question) {
26438
+ return runExploreAgent(ctx, {
26439
+ userQuestion: question,
26440
+ responseMode: "deep",
26441
+ showExpandHint: false
26442
+ });
26443
+ }
26444
+ async function runExploreAgent(ctx, opts) {
26445
+ const { userQuestion, responseMode, showExpandHint } = opts;
26344
26446
  let snapshot = ctx.snapshot.computeResult;
26345
26447
  if (!snapshot) {
26346
26448
  const metricsFirst = prefersMetricsFirstContext(ctx);
@@ -26357,7 +26459,7 @@ async function runNaturalLanguage(input, ctx) {
26357
26459
  }
26358
26460
  }
26359
26461
  console.log();
26360
- const memoryBlock = await buildMemoryBlock(input).catch((err) => {
26462
+ const memoryBlock = await buildMemoryBlock(userQuestion).catch((err) => {
26361
26463
  debugError("nl.buildMemoryBlock", err);
26362
26464
  return "";
26363
26465
  });
@@ -26368,13 +26470,12 @@ async function runNaturalLanguage(input, ctx) {
26368
26470
  setAgentContext(ctx);
26369
26471
  try {
26370
26472
  const analysisBlock = buildAnalysisBlock(ctx);
26371
- const responseMode = resolveExploreResponseMode(input, ctx, ctx.conversation.length);
26372
26473
  const conversationBlock = getConversationPhaseBlock(ctx, { responseMode });
26373
26474
  const bundle = await loadSessionAnalysisBundle();
26374
26475
  const sessionArtifact = hasAnyAnalysis(bundle) ? buildExploreContextBlock(bundle, ctx) : "";
26375
26476
  for await (const event of agenticFindings(snapshot, ctx.snapshot.divergences, {
26376
26477
  mode: "fresh",
26377
- userQuestion: input,
26478
+ userQuestion,
26378
26479
  sessionContext: ctx.resumedSessionSummary,
26379
26480
  includeMetrics: true,
26380
26481
  analysisBlock,
@@ -26415,7 +26516,7 @@ async function runNaturalLanguage(input, ctx) {
26415
26516
  const { isLlmAuthError: isLlmAuthError2 } = await Promise.resolve().then(() => (init_errors2(), errors_exports));
26416
26517
  if (isLlmAuthError2(err)) {
26417
26518
  const { queuePendingAsk: queuePendingAsk2 } = await Promise.resolve().then(() => (init_pending_ask(), pending_ask_exports));
26418
- if (!ctx.pendingAsk) queuePendingAsk2(ctx, input, "explore");
26519
+ if (!ctx.pendingAsk) queuePendingAsk2(ctx, userQuestion, "explore");
26419
26520
  const { recoverFromAuthFailure: recoverFromAuthFailure2 } = await Promise.resolve().then(() => (init_auth_recovery(), auth_recovery_exports));
26420
26521
  await recoverFromAuthFailure2(ctx, err);
26421
26522
  return;
@@ -26440,8 +26541,18 @@ async function runNaturalLanguage(input, ctx) {
26440
26541
  saveSessionState(ctx);
26441
26542
  }
26442
26543
  creditNlAnswer(ctx, Math.floor(ctx.messages.length / 2));
26443
- recordAnalysis({ question: input, answer: lastAnswer, tools: toolsUsed, session_id: ctx.sessionId });
26444
- ctx.lastExchange = { question: input, answer: lastAnswer };
26544
+ recordAnalysis({
26545
+ question: userQuestion,
26546
+ answer: lastAnswer,
26547
+ tools: toolsUsed,
26548
+ session_id: ctx.sessionId
26549
+ });
26550
+ ctx.lastExchange = { question: userQuestion, answer: lastAnswer, mode: responseMode };
26551
+ if (showExpandHint) {
26552
+ console.log(
26553
+ " " + chalk25.dim("Type ") + chalk25.cyan("expand") + chalk25.dim(" for more reasoning.")
26554
+ );
26555
+ }
26445
26556
  }
26446
26557
  console.log();
26447
26558
  const { promptQueuedAiStrategist: promptQueuedAiStrategist2 } = await Promise.resolve().then(() => (init_strategist_flow(), strategist_flow_exports));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonnechasser/ntrp",
3
- "version": "2.1.11",
3
+ "version": "2.2.0",
4
4
  "description": "GTM Health Diagnostic CLI — local pipeline analysis tool",
5
5
  "homepage": "https://ntrp.sonnechasser.com",
6
6
  "repository": {