@sonnechasser/ntrp 1.3.9 → 1.4.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.
Files changed (3) hide show
  1. package/dist/index.js +1107 -324
  2. package/dist/mcp/server.js +797 -131
  3. package/package.json +2 -1
@@ -1369,6 +1369,26 @@ function buildSessionContextDoc(file, opts = {}) {
1369
1369
  if (file.strategist.origin) lines.push(`- Origin: ${file.strategist.origin}`);
1370
1370
  lines.push("");
1371
1371
  }
1372
+ if (file.think) {
1373
+ lines.push("## Think (in flight)");
1374
+ lines.push("");
1375
+ lines.push(`- Step: ${file.think.step}`);
1376
+ if (file.think.seed) lines.push(`- Seed: ${file.think.seed}`);
1377
+ if (file.think.origin) lines.push(`- Origin: ${file.think.origin}`);
1378
+ if (file.think.open_questions?.length) {
1379
+ lines.push("- Open questions:");
1380
+ for (const q of file.think.open_questions) lines.push(` - ${q}`);
1381
+ }
1382
+ if (file.think.challenged_assumptions?.length) {
1383
+ lines.push("- Challenged assumptions:");
1384
+ for (const a of file.think.challenged_assumptions) lines.push(` - ${a}`);
1385
+ }
1386
+ if (file.think.working_hypotheses?.length) {
1387
+ lines.push("- Working hypotheses:");
1388
+ for (const h of file.think.working_hypotheses) lines.push(` - ${h}`);
1389
+ }
1390
+ lines.push("");
1391
+ }
1372
1392
  lines.push("## Deliverables");
1373
1393
  lines.push("");
1374
1394
  if (file.deliverables && file.deliverables.length > 0) {
@@ -8090,6 +8110,7 @@ function initContext(oneShot, execution) {
8090
8110
  snapshot: { computeResult: null, divergences: [] },
8091
8111
  messages: [],
8092
8112
  conversation: [],
8113
+ thinkConversation: [],
8093
8114
  stage: "new",
8094
8115
  deliverables: [],
8095
8116
  analysis: defaultSessionAnalysis(),
@@ -8110,12 +8131,14 @@ function buildSessionFileSnapshot(ctx) {
8110
8131
  if (ctx.dataset) file.dataset = ctx.dataset;
8111
8132
  if (ctx.deliverables.length > 0) file.deliverables = ctx.deliverables;
8112
8133
  if (ctx.conversation.length > 0) file.thread = ctx.conversation;
8134
+ if (ctx.thinkConversation.length > 0) file.think_thread = ctx.thinkConversation;
8113
8135
  if (ctx.resumedFromId) file.resumed_from = ctx.resumedFromId;
8114
8136
  if (ctx.analysis) file.analysis = ctx.analysis;
8115
8137
  if (ctx.scope) file.scope = ctx.scope;
8116
8138
  if (ctx.attachments && ctx.attachments.length > 0) file.attachments = ctx.attachments;
8117
8139
  if (ctx.llm && Object.keys(ctx.llm).length > 0) file.llm = ctx.llm;
8118
8140
  if (ctx.strategistState) file.strategist = ctx.strategistState;
8141
+ if (ctx.thinkState) file.think = ctx.thinkState;
8119
8142
  if (ctx.pendingAsk) file.pending_ask = ctx.pendingAsk;
8120
8143
  return file;
8121
8144
  }
@@ -8242,6 +8265,9 @@ function loadSessionFile(id) {
8242
8265
  if (session.thread?.length) {
8243
8266
  session.thread = normalizeThread(session.thread);
8244
8267
  }
8268
+ if (session.think_thread?.length) {
8269
+ session.think_thread = normalizeThread(session.think_thread);
8270
+ }
8245
8271
  return session;
8246
8272
  } catch {
8247
8273
  return null;
@@ -8444,6 +8470,9 @@ async function finalizeSession(ctx, stage) {
8444
8470
  if (ctx.conversation.length > 0) {
8445
8471
  file.thread = ctx.conversation;
8446
8472
  }
8473
+ if (ctx.thinkConversation.length > 0) {
8474
+ file.think_thread = ctx.thinkConversation;
8475
+ }
8447
8476
  if (ctx.analysis) {
8448
8477
  file.analysis = ctx.analysis;
8449
8478
  }
@@ -8459,6 +8488,9 @@ async function finalizeSession(ctx, stage) {
8459
8488
  if (ctx.strategistState) {
8460
8489
  file.strategist = ctx.strategistState;
8461
8490
  }
8491
+ if (ctx.thinkState) {
8492
+ file.think = ctx.thinkState;
8493
+ }
8462
8494
  if (ctx.pendingAsk) {
8463
8495
  file.pending_ask = ctx.pendingAsk;
8464
8496
  }
@@ -8520,6 +8552,7 @@ function resetContextForSwitch(ctx, opts) {
8520
8552
  ctx.sessionName = opts.sessionName;
8521
8553
  ctx.messages = opts.messages;
8522
8554
  ctx.conversation = opts.conversation ?? [];
8555
+ ctx.thinkConversation = opts.thinkConversation ?? [];
8523
8556
  ctx.resumedFromId = opts.resumedFromId;
8524
8557
  ctx.resumedSessionSummary = opts.resumedSessionSummary;
8525
8558
  ctx.stage = opts.stage ?? "new";
@@ -8530,6 +8563,7 @@ function resetContextForSwitch(ctx, opts) {
8530
8563
  ctx.attachments = opts.attachments ?? [];
8531
8564
  ctx.llm = opts.llm;
8532
8565
  ctx.strategistState = opts.strategistState;
8566
+ ctx.thinkState = opts.thinkState;
8533
8567
  ctx.pendingAsk = opts.pendingAsk;
8534
8568
  ctx.gapAudit = void 0;
8535
8569
  ctx.deliverIntent = false;
@@ -10215,6 +10249,21 @@ Bare \`/deepdive\` runs the full onboarding tour. Type \`/deepdive guide\` to ju
10215
10249
  Type \`/deepdive handoff\` for the ship-to-Claude slide. Type \`/deepdive <metric>\` to jump to one metric card.
10216
10250
  Type \`/deepdive list\` to print the catalog. Works without an AI key. Re-run anytime from the homescreen.
10217
10251
  Live values overlay when an analysis exists.`
10252
+ },
10253
+ {
10254
+ name: "thinkwithme",
10255
+ raw: `---
10256
+ name: thinkwithme
10257
+ description: Socratic co-thinking channel \u2014 explore and pressure-test
10258
+ section: Navigation
10259
+ args: [topic]
10260
+ handler: ../commands/thinkwithme.ts
10261
+ ---
10262
+
10263
+ Open a dedicated \`think \u203A\` channel to explore ideas, challenge assumptions, and pull evidence from your data.
10264
+ Bare \`/thinkwithme\` enters the channel. Type \`/thinkwithme <topic>\` to seed the first turn.
10265
+ Requires an analysis and an AI key (\`/connect\`). Type \`done\` or \`cancel\` to return to ask \u203A.
10266
+ When you are ready to commit to a plan, say so or the partner can hand off to \`/strategy\`.`
10218
10267
  },
10219
10268
  {
10220
10269
  name: "status",
@@ -11041,13 +11090,21 @@ function buildFreshNlTools() {
11041
11090
  if (isWebRetrievalEnabled()) tools2.push(WEB_SEARCH_TOOL);
11042
11091
  return tools2;
11043
11092
  }
11093
+ function buildThinkTools() {
11094
+ const tools2 = [
11095
+ ...AGENTIC_TOOLS,
11096
+ ...THINK_CHANNEL_TOOLS
11097
+ ];
11098
+ if (isWebRetrievalEnabled()) tools2.push(WEB_SEARCH_TOOL);
11099
+ return tools2;
11100
+ }
11044
11101
  function allRegisteredToolSchemas() {
11045
- return [...AGENTIC_TOOLS, ...CONVERSATION_TOOLS, WEB_SEARCH_TOOL];
11102
+ return [...AGENTIC_TOOLS, ...CONVERSATION_TOOLS, ...THINK_CHANNEL_TOOLS, WEB_SEARCH_TOOL];
11046
11103
  }
11047
11104
  function getToolSchema(name) {
11048
11105
  return allRegisteredToolSchemas().find((t) => t.name === name);
11049
11106
  }
11050
- var WEB_SEARCH_TOOL, CONVERSATION_TOOLS, AGENTIC_TOOLS;
11107
+ var WEB_SEARCH_TOOL, CONVERSATION_TOOLS, THINK_CHANNEL_TOOLS, AGENTIC_TOOLS;
11051
11108
  var init_tool_schemas = __esm({
11052
11109
  "src/ai/tool-schemas.ts"() {
11053
11110
  "use strict";
@@ -11124,6 +11181,64 @@ var init_tool_schemas = __esm({
11124
11181
  }
11125
11182
  }
11126
11183
  ];
11184
+ THINK_CHANNEL_TOOLS = [
11185
+ {
11186
+ name: "draft_handoff",
11187
+ description: "Draft a handoff prompt combining analysis numbers and conversation thread.",
11188
+ parameters: {
11189
+ type: "object",
11190
+ properties: {
11191
+ target: {
11192
+ type: "string",
11193
+ enum: ["deck", "asana", "clay", "plan"],
11194
+ description: "Deliverable type. Defaults to plan."
11195
+ }
11196
+ }
11197
+ }
11198
+ },
11199
+ {
11200
+ name: "draft_strategy",
11201
+ description: "Hand off to the strategist brain from the think channel when the user is ready to commit to a plan. Do not improvise a multi-week roadmap inline \u2014 call this instead.",
11202
+ parameters: {
11203
+ type: "object",
11204
+ properties: {
11205
+ objective: {
11206
+ type: "string",
11207
+ maxLength: 2e3,
11208
+ description: "The measurable objective to plan toward, in the user's terms."
11209
+ }
11210
+ },
11211
+ required: ["objective"]
11212
+ }
11213
+ },
11214
+ {
11215
+ name: "update_think_scratch",
11216
+ description: "Update the think-channel working scratch: open questions, challenged assumptions, and working hypotheses. Pass only the arrays you want to replace; omitted fields stay unchanged. Call when the conversation advances a question, surfaces a challenged assumption, or forms a hypothesis.",
11217
+ parameters: {
11218
+ type: "object",
11219
+ properties: {
11220
+ open_questions: {
11221
+ type: "array",
11222
+ items: { type: "string", maxLength: 500 },
11223
+ maxItems: 12,
11224
+ description: "Current open questions (replaces the list when provided)."
11225
+ },
11226
+ challenged_assumptions: {
11227
+ type: "array",
11228
+ items: { type: "string", maxLength: 500 },
11229
+ maxItems: 12,
11230
+ description: "Assumptions that have been pressure-tested (replaces when provided)."
11231
+ },
11232
+ working_hypotheses: {
11233
+ type: "array",
11234
+ items: { type: "string", maxLength: 500 },
11235
+ maxItems: 12,
11236
+ description: "Working hypotheses under consideration (replaces when provided)."
11237
+ }
11238
+ }
11239
+ }
11240
+ }
11241
+ ];
11127
11242
  AGENTIC_TOOLS = [
11128
11243
  {
11129
11244
  name: "get_health_summary",
@@ -13515,6 +13630,8 @@ function resolveRecommendedAction(ctx) {
13515
13630
  return { submit: "yes", hint: "yes" };
13516
13631
  case "strategize":
13517
13632
  return ctx.strategistState?.step === "objective_confirm" ? { submit: "yes", hint: "yes" } : null;
13633
+ case "think":
13634
+ return null;
13518
13635
  default:
13519
13636
  return null;
13520
13637
  }
@@ -13549,6 +13666,9 @@ function resolveConversationPhase(ctx) {
13549
13666
  if (ctx.strategistState && ctx.strategistState.step !== "awaiting_analysis" && ctx.strategistState.step !== "awaiting_connect") {
13550
13667
  return "strategize";
13551
13668
  }
13669
+ if (ctx.thinkState?.step === "active") {
13670
+ return "think";
13671
+ }
13552
13672
  if (isAnalysisReady(ctx)) return "explore";
13553
13673
  const scope = ctx.scope;
13554
13674
  if (scope?.confirmed_at) {
@@ -13573,6 +13693,8 @@ function formatPhaseLabel(phase) {
13573
13693
  return "setup";
13574
13694
  case "explore":
13575
13695
  return "ready to ask";
13696
+ case "think":
13697
+ return "thinking together";
13576
13698
  default:
13577
13699
  return phase.replace(/_/g, " ");
13578
13700
  }
@@ -13591,8 +13713,14 @@ function buildConversationPrompt(ctx) {
13591
13713
  const modeTag = mode === "brief" ? "brief" : "deep";
13592
13714
  const stack = canUseReplAi(ctx) ? formatActiveStackShort(ctx) : "no engine";
13593
13715
  const strategyWait = ctx.strategistState?.step === "awaiting_connect" ? chalk8.dim(" \xB7 strategy after /connect") : "";
13716
+ const thinkWait = ctx.thinkState?.step === "awaiting_connect" ? chalk8.dim(" \xB7 think after /connect") : "";
13594
13717
  const enterHint2 = action ? chalk8.dim(` \xB7 \u23CE ${action.hint}`) : "";
13595
- return paint("accent", `ask${scope} \u203A `) + chalk8.dim(`${modeTag} \xB7 ${stack}`) + strategyWait + enterHint2 + " ";
13718
+ return paint("accent", `ask${scope} \u203A `) + chalk8.dim(`${modeTag} \xB7 ${stack}`) + strategyWait + thinkWait + enterHint2 + " ";
13719
+ }
13720
+ if (phase === "think") {
13721
+ const stack = canUseReplAi(ctx) ? formatActiveStackShort(ctx) : "no engine";
13722
+ const enterHint2 = action ? chalk8.dim(` \xB7 \u23CE ${action.hint}`) : "";
13723
+ return paint("accent", `think${scope} \u203A `) + chalk8.dim(stack) + enterHint2 + " ";
13596
13724
  }
13597
13725
  const enterHint = action ? chalk8.dim(`\u23CE ${action.hint} `) : "";
13598
13726
  return paint("accent", `${label.replace(" \u203A", "")}${scope} \u203A `) + enterHint;
@@ -13633,6 +13761,7 @@ var init_phase = __esm({
13633
13761
  awaiting_data: "data \u203A",
13634
13762
  compute: "\u2026",
13635
13763
  explore: "ask \u203A",
13764
+ think: "think \u203A",
13636
13765
  strategize: "strategy \u203A",
13637
13766
  deliver: "ship \u203A"
13638
13767
  };
@@ -18304,45 +18433,372 @@ var init_strategist_flow = __esm({
18304
18433
  }
18305
18434
  });
18306
18435
 
18307
- // src/conversation/gap-card.ts
18436
+ // src/services/think.ts
18437
+ var think_exports = {};
18438
+ __export(think_exports, {
18439
+ runThinkTurn: () => runThinkTurn
18440
+ });
18308
18441
  import chalk18 from "chalk";
18442
+ async function runThinkTurn(input, ctx) {
18443
+ assertReplAi(ctx);
18444
+ let snapshot = ctx.snapshot.computeResult;
18445
+ if (!snapshot) {
18446
+ const metricsFirst = prefersMetricsFirstContext(ctx);
18447
+ const spinner2 = makeSpinner(metricsFirst ? "Loading session context\u2026" : "Computing vital signs\u2026");
18448
+ try {
18449
+ snapshot = await computeFullHealth();
18450
+ ctx.snapshot.computeResult = snapshot;
18451
+ const divInput = snapshot.segments.map((s) => ({
18452
+ segmentId: s.segment.id,
18453
+ segmentName: s.segment.name,
18454
+ result: s.result
18455
+ }));
18456
+ ctx.snapshot.divergences = detectDivergences(snapshot.aggregate, divInput).divergences;
18457
+ spinner2.succeed(metricsFirst ? "Session context ready" : "Health snapshot ready");
18458
+ } catch (err) {
18459
+ spinner2.fail("Could not compute health snapshot");
18460
+ console.error(" " + chalk18.red(String(err.message ?? err)));
18461
+ console.log(" " + chalk18.dim("Run ") + paint("accent", "/new") + chalk18.dim(" \u2192 pick Demo to load sample data."));
18462
+ console.log();
18463
+ return;
18464
+ }
18465
+ }
18466
+ console.log();
18467
+ const memoryBlock = await buildMemoryBlock(input).catch(() => "");
18468
+ const spinner = makeSpinner("Thinking with you\u2026");
18469
+ let lastAnswer = "";
18470
+ let rawHistory = [];
18471
+ const toolsUsed = [];
18472
+ setAgentContext(ctx);
18473
+ try {
18474
+ const analysisBlock = buildAnalysisBlock(ctx);
18475
+ const conversationBlock = getConversationPhaseBlock(ctx);
18476
+ const bundle = await loadSessionAnalysisBundle();
18477
+ const sessionArtifact = hasAnyAnalysis(bundle) ? buildExploreContextBlock(bundle, ctx) : "";
18478
+ for await (const event of agenticFindings(snapshot, ctx.snapshot.divergences, {
18479
+ mode: "think",
18480
+ userQuestion: input,
18481
+ sessionContext: ctx.resumedSessionSummary,
18482
+ includeMetrics: true,
18483
+ analysisBlock,
18484
+ conversationBlock,
18485
+ sessionArtifact,
18486
+ priorMessages: ctx.thinkConversation,
18487
+ memoryBlock,
18488
+ ctx
18489
+ })) {
18490
+ switch (event.type) {
18491
+ case "tool_call":
18492
+ toolsUsed.push(event.name);
18493
+ spinner.text = `Querying ${event.name}\u2026`;
18494
+ break;
18495
+ case "thinking":
18496
+ spinner.stop();
18497
+ console.log(" " + chalk18.dim.italic(event.text));
18498
+ spinner.start("Thinking with you\u2026");
18499
+ break;
18500
+ case "answer":
18501
+ spinner.stop();
18502
+ lastAnswer = event.text;
18503
+ printMarkdown(event.text, { indent: 2 });
18504
+ break;
18505
+ case "finding":
18506
+ spinner.stop();
18507
+ printFindingInline(event.finding);
18508
+ break;
18509
+ case "done":
18510
+ spinner.stop();
18511
+ rawHistory = event.conversation_history;
18512
+ break;
18513
+ }
18514
+ }
18515
+ } catch (err) {
18516
+ spinner.fail("Error while thinking");
18517
+ console.error(" " + chalk18.red(String(err.message ?? err)));
18518
+ console.log();
18519
+ return;
18520
+ } finally {
18521
+ setAgentContext(null);
18522
+ }
18523
+ if (rawHistory.length > 0) {
18524
+ ctx.thinkConversation = distillThread(rawHistory);
18525
+ }
18526
+ if (!lastAnswer) {
18527
+ console.log(" " + chalk18.dim("(no answer returned)"));
18528
+ } else {
18529
+ recordMessage(ctx, "agent", lastAnswer);
18530
+ saveSessionState(ctx);
18531
+ creditNlAnswer(ctx, Math.floor(ctx.messages.length / 2));
18532
+ recordAnalysis({
18533
+ question: `[think] ${input}`,
18534
+ answer: lastAnswer,
18535
+ tools: toolsUsed,
18536
+ session_id: ctx.sessionId
18537
+ });
18538
+ ctx.lastExchange = { question: input, answer: lastAnswer };
18539
+ }
18540
+ console.log();
18541
+ return lastAnswer ? extractSummary(lastAnswer) : void 0;
18542
+ }
18543
+ function extractSummary(text) {
18544
+ const plain = text.replace(/#{1,6}\s+/g, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^[-*]\s+/gm, "").trim();
18545
+ const sentenceMatch = plain.match(/^(.+?[.!?])(?:\s|$)/);
18546
+ const sentence = sentenceMatch ? sentenceMatch[1] : plain.split("\n")[0];
18547
+ if (sentence.length <= 60) return sentence;
18548
+ return sentence.slice(0, 60).replace(/\s+\S*$/, "") + "\u2026";
18549
+ }
18550
+ function printFindingInline(finding) {
18551
+ const sev = finding.severity;
18552
+ console.log();
18553
+ console.log(
18554
+ " " + severityPaint(sev)(sev.toUpperCase()) + " " + (finding.finding ?? "").slice(0, 120)
18555
+ );
18556
+ }
18557
+ var init_think = __esm({
18558
+ "src/services/think.ts"() {
18559
+ "use strict";
18560
+ init_spinner();
18561
+ init_context2();
18562
+ init_phase();
18563
+ init_agent_context();
18564
+ init_agentic_loop();
18565
+ init_thread();
18566
+ init_store2();
18567
+ init_health_score();
18568
+ init_divergence();
18569
+ init_repl_api();
18570
+ init_theme();
18571
+ init_markdown();
18572
+ init_session_analysis();
18573
+ init_time_bank();
18574
+ }
18575
+ });
18576
+
18577
+ // src/conversation/think-flow.ts
18578
+ var think_flow_exports = {};
18579
+ __export(think_flow_exports, {
18580
+ clearThinkFlow: () => clearThinkFlow,
18581
+ extractThinkSeed: () => extractThinkSeed,
18582
+ handleThinkFlow: () => handleThinkFlow,
18583
+ isThinkIntent: () => isThinkIntent,
18584
+ queueThinkForAnalysis: () => queueThinkForAnalysis,
18585
+ resumeThinkAfterCompute: () => resumeThinkAfterCompute,
18586
+ resumeThinkAfterConnect: () => resumeThinkAfterConnect,
18587
+ startThinkFlow: () => startThinkFlow
18588
+ });
18589
+ import chalk19 from "chalk";
18590
+ function isThinkIntent(input) {
18591
+ const line = input.trim();
18592
+ if (!line) return false;
18593
+ if (isShipIntent(line)) return false;
18594
+ if (isStrategistIntent(line)) return false;
18595
+ return THINK_INTENT_RE.test(line);
18596
+ }
18597
+ function extractThinkSeed(input) {
18598
+ const cleaned = input.trim().replace(/^(hey|ok|okay|please|can you|could you|help me|let'?s|i want to|i'?d like to)\s+/i, "").replace(/^(think\s+with\s+me|pressure[- ]?test|dig\s+into|think\s+through)\s*(about|on|around|this|:)?\s*/i, "").replace(/^(what\s+am\s+i\s+missing\s*(about|on|with|here)?)\s*/i, "").trim();
18599
+ return cleaned.length >= 4 ? cleaned : input.trim();
18600
+ }
18601
+ function queueThinkForAnalysis(ctx, opts) {
18602
+ ctx.thinkState = {
18603
+ step: "awaiting_analysis",
18604
+ seed: opts.seed,
18605
+ origin: opts.origin,
18606
+ started_at: (/* @__PURE__ */ new Date()).toISOString()
18607
+ };
18608
+ saveSessionState(ctx);
18609
+ console.log();
18610
+ console.log(
18611
+ " " + chalk19.dim("Think session queued. NTRP opens the channel after analysis.")
18612
+ );
18613
+ if (opts.origin !== "nl") {
18614
+ console.log(
18615
+ " " + chalk19.dim("Type what to look at. Paste a CSV path. Or type ") + chalk19.cyan("use demo data") + chalk19.dim(".")
18616
+ );
18617
+ }
18618
+ console.log();
18619
+ }
18620
+ function printChannelIntro(seed) {
18621
+ console.log();
18622
+ console.log(" " + paint("accent", "Think with me"));
18623
+ console.log(
18624
+ " " + chalk19.dim(
18625
+ "Socratic channel \u2014 explore, challenge assumptions, pull evidence. Type "
18626
+ ) + chalk19.cyan("done") + chalk19.dim(" or ") + chalk19.cyan("cancel") + chalk19.dim(" to return to ask \u203A.")
18627
+ );
18628
+ if (seed) {
18629
+ console.log(" " + chalk19.dim("Seed: ") + seed);
18630
+ }
18631
+ console.log();
18632
+ }
18633
+ function armKeylessThink(ctx, opts) {
18634
+ ctx.thinkState = {
18635
+ step: "awaiting_connect",
18636
+ seed: opts.seed,
18637
+ origin: opts.origin,
18638
+ started_at: (/* @__PURE__ */ new Date()).toISOString()
18639
+ };
18640
+ saveSessionState(ctx);
18641
+ console.log();
18642
+ console.log(" " + chalk19.dim("Think channel needs an AI key."));
18643
+ console.log(
18644
+ " " + chalk19.dim("Type ") + paint("accent", "/connect") + chalk19.dim(" and paste a key. Seed kept \u2014 the channel opens after connect.")
18645
+ );
18646
+ console.log();
18647
+ }
18648
+ async function startThinkFlow(ctx, opts) {
18649
+ if (!isAnalysisReady(ctx)) {
18650
+ queueThinkForAnalysis(ctx, opts);
18651
+ return "Think queued";
18652
+ }
18653
+ if (!canUseReplAi(ctx)) {
18654
+ armKeylessThink(ctx, opts);
18655
+ return "Think awaiting connect";
18656
+ }
18657
+ const seed = opts.seed?.trim() || void 0;
18658
+ ctx.thinkState = {
18659
+ step: "active",
18660
+ seed,
18661
+ origin: opts.origin,
18662
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
18663
+ open_questions: [],
18664
+ challenged_assumptions: [],
18665
+ working_hypotheses: []
18666
+ };
18667
+ if (ctx.thinkConversation.length === 0 && seed) {
18668
+ }
18669
+ saveSessionState(ctx);
18670
+ printChannelIntro(seed);
18671
+ recordMessage(ctx, "agent", seed ? `Think channel opened: ${seed}` : "Think channel opened");
18672
+ if (seed) {
18673
+ recordMessage(ctx, "user", seed);
18674
+ const { runThinkTurn: runThinkTurn2 } = await Promise.resolve().then(() => (init_think(), think_exports));
18675
+ await runThinkTurn2(seed, ctx);
18676
+ }
18677
+ return "Think channel open";
18678
+ }
18679
+ async function resumeThinkAfterCompute(ctx) {
18680
+ const state2 = ctx.thinkState;
18681
+ if (!state2 || state2.step !== "awaiting_analysis") return;
18682
+ if (ctx.strategistState && ctx.strategistState.step !== "awaiting_analysis" && ctx.strategistState.step !== "awaiting_connect") {
18683
+ return;
18684
+ }
18685
+ if (ctx.strategistState?.step === "awaiting_analysis") return;
18686
+ console.log();
18687
+ console.log(" " + paint("accent", "Analysis is ready. The think channel continues."));
18688
+ await startThinkFlow(ctx, {
18689
+ seed: state2.seed,
18690
+ origin: state2.origin ?? "nl"
18691
+ });
18692
+ }
18693
+ async function resumeThinkAfterConnect(ctx) {
18694
+ const state2 = ctx.thinkState;
18695
+ if (!state2 || state2.step !== "awaiting_connect") return false;
18696
+ if (!canUseReplAi(ctx)) return false;
18697
+ console.log();
18698
+ console.log(" " + paint("accent", "Key connected. Opening the think channel."));
18699
+ await startThinkFlow(ctx, {
18700
+ seed: state2.seed,
18701
+ origin: state2.origin ?? "nl"
18702
+ });
18703
+ return true;
18704
+ }
18705
+ function clearThinkFlow(ctx, reason) {
18706
+ ctx.thinkState = void 0;
18707
+ saveSessionState(ctx);
18708
+ if (reason === "handoff") return;
18709
+ console.log();
18710
+ console.log(
18711
+ " " + chalk19.dim(
18712
+ reason === "done" ? "Think channel closed. Back to ask \u203A." : "Think session cancelled. Continue exploration."
18713
+ )
18714
+ );
18715
+ console.log();
18716
+ }
18717
+ async function handleThinkFlow(input, ctx) {
18718
+ const state2 = ctx.thinkState;
18719
+ if (!state2 || state2.step !== "active") return;
18720
+ const line = input.trim();
18721
+ recordMessage(ctx, "user", line);
18722
+ if (CANCEL_RE2.test(line) || DONE_RE.test(line)) {
18723
+ clearThinkFlow(ctx, CANCEL_RE2.test(line) ? "cancel" : "done");
18724
+ recordMessage(ctx, "agent", "Think channel closed");
18725
+ return "Think closed";
18726
+ }
18727
+ if (isStrategistIntent(line)) {
18728
+ clearThinkFlow(ctx, "handoff");
18729
+ const summary = await startStrategistFlow(ctx, {
18730
+ seed: extractObjectiveSeed(line),
18731
+ origin: "nl"
18732
+ }) ?? void 0;
18733
+ return summary ?? "Handed off to strategist";
18734
+ }
18735
+ if (!canUseReplAi(ctx)) {
18736
+ armKeylessThink(ctx, { seed: state2.seed ?? line, origin: state2.origin ?? "nl" });
18737
+ return "Think awaiting connect";
18738
+ }
18739
+ const { runThinkTurn: runThinkTurn2 } = await Promise.resolve().then(() => (init_think(), think_exports));
18740
+ await runThinkTurn2(line, ctx);
18741
+ if (ctx.strategistState && ctx.strategistState.step !== "awaiting_analysis" && ctx.strategistState.step !== "awaiting_connect") {
18742
+ clearThinkFlow(ctx, "handoff");
18743
+ const { promptQueuedAiStrategist: promptQueuedAiStrategist2 } = await Promise.resolve().then(() => (init_strategist_flow(), strategist_flow_exports));
18744
+ promptQueuedAiStrategist2(ctx);
18745
+ }
18746
+ return "Think turn";
18747
+ }
18748
+ var THINK_INTENT_RE, CANCEL_RE2, DONE_RE;
18749
+ var init_think_flow = __esm({
18750
+ "src/conversation/think-flow.ts"() {
18751
+ "use strict";
18752
+ init_context2();
18753
+ init_repl_api();
18754
+ init_theme();
18755
+ init_handoff_draft();
18756
+ init_strategist_flow();
18757
+ THINK_INTENT_RE = /\b(think\s+with\s+me|pressure[- ]?test|what\s+am\s+i\s+missing|challenge\s+(my\s+)?(assumption|thinking|hypothesis)|let'?s\s+(dig|explore|think|pressure)|dig\s+into|steelman|devil'?s\s+advocate|think\s+through|brainstorm\s+(with\s+me|this)|socratic)\b/i;
18758
+ CANCEL_RE2 = /^(cancel|stop|quit|abort|never\s?mind|nevermind|forget it)\s*[.!]?\s*$/i;
18759
+ DONE_RE = /^(done|enough|enough for now|that'?s enough|leave|exit think)\s*[.!]?\s*$/i;
18760
+ }
18761
+ });
18762
+
18763
+ // src/conversation/gap-card.ts
18764
+ import chalk20 from "chalk";
18309
18765
  function printGapCard(audit, opts = {}) {
18310
18766
  console.log();
18311
18767
  if (opts.skipSatisfied) {
18312
18768
  if (audit.missing.length > 0) {
18313
- console.log(" " + chalk18.bold("Data check"));
18769
+ console.log(" " + chalk20.bold("Data check"));
18314
18770
  }
18315
18771
  } else if (audit.satisfied.length > 0) {
18316
18772
  const bits = audit.satisfied.map((item) => item.detail);
18317
18773
  console.log(
18318
- " " + chalk18.green("\u2713") + " " + chalk18.bold("Data check") + chalk18.dim(" \u2014 " + bits.join(" \xB7 "))
18774
+ " " + chalk20.green("\u2713") + " " + chalk20.bold("Data check") + chalk20.dim(" \u2014 " + bits.join(" \xB7 "))
18319
18775
  );
18320
18776
  } else {
18321
- console.log(" " + chalk18.bold("Data check"));
18777
+ console.log(" " + chalk20.bold("Data check"));
18322
18778
  }
18323
18779
  for (const item of audit.missing) {
18324
- console.log(" " + chalk18.red("\u2717") + " " + item.label + chalk18.dim(` \u2014 ${item.why}`));
18325
- console.log(" " + chalk18.dim(item.suggestion));
18780
+ console.log(" " + chalk20.red("\u2717") + " " + item.label + chalk20.dim(` \u2014 ${item.why}`));
18781
+ console.log(" " + chalk20.dim(item.suggestion));
18326
18782
  }
18327
18783
  if (audit.optional.length > 0) {
18328
18784
  const heads = audit.optional.map((item) => item.detail.split(" \u2014 ")[0] ?? item.detail);
18329
18785
  const joined = heads.join(" \xB7 ");
18330
18786
  if (joined.length <= 100) {
18331
- console.log(" " + chalk18.yellow("~") + " " + chalk18.dim(joined));
18787
+ console.log(" " + chalk20.yellow("~") + " " + chalk20.dim(joined));
18332
18788
  } else {
18333
18789
  for (const item of audit.optional) {
18334
- console.log(" " + chalk18.yellow("~") + " " + chalk18.dim(`${item.label}: ${item.detail}`));
18790
+ console.log(" " + chalk20.yellow("~") + " " + chalk20.dim(`${item.label}: ${item.detail}`));
18335
18791
  }
18336
18792
  }
18337
18793
  }
18338
18794
  console.log();
18339
18795
  if (audit.can_compute) {
18340
18796
  console.log(
18341
- " " + chalk18.dim("Ready to compute. Press ") + chalk18.cyan("\u23CE") + chalk18.dim(" or type ") + chalk18.cyan('"go ahead"')
18797
+ " " + chalk20.dim("Ready to compute. Press ") + chalk20.cyan("\u23CE") + chalk20.dim(" or type ") + chalk20.cyan('"go ahead"')
18342
18798
  );
18343
18799
  } else if (audit.missing.length > 0) {
18344
18800
  console.log(
18345
- " " + chalk18.dim("Load data. Paste a CSV path, or press ") + chalk18.cyan("\u23CE") + chalk18.dim(" to ") + chalk18.cyan("use demo data")
18801
+ " " + chalk20.dim("Load data. Paste a CSV path, or press ") + chalk20.cyan("\u23CE") + chalk20.dim(" to ") + chalk20.cyan("use demo data")
18346
18802
  );
18347
18803
  }
18348
18804
  console.log();
@@ -18359,7 +18815,7 @@ __export(keyless_ask_exports, {
18359
18815
  isKeylessVitalsAsk: () => isKeylessVitalsAsk,
18360
18816
  tryKeylessAskAnswer: () => tryKeylessAskAnswer
18361
18817
  });
18362
- import chalk19 from "chalk";
18818
+ import chalk21 from "chalk";
18363
18819
  function isKeylessVitalsAsk(input) {
18364
18820
  return KEYLESS_ASK_RE.test(input.trim());
18365
18821
  }
@@ -18408,35 +18864,35 @@ async function tryKeylessAskAnswer(ctx, input, opts = {}) {
18408
18864
  const headline = dollarBit ? `${label} \u2014 ${dollarBit} \u2014 is the most expensive problem to solve right now.` : `${label} (score ${Math.round(primary.score)}, ${primary.status}) is the problem to fix first.`;
18409
18865
  const runners = [...aggregate.vital_signs].filter((v) => v.vital_sign !== primary.vital_sign && (v.dollar_value ?? 0) > 0).sort((a, b) => (b.dollar_value ?? 0) - (a.dollar_value ?? 0)).slice(0, 2);
18410
18866
  console.log();
18411
- console.log(" " + chalk19.bold(headline));
18867
+ console.log(" " + chalk21.bold(headline));
18412
18868
  if (opts.fromResume) {
18413
18869
  if (runners.length > 0) {
18414
18870
  console.log(
18415
- " " + chalk19.dim("Next after that: ") + chalk19.dim(runners.map(formatRunnerBit).join(" \xB7 "))
18871
+ " " + chalk21.dim("Next after that: ") + chalk21.dim(runners.map(formatRunnerBit).join(" \xB7 "))
18416
18872
  );
18417
18873
  }
18418
18874
  } else {
18419
18875
  console.log();
18420
18876
  if (gating && gating.vital_sign !== primary.vital_sign) {
18421
18877
  console.log(
18422
- " " + chalk19.dim("Gating vital: ") + paint("accent", VITAL_SIGN_LABELS[gating.vital_sign]) + chalk19.dim(` (score ${Math.round(gating.score)}) \u2014 it bounds what you can trust downstream.`)
18878
+ " " + chalk21.dim("Gating vital: ") + paint("accent", VITAL_SIGN_LABELS[gating.vital_sign]) + chalk21.dim(` (score ${Math.round(gating.score)}) \u2014 it bounds what you can trust downstream.`)
18423
18879
  );
18424
18880
  }
18425
18881
  if (runners.length > 0) {
18426
- console.log(" " + chalk19.dim("Also on the board:"));
18882
+ console.log(" " + chalk21.dim("Also on the board:"));
18427
18883
  for (const vs of runners) {
18428
- console.log(" " + chalk19.dim("\xB7 ") + formatVitalLine(vs));
18884
+ console.log(" " + chalk21.dim("\xB7 ") + formatVitalLine(vs));
18429
18885
  }
18430
18886
  }
18431
18887
  if (aggregate.total_value_at_risk != null && aggregate.total_value_at_risk > 0) {
18432
18888
  console.log(
18433
- " " + chalk19.dim("Total at risk: ") + chalk19.green(formatCurrency(aggregate.total_value_at_risk))
18889
+ " " + chalk21.dim("Total at risk: ") + chalk21.green(formatCurrency(aggregate.total_value_at_risk))
18434
18890
  );
18435
18891
  }
18436
18892
  }
18437
18893
  console.log();
18438
18894
  console.log(
18439
- " " + chalk19.dim("Press ") + paint("accent", "\u23CE") + chalk19.dim(" to connect a key (") + paint("accent", "/connect") + chalk19.dim(") for the why and the plan. NTRP will finish this question after you connect.")
18895
+ " " + chalk21.dim("Press ") + paint("accent", "\u23CE") + chalk21.dim(" to connect a key (") + paint("accent", "/connect") + chalk21.dim(") for the why and the plan. NTRP will finish this question after you connect.")
18440
18896
  );
18441
18897
  console.log();
18442
18898
  if (!opts.fromResume) {
@@ -18459,7 +18915,7 @@ var init_keyless_ask = __esm({
18459
18915
  });
18460
18916
 
18461
18917
  // src/conversation/keyless-definitions.ts
18462
- import chalk20 from "chalk";
18918
+ import chalk22 from "chalk";
18463
18919
  function isPossessiveMetricAsk(input) {
18464
18920
  return POSSESSIVE_RE.test(input.trim());
18465
18921
  }
@@ -18512,9 +18968,9 @@ function tryKeylessDefinitionAnswer(ctx, input) {
18512
18968
  const bench = explainer.benchmarkHint?.(motion);
18513
18969
  console.log();
18514
18970
  console.log(
18515
- " " + sectionHeading(explainer.label) + chalk20.dim(` \xB7 ${explainer.kind === "vital" ? "vital sign" : "SaaS metric"}`)
18971
+ " " + sectionHeading(explainer.label) + chalk22.dim(` \xB7 ${explainer.kind === "vital" ? "vital sign" : "SaaS metric"}`)
18516
18972
  );
18517
- console.log(" " + chalk20.dim(explainer.tagline));
18973
+ console.log(" " + chalk22.dim(explainer.tagline));
18518
18974
  console.log();
18519
18975
  console.log(" " + bold("Meaning"));
18520
18976
  printWrapped2(explainer.meaning, " ");
@@ -18526,16 +18982,16 @@ function tryKeylessDefinitionAnswer(ctx, input) {
18526
18982
  }
18527
18983
  if (bench) {
18528
18984
  console.log();
18529
- console.log(" " + chalk20.dim(`Benchmark \xB7 ${bench}`));
18985
+ console.log(" " + chalk22.dim(`Benchmark \xB7 ${bench}`));
18530
18986
  }
18531
18987
  if (explainer.dollar_label) {
18532
18988
  console.log(
18533
- " " + chalk20.dim(`Dollar translation \xB7 ${explainer.dollar_label}`)
18989
+ " " + chalk22.dim(`Dollar translation \xB7 ${explainer.dollar_label}`)
18534
18990
  );
18535
18991
  }
18536
18992
  console.log();
18537
18993
  console.log(
18538
- " " + chalk20.dim("More: ") + paint("accent", `/deepdive ${explainer.id}`) + chalk20.dim(" \xB7 full tour: ") + paint("accent", "/deepdive")
18994
+ " " + chalk22.dim("More: ") + paint("accent", `/deepdive ${explainer.id}`) + chalk22.dim(" \xB7 full tour: ") + paint("accent", "/deepdive")
18539
18995
  );
18540
18996
  console.log();
18541
18997
  recordMessage(ctx, "user", input);
@@ -18565,7 +19021,7 @@ var init_keyless_definitions = __esm({
18565
19021
  });
18566
19022
 
18567
19023
  // src/conversation/orchestrator.ts
18568
- import chalk21 from "chalk";
19024
+ import chalk23 from "chalk";
18569
19025
  async function handleExploreWithoutKey(ctx, input) {
18570
19026
  if (isDefinitionAsk(input) && tryKeylessDefinitionAnswer(ctx, input)) {
18571
19027
  return;
@@ -18595,7 +19051,7 @@ async function handleExploreWithoutKey(ctx, input) {
18595
19051
  );
18596
19052
  if (ctx.pendingAsk) {
18597
19053
  console.log(
18598
- " " + chalk21.dim("Your question is stored. NTRP will answer it after you connect.")
19054
+ " " + chalk23.dim("Your question is stored. NTRP will answer it after you connect.")
18599
19055
  );
18600
19056
  }
18601
19057
  if (ctx.gapAudit) {
@@ -18610,12 +19066,12 @@ async function handleExploreWithoutKey(ctx, input) {
18610
19066
  return;
18611
19067
  }
18612
19068
  console.log();
18613
- console.log(" " + chalk21.yellow("No key is connected. Q&A stays off until you type ") + paint("accent", "/connect") + chalk21.yellow("."));
18614
- console.log(" " + chalk21.dim("These commands work without a key:"));
18615
- console.log(" " + paint("accent", "/deepdive") + chalk21.dim(" slides for numbers and how to use NTRP"));
18616
- console.log(" " + paint("accent", "/playbook") + chalk21.dim(" recommended plays from your computed vitals"));
18617
- console.log(" " + chalk21.cyan('"how should we fix this?"') + chalk21.dim(" a simple plan. No AI."));
18618
- console.log(" " + paint("accent", "/handoff") + chalk21.dim(" write this analysis for another tool"));
19069
+ console.log(" " + chalk23.yellow("No key is connected. Q&A stays off until you type ") + paint("accent", "/connect") + chalk23.yellow("."));
19070
+ console.log(" " + chalk23.dim("These commands work without a key:"));
19071
+ console.log(" " + paint("accent", "/deepdive") + chalk23.dim(" slides for numbers and how to use NTRP"));
19072
+ console.log(" " + paint("accent", "/playbook") + chalk23.dim(" recommended plays from your computed vitals"));
19073
+ console.log(" " + chalk23.cyan('"how should we fix this?"') + chalk23.dim(" a simple plan. No AI."));
19074
+ console.log(" " + paint("accent", "/handoff") + chalk23.dim(" write this analysis for another tool"));
18619
19075
  console.log();
18620
19076
  recordMessage(
18621
19077
  ctx,
@@ -19270,7 +19726,7 @@ var nl_exports = {};
19270
19726
  __export(nl_exports, {
19271
19727
  runNaturalLanguage: () => runNaturalLanguage
19272
19728
  });
19273
- import chalk22 from "chalk";
19729
+ import chalk24 from "chalk";
19274
19730
  async function runNaturalLanguage(input, ctx) {
19275
19731
  if (isSmokeProtocolTrigger(input)) {
19276
19732
  recordMessage(ctx, "user", input);
@@ -19282,10 +19738,10 @@ async function runNaturalLanguage(input, ctx) {
19282
19738
  printAnswer(result.answer);
19283
19739
  recordMessage(ctx, "agent", result.answer);
19284
19740
  console.log();
19285
- return extractSummary(result.answer);
19741
+ return extractSummary2(result.answer);
19286
19742
  } catch (err) {
19287
19743
  spinner2.fail("Smoke protocol failed");
19288
- console.error(" " + chalk22.red(String(err.message ?? err)));
19744
+ console.error(" " + chalk24.red(String(err.message ?? err)));
19289
19745
  console.log();
19290
19746
  return;
19291
19747
  }
@@ -19315,8 +19771,8 @@ async function runNaturalLanguage(input, ctx) {
19315
19771
  spinner2.succeed(metricsFirst ? "Session context ready" : "Health snapshot ready");
19316
19772
  } catch (err) {
19317
19773
  spinner2.fail("Could not compute health snapshot");
19318
- console.error(" " + chalk22.red(String(err.message ?? err)));
19319
- console.log(" " + chalk22.dim("Run ") + paint("accent", "/new") + chalk22.dim(" \u2192 pick Demo to load sample data."));
19774
+ console.error(" " + chalk24.red(String(err.message ?? err)));
19775
+ console.log(" " + chalk24.dim("Run ") + paint("accent", "/new") + chalk24.dim(" \u2192 pick Demo to load sample data."));
19320
19776
  console.log();
19321
19777
  return;
19322
19778
  }
@@ -19354,7 +19810,7 @@ async function runNaturalLanguage(input, ctx) {
19354
19810
  break;
19355
19811
  case "thinking":
19356
19812
  spinner.stop();
19357
- console.log(" " + chalk22.dim.italic(event.text));
19813
+ console.log(" " + chalk24.dim.italic(event.text));
19358
19814
  spinner.start("Thinking\u2026");
19359
19815
  break;
19360
19816
  case "answer":
@@ -19364,7 +19820,7 @@ async function runNaturalLanguage(input, ctx) {
19364
19820
  break;
19365
19821
  case "finding":
19366
19822
  spinner.stop();
19367
- printFindingInline(event.finding);
19823
+ printFindingInline2(event.finding);
19368
19824
  break;
19369
19825
  case "done":
19370
19826
  spinner.stop();
@@ -19374,7 +19830,7 @@ async function runNaturalLanguage(input, ctx) {
19374
19830
  }
19375
19831
  } catch (err) {
19376
19832
  spinner.fail("Error while investigating");
19377
- console.error(" " + chalk22.red(String(err.message ?? err)));
19833
+ console.error(" " + chalk24.red(String(err.message ?? err)));
19378
19834
  console.log();
19379
19835
  return;
19380
19836
  } finally {
@@ -19384,7 +19840,7 @@ async function runNaturalLanguage(input, ctx) {
19384
19840
  ctx.conversation = distillThread(rawHistory);
19385
19841
  }
19386
19842
  if (!lastAnswer) {
19387
- console.log(" " + chalk22.dim("(no answer returned)"));
19843
+ console.log(" " + chalk24.dim("(no answer returned)"));
19388
19844
  } else {
19389
19845
  recordMessage(ctx, "agent", lastAnswer);
19390
19846
  if (ctx.pendingAsk) {
@@ -19400,12 +19856,12 @@ async function runNaturalLanguage(input, ctx) {
19400
19856
  console.log();
19401
19857
  const { promptQueuedAiStrategist: promptQueuedAiStrategist2 } = await Promise.resolve().then(() => (init_strategist_flow(), strategist_flow_exports));
19402
19858
  promptQueuedAiStrategist2(ctx);
19403
- return lastAnswer ? extractSummary(lastAnswer) : void 0;
19859
+ return lastAnswer ? extractSummary2(lastAnswer) : void 0;
19404
19860
  }
19405
19861
  function printAnswer(text) {
19406
19862
  printMarkdown(text, { indent: 2 });
19407
19863
  }
19408
- function extractSummary(text) {
19864
+ function extractSummary2(text) {
19409
19865
  const plain = text.replace(/#{1,6}\s+/g, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^[-*]\s+/gm, "").trim();
19410
19866
  const sentenceMatch = plain.match(/^(.+?[.!?])(?:\s|$)/);
19411
19867
  const sentence = sentenceMatch ? sentenceMatch[1] : plain.split("\n")[0];
@@ -19413,16 +19869,16 @@ function extractSummary(text) {
19413
19869
  const truncated = sentence.slice(0, 60).replace(/\s+\S*$/, "");
19414
19870
  return truncated + "\u2026";
19415
19871
  }
19416
- function printFindingInline(finding) {
19872
+ function printFindingInline2(finding) {
19417
19873
  const sev = finding.severity;
19418
19874
  console.log();
19419
- console.log(" " + severityPaint(sev)(`[${sev}]`) + " " + chalk22.bold(finding.segment));
19875
+ console.log(" " + severityPaint(sev)(`[${sev}]`) + " " + chalk24.bold(finding.segment));
19420
19876
  printMarkdown(finding.finding, { indent: 2 });
19421
19877
  const play = finding.recommended_plays?.[0];
19422
- if (play) console.log(" " + chalk22.dim("\u2192 " + play.play_name + " \u2014 " + play.rationale));
19878
+ if (play) console.log(" " + chalk24.dim("\u2192 " + play.play_name + " \u2014 " + play.rationale));
19423
19879
  if (finding.recommended_focus) {
19424
19880
  console.log(
19425
- " " + chalk22.dim("How this works: ") + paint("accent", `/deepdive ${finding.recommended_focus}`)
19881
+ " " + chalk24.dim("How this works: ") + paint("accent", `/deepdive ${finding.recommended_focus}`)
19426
19882
  );
19427
19883
  }
19428
19884
  }
@@ -19458,12 +19914,12 @@ __export(demo_exports, {
19458
19914
  printDemoDisabled: () => printDemoDisabled,
19459
19915
  setDemoEnabled: () => setDemoEnabled
19460
19916
  });
19461
- import chalk23 from "chalk";
19917
+ import chalk25 from "chalk";
19462
19918
  function printDemoDisabled() {
19463
19919
  console.log();
19464
- console.log(" " + chalk23.red(DEMO_DISABLED_MESSAGE));
19920
+ console.log(" " + chalk25.red(DEMO_DISABLED_MESSAGE));
19465
19921
  console.log(
19466
- " " + chalk23.dim("Re-enable with ") + paint("accent", "/config set demo-enabled true") + chalk23.dim(".")
19922
+ " " + chalk25.dim("Re-enable with ") + paint("accent", "/config set demo-enabled true") + chalk25.dim(".")
19467
19923
  );
19468
19924
  console.log();
19469
19925
  }
@@ -22765,16 +23221,16 @@ var generate_exports = {};
22765
23221
  __export(generate_exports, {
22766
23222
  handler: () => handler2
22767
23223
  });
22768
- import chalk24 from "chalk";
23224
+ import chalk26 from "chalk";
22769
23225
  async function handler2(args, ctx) {
22770
23226
  const { flags } = parseArgs(args, ["list-scenarios", "regen-taxonomy", "brief"]);
22771
23227
  const quiet = ctx.execution.quiet;
22772
23228
  const brief = getBool(flags, "brief");
22773
23229
  if (getBool(flags, "list-scenarios")) {
22774
- console.log(chalk24.bold("\n Available Scenarios:\n"));
23230
+ console.log(chalk26.bold("\n Available Scenarios:\n"));
22775
23231
  for (const s of SCENARIO_LIST) {
22776
- console.log(` ${chalk24.cyan(s.key.padEnd(20))} ${s.label}`);
22777
- console.log(` ${chalk24.dim(" ".repeat(20))} ${s.description}
23232
+ console.log(` ${chalk26.cyan(s.key.padEnd(20))} ${s.label}`);
23233
+ console.log(` ${chalk26.dim(" ".repeat(20))} ${s.description}
22778
23234
  `);
22779
23235
  }
22780
23236
  return true;
@@ -22784,9 +23240,9 @@ async function handler2(args, ctx) {
22784
23240
  const skipProfile = getFalse(flags, "profile");
22785
23241
  if (!isProfileConfigured(profile) && !skipProfile) {
22786
23242
  console.error();
22787
- console.error(" " + chalk24.red("No company profile found."));
22788
- console.error(" " + chalk24.dim("Run ") + paint("accent", "/onboard") + chalk24.dim(" first for a richer demo,"));
22789
- console.error(" " + chalk24.dim("or pass ") + paint("accent", "--no-profile") + chalk24.dim(" to skip."));
23243
+ console.error(" " + chalk26.red("No company profile found."));
23244
+ console.error(" " + chalk26.dim("Run ") + paint("accent", "/onboard") + chalk26.dim(" first for a richer demo,"));
23245
+ console.error(" " + chalk26.dim("or pass ") + paint("accent", "--no-profile") + chalk26.dim(" to skip."));
22790
23246
  console.error();
22791
23247
  markFailure(ctx);
22792
23248
  return false;
@@ -22794,8 +23250,8 @@ async function handler2(args, ctx) {
22794
23250
  const explicitScenario = getString(flags, "scenario", "s");
22795
23251
  const resolvedScenario = resolveScenarioInput(explicitScenario);
22796
23252
  if (resolvedScenario === null) {
22797
- console.error(chalk24.red(` Unknown scenario: ${explicitScenario}`));
22798
- console.log(chalk24.dim(` Valid: ${SCENARIO_LIST.map((s) => s.key).join(", ")}`));
23253
+ console.error(chalk26.red(` Unknown scenario: ${explicitScenario}`));
23254
+ console.log(chalk26.dim(` Valid: ${SCENARIO_LIST.map((s) => s.key).join(", ")}`));
22799
23255
  markFailure(ctx);
22800
23256
  return false;
22801
23257
  }
@@ -22809,10 +23265,10 @@ async function handler2(args, ctx) {
22809
23265
  const s = getScenario(scenario);
22810
23266
  console.log();
22811
23267
  if (brief) {
22812
- console.log(" " + paint("accent", "\u2713 Demo: ") + bold(s.label) + chalk24.dim(" \u2014 " + s.hook));
23268
+ console.log(" " + paint("accent", "\u2713 Demo: ") + bold(s.label) + chalk26.dim(" \u2014 " + s.hook));
22813
23269
  } else {
22814
23270
  console.log(" " + paint("accent", "\u2713 Scenario: ") + bold(s.label));
22815
- console.log(" " + chalk24.dim(s.story));
23271
+ console.log(" " + chalk26.dim(s.story));
22816
23272
  console.log();
22817
23273
  }
22818
23274
  }
@@ -22842,18 +23298,18 @@ async function handler2(args, ctx) {
22842
23298
  if (brief) {
22843
23299
  spinner.succeed(`Demo loaded \u2014 ${briefCounts(result.counts)}`);
22844
23300
  } else {
22845
- spinner.succeed(`Generated demo data for "${chalk24.cyan(scenario)}" scenario`);
23301
+ spinner.succeed(`Generated demo data for "${chalk26.cyan(scenario)}" scenario`);
22846
23302
  console.log();
22847
23303
  printEntityCounts(result.counts);
22848
23304
  }
22849
23305
  }
22850
23306
  if (!quiet && !brief && ctx.analysis.primary !== "revenue_metrics") {
22851
- console.log(chalk24.dim("\n Run /diagnose to compute vital signs.\n"));
23307
+ console.log(chalk26.dim("\n Run /diagnose to compute vital signs.\n"));
22852
23308
  }
22853
23309
  }
22854
23310
  } catch (err) {
22855
23311
  if (spinner) spinner.fail("Generation failed");
22856
- console.error(chalk24.red(String(err)));
23312
+ console.error(chalk26.red(String(err)));
22857
23313
  markFailure(ctx);
22858
23314
  return false;
22859
23315
  }
@@ -22891,7 +23347,7 @@ async function loadOrBuildTaxonomy(profile, forceRegen, ctx) {
22891
23347
  return taxonomy;
22892
23348
  } catch (err) {
22893
23349
  spinner.fail("Couldn't build market taxonomy \u2014 using generic data pools");
22894
- console.log(" " + chalk24.dim(String(err.message ?? err)));
23350
+ console.log(" " + chalk26.dim(String(err.message ?? err)));
22895
23351
  return void 0;
22896
23352
  }
22897
23353
  }
@@ -22986,7 +23442,7 @@ __export(inbox_setup_exports, {
22986
23442
  reuseInboxFolderIfPresent: () => reuseInboxFolderIfPresent,
22987
23443
  shouldOfferInboxSkillSetup: () => shouldOfferInboxSkillSetup
22988
23444
  });
22989
- import chalk25 from "chalk";
23445
+ import chalk27 from "chalk";
22990
23446
  import { existsSync as existsSync22 } from "fs";
22991
23447
  function markDemoOffered() {
22992
23448
  setConfigValue("ai-inbox-nudge-seen", "true");
@@ -23008,27 +23464,27 @@ function printSkipHint(beat) {
23008
23464
  const skillCmd = paint("accent", "/inbox skill");
23009
23465
  if (beat === "demo") {
23010
23466
  console.log(
23011
- " " + chalk25.dim("Skipped. NTRP will ask once when you load your own data. Or type ") + setCmd + chalk25.dim(" then ") + skillCmd
23467
+ " " + chalk27.dim("Skipped. NTRP will ask once when you load your own data. Or type ") + setCmd + chalk27.dim(" then ") + skillCmd
23012
23468
  );
23013
23469
  return;
23014
23470
  }
23015
23471
  console.log(
23016
- " " + chalk25.dim("Skipped. NTRP will not ask again. Type ") + setCmd + chalk25.dim(" then ") + skillCmd + chalk25.dim(" at any time.")
23472
+ " " + chalk27.dim("Skipped. NTRP will not ask again. Type ") + setCmd + chalk27.dim(" then ") + skillCmd + chalk27.dim(" at any time.")
23017
23473
  );
23018
23474
  }
23019
23475
  async function reuseInboxFolderIfPresent(session, beat, folderPath = defaultAiInboxDir()) {
23020
23476
  if (getAiInboxDir()) return false;
23021
23477
  if (!existsSync22(folderPath)) return false;
23022
- console.log(" " + chalk25.dim("Pickup folder still on disk: ") + folderPath);
23478
+ console.log(" " + chalk27.dim("Pickup folder still on disk: ") + folderPath);
23023
23479
  const reuse = await session.confirm("Reuse this pickup folder?", true);
23024
23480
  if (!reuse) return false;
23025
23481
  const resolved = setAiInboxDir(folderPath);
23026
23482
  markDemoOffered();
23027
23483
  if (beat === "production") markProductionOffered();
23028
23484
  console.log();
23029
- console.log(" " + paint("accent", "Inbox ready") + chalk25.dim(" ") + resolved);
23485
+ console.log(" " + paint("accent", "Inbox ready") + chalk27.dim(" ") + resolved);
23030
23486
  console.log(
23031
- " " + chalk25.dim("Folder reused. Type ") + paint("accent", "/inbox skill") + chalk25.dim(" to print the finder again.")
23487
+ " " + chalk27.dim("Folder reused. Type ") + paint("accent", "/inbox skill") + chalk27.dim(" to print the finder again.")
23032
23488
  );
23033
23489
  console.log();
23034
23490
  return true;
@@ -23039,12 +23495,12 @@ async function offerInboxSkillSetup(session, opts = {}) {
23039
23495
  console.log();
23040
23496
  console.log(" " + bold("Teach Claude where handoffs live"));
23041
23497
  console.log(
23042
- " " + chalk25.dim(
23498
+ " " + chalk27.dim(
23043
23499
  "Optional. NTRP copies every handoff into one folder. You paste instructions once; later /handoff just writes the file."
23044
23500
  )
23045
23501
  );
23046
23502
  if (beat === "production" && getConfigValue("ai-inbox-nudge-seen") === "true") {
23047
- console.log(" " + chalk25.dim("You skipped this during demo."));
23503
+ console.log(" " + chalk27.dim("You skipped this during demo."));
23048
23504
  }
23049
23505
  console.log();
23050
23506
  if (await reuseInboxFolderIfPresent(session, beat)) return;
@@ -23075,16 +23531,16 @@ async function offerInboxSkillSetup(session, opts = {}) {
23075
23531
  markDemoOffered();
23076
23532
  if (beat === "production") markProductionOffered();
23077
23533
  console.log();
23078
- console.log(" " + paint("accent", "Inbox ready") + chalk25.dim(" ") + resolved);
23534
+ console.log(" " + paint("accent", "Inbox ready") + chalk27.dim(" ") + resolved);
23079
23535
  if (n > 0) {
23080
- console.log(" " + chalk25.dim(`Synced ${n} recent export${n === 1 ? "" : "s"}.`));
23536
+ console.log(" " + chalk27.dim(`Synced ${n} recent export${n === 1 ? "" : "s"}.`));
23081
23537
  }
23082
23538
  console.log(
23083
- " " + chalk25.dim("Paste this skill into Claude once. Later, tell Claude to open the latest NTRP handoff.")
23539
+ " " + chalk27.dim("Paste this skill into Claude once. Later, tell Claude to open the latest NTRP handoff.")
23084
23540
  );
23085
23541
  printStandingSkill();
23086
23542
  await session.askPressEnter("Paste the skill into Claude. Then continue");
23087
- console.log(" " + chalk25.dim("Done. Later handoffs write to that folder. The skill is not printed again."));
23543
+ console.log(" " + chalk27.dim("Done. Later handoffs write to that folder. The skill is not printed again."));
23088
23544
  console.log();
23089
23545
  }
23090
23546
  async function maybeOfferInboxOnProduction(ctx) {
@@ -23117,7 +23573,7 @@ var ingest_exports = {};
23117
23573
  __export(ingest_exports, {
23118
23574
  handler: () => handler3
23119
23575
  });
23120
- import chalk26 from "chalk";
23576
+ import chalk28 from "chalk";
23121
23577
  import { readFileSync as readFileSync20, existsSync as existsSync23 } from "fs";
23122
23578
  import { basename as basename6 } from "path";
23123
23579
  async function handler3(args, ctx) {
@@ -23138,21 +23594,21 @@ async function handler3(args, ctx) {
23138
23594
  const source = getString(flags, "source", "s") ?? "salesforce";
23139
23595
  const skipResolve = getBool(flags, "skip-resolve");
23140
23596
  if (!file) {
23141
- console.error(chalk26.red(" Usage: /ingest <file> [--source salesforce|hubspot|outreach]"));
23142
- console.error(chalk26.dim(" /ingest --demo [--scenario <name>]"));
23597
+ console.error(chalk28.red(" Usage: /ingest <file> [--source salesforce|hubspot|outreach]"));
23598
+ console.error(chalk28.dim(" /ingest --demo [--scenario <name>]"));
23143
23599
  process.exit(1);
23144
23600
  }
23145
23601
  if (!existsSync23(file)) {
23146
- console.error(chalk26.red(` File not found: ${file}`));
23602
+ console.error(chalk28.red(` File not found: ${file}`));
23147
23603
  process.exit(1);
23148
23604
  }
23149
23605
  const profile = loadProfile();
23150
23606
  const skipProfile = getFalse(flags, "profile");
23151
23607
  if (!profile && !skipProfile) {
23152
23608
  console.error();
23153
- console.error(" " + chalk26.red("No company profile found."));
23154
- console.error(" " + chalk26.dim("Run ") + paint("accent", "/onboard") + chalk26.dim(" first for better column mapping,"));
23155
- console.error(" " + chalk26.dim("or pass ") + paint("accent", "--no-profile") + chalk26.dim(" to skip."));
23609
+ console.error(" " + chalk28.red("No company profile found."));
23610
+ console.error(" " + chalk28.dim("Run ") + paint("accent", "/onboard") + chalk28.dim(" first for better column mapping,"));
23611
+ console.error(" " + chalk28.dim("or pass ") + paint("accent", "--no-profile") + chalk28.dim(" to skip."));
23156
23612
  console.error();
23157
23613
  process.exit(1);
23158
23614
  }
@@ -23184,15 +23640,15 @@ async function handler3(args, ctx) {
23184
23640
  row_count: result2.imported
23185
23641
  });
23186
23642
  spinner.succeed(
23187
- `Imported ${chalk26.bold(result2.imported.toString())} revenue events from ${chalk26.dim(basename6(file))}`
23643
+ `Imported ${chalk28.bold(result2.imported.toString())} revenue events from ${chalk28.dim(basename6(file))}`
23188
23644
  );
23189
23645
  if (result2.errors.length > 0) {
23190
- console.log(chalk26.yellow(` ${result2.errors.length} rows skipped`));
23646
+ console.log(chalk28.yellow(` ${result2.errors.length} rows skipped`));
23191
23647
  }
23192
23648
  if (ctx.analysis) {
23193
23649
  ctx.analysis.data_source_type = "revenue_ledger";
23194
23650
  }
23195
- console.log(chalk26.dim(" Run ") + chalk26.cyan("/metrics") + chalk26.dim(" for SaaS metrics with ledger-backed retention."));
23651
+ console.log(chalk28.dim(" Run ") + chalk28.cyan("/metrics") + chalk28.dim(" for SaaS metrics with ledger-backed retention."));
23196
23652
  const { maybeOfferInboxOnProduction: maybeOfferInboxOnProduction3 } = await Promise.resolve().then(() => (init_inbox_setup(), inbox_setup_exports));
23197
23653
  await maybeOfferInboxOnProduction3(ctx);
23198
23654
  return `${result2.imported} revenue events from ${basename6(file)}`;
@@ -23201,7 +23657,7 @@ async function handler3(args, ctx) {
23201
23657
  const detection = detectEntityType(headers, source);
23202
23658
  if (!detection) {
23203
23659
  spinner.fail(`Could not auto-detect entity type for source: ${source}`);
23204
- console.log(chalk26.dim(" Headers found: " + headers.join(", ")));
23660
+ console.log(chalk28.dim(" Headers found: " + headers.join(", ")));
23205
23661
  process.exit(1);
23206
23662
  }
23207
23663
  spinner.text = `Importing ${rows.length} ${detection.entityType} rows...`;
@@ -23224,15 +23680,15 @@ async function handler3(args, ctx) {
23224
23680
  row_count: result.imported
23225
23681
  });
23226
23682
  spinner.succeed(
23227
- `Imported ${chalk26.bold(result.imported.toString())} ${detection.entityType} from ${chalk26.dim(basename6(file))} (${source})`
23683
+ `Imported ${chalk28.bold(result.imported.toString())} ${detection.entityType} from ${chalk28.dim(basename6(file))} (${source})`
23228
23684
  );
23229
23685
  if (result.errors.length > 0) {
23230
- console.log(chalk26.yellow(` ${result.errors.length} rows skipped`));
23686
+ console.log(chalk28.yellow(` ${result.errors.length} rows skipped`));
23231
23687
  for (const err of result.errors.slice(0, 3)) {
23232
- console.log(chalk26.dim(` - ${err}`));
23688
+ console.log(chalk28.dim(` - ${err}`));
23233
23689
  }
23234
23690
  if (result.errors.length > 3) {
23235
- console.log(chalk26.dim(` ... and ${result.errors.length - 3} more`));
23691
+ console.log(chalk28.dim(` ... and ${result.errors.length - 3} more`));
23236
23692
  }
23237
23693
  }
23238
23694
  if (!skipResolve) {
@@ -23251,7 +23707,7 @@ async function handler3(args, ctx) {
23251
23707
  return `${result.imported} ${detection.entityType} from ${basename6(file)}`;
23252
23708
  } catch (err) {
23253
23709
  spinner.fail("Import failed");
23254
- console.error(chalk26.red(String(err)));
23710
+ console.error(chalk28.red(String(err)));
23255
23711
  process.exit(1);
23256
23712
  }
23257
23713
  }
@@ -23363,13 +23819,13 @@ __export(demo_fit_exports, {
23363
23819
  resolveDemoScenarioForLoad: () => resolveDemoScenarioForLoad,
23364
23820
  runDemoFitQuiz: () => runDemoFitQuiz
23365
23821
  });
23366
- import chalk27 from "chalk";
23822
+ import chalk29 from "chalk";
23367
23823
  async function runDemoFitQuiz(session, opts = {}) {
23368
23824
  if (opts.intro !== false) {
23369
23825
  console.log();
23370
23826
  console.log(" " + bold("Fit a sample book of business"));
23371
23827
  console.log(
23372
- " " + chalk27.dim(
23828
+ " " + chalk29.dim(
23373
23829
  "No API key needed. Two questions about how you sell, then you pick which of seven sample pipelines feels closest."
23374
23830
  )
23375
23831
  );
@@ -23387,8 +23843,8 @@ async function runDemoFitQuiz(session, opts = {}) {
23387
23843
  );
23388
23844
  const recommended = inferDemoScenario({ salesMotion: motion, dealBand });
23389
23845
  console.log();
23390
- console.log(" " + chalk27.dim("Recommended: ") + paint("accent", getScenario(recommended.scenario).label));
23391
- console.log(" " + chalk27.dim(recommended.reason));
23846
+ console.log(" " + chalk29.dim("Recommended: ") + paint("accent", getScenario(recommended.scenario).label));
23847
+ console.log(" " + chalk29.dim(recommended.reason));
23392
23848
  const scenario = await session.choose(
23393
23849
  "Which of these sample books feels closest to the one you manage?",
23394
23850
  scenarioMenuChoices(),
@@ -23408,8 +23864,8 @@ async function offerFittedDemoAfterOnboard(session, ctx, profile) {
23408
23864
  const s = getScenario(fit.scenario);
23409
23865
  console.log();
23410
23866
  console.log(" " + bold("A sample pipeline that looks like you"));
23411
- console.log(" " + paint("accent", s.label) + chalk27.dim(" \u2014 " + s.hook));
23412
- console.log(" " + chalk27.dim(fit.reason));
23867
+ console.log(" " + paint("accent", s.label) + chalk29.dim(" \u2014 " + s.hook));
23868
+ console.log(" " + chalk29.dim(fit.reason));
23413
23869
  console.log();
23414
23870
  const action = await session.choose(
23415
23871
  "Try NTRP on that book of business?",
@@ -23466,8 +23922,8 @@ async function resolveDemoScenarioForLoad(ctx, opts = {}) {
23466
23922
  if (!opts.forceQuiz && isProfileConfigured(profile) && profile) {
23467
23923
  const fit = await resolveProfileFit(profile, ctx);
23468
23924
  console.log();
23469
- console.log(" " + chalk27.dim("Recommended: ") + paint("accent", getScenario(fit.scenario).label));
23470
- console.log(" " + chalk27.dim(fit.reason));
23925
+ console.log(" " + chalk29.dim("Recommended: ") + paint("accent", getScenario(fit.scenario).label));
23926
+ console.log(" " + chalk29.dim(fit.reason));
23471
23927
  const scenario = await session.choose(
23472
23928
  "Which sample book of business?",
23473
23929
  scenarioMenuChoices(),
@@ -23531,7 +23987,7 @@ __export(ingest_chat_exports, {
23531
23987
  import { existsSync as existsSync24 } from "fs";
23532
23988
  import { basename as basename7, resolve as resolve9 } from "path";
23533
23989
  import { homedir as homedir8 } from "os";
23534
- import chalk28 from "chalk";
23990
+ import chalk30 from "chalk";
23535
23991
  function extractFilePath(input) {
23536
23992
  const trimmed = input.trim();
23537
23993
  const patterns = [
@@ -23566,7 +24022,7 @@ function looksLikeFilePath(input) {
23566
24022
  }
23567
24023
  async function ingestFromChat(ctx, filePath) {
23568
24024
  if (!ctx.rl) {
23569
- console.log(" " + chalk28.red("Ingest confirm requires interactive mode."));
24025
+ console.log(" " + chalk30.red("Ingest confirm requires interactive mode."));
23570
24026
  return false;
23571
24027
  }
23572
24028
  const name = basename7(filePath);
@@ -23574,7 +24030,7 @@ async function ingestFromChat(ctx, filePath) {
23574
24030
  try {
23575
24031
  const ok = await prompts.confirm(`Ingest ${name} as CRM export?`, true);
23576
24032
  if (!ok) {
23577
- console.log(" " + chalk28.dim("Ingest cancelled."));
24033
+ console.log(" " + chalk30.dim("Ingest cancelled."));
23578
24034
  return false;
23579
24035
  }
23580
24036
  } finally {
@@ -23602,7 +24058,7 @@ async function ingestFromChat(ctx, filePath) {
23602
24058
  true
23603
24059
  );
23604
24060
  if (useAi) {
23605
- console.log(" " + chalk28.dim("AI column mapping is not wired to ingest yet \u2014 trying standard ingest."));
24061
+ console.log(" " + chalk30.dim("AI column mapping is not wired to ingest yet \u2014 trying standard ingest."));
23606
24062
  }
23607
24063
  } finally {
23608
24064
  prompts2.close();
@@ -23629,7 +24085,7 @@ async function ingestFromChat(ctx, filePath) {
23629
24085
  invalidateGapAudit(ctx);
23630
24086
  saveSessionState(ctx);
23631
24087
  console.log();
23632
- console.log(" " + paint("accent", "\u2713 Data loaded") + chalk28.dim(` \u2014 ${name}`));
24088
+ console.log(" " + paint("accent", "\u2713 Data loaded") + chalk30.dim(` \u2014 ${name}`));
23633
24089
  recordMessage(ctx, "user", `[ingested ${name}]`);
23634
24090
  recordMessage(ctx, "agent", `Loaded ${name}. Checking what we can analyze\u2026`);
23635
24091
  const audit = await refreshGapAudit(ctx);
@@ -23637,7 +24093,7 @@ async function ingestFromChat(ctx, filePath) {
23637
24093
  if (audit.can_compute && ctx.scope?.confirmed_at) {
23638
24094
  if (ctx.pendingAsk) {
23639
24095
  console.log();
23640
- console.log(" " + chalk28.dim("Computing so I can answer\u2026"));
24096
+ console.log(" " + chalk30.dim("Computing so I can answer\u2026"));
23641
24097
  await runConversationCompute(ctx);
23642
24098
  return true;
23643
24099
  }
@@ -23685,7 +24141,7 @@ async function loadDemoFromChat(ctx, scenario, opts = {}) {
23685
24141
  const { getScenario: getScenario2 } = await Promise.resolve().then(() => (init_scenarios(), scenarios_exports));
23686
24142
  const s = getScenario2(chosen);
23687
24143
  console.log();
23688
- console.log(" " + paint("accent", "Fitting ") + s.label + chalk28.dim(" \u2014 " + s.hook));
24144
+ console.log(" " + paint("accent", "Fitting ") + s.label + chalk30.dim(" \u2014 " + s.hook));
23689
24145
  }
23690
24146
  const { handler: demo } = await Promise.resolve().then(() => (init_generate(), generate_exports));
23691
24147
  const args = ["--no-profile", "--brief"];
@@ -23721,7 +24177,7 @@ async function loadDemoFromChat(ctx, scenario, opts = {}) {
23721
24177
  const shouldAuto = opts.autoCompute || Boolean(ctx.pendingAsk && audit.can_compute && ctx.scope?.confirmed_at);
23722
24178
  if (shouldAuto && audit.can_compute) {
23723
24179
  console.log();
23724
- console.log(" " + chalk28.dim("Computing so I can answer\u2026"));
24180
+ console.log(" " + chalk30.dim("Computing so I can answer\u2026"));
23725
24181
  await runConversationCompute(ctx);
23726
24182
  return true;
23727
24183
  }
@@ -23754,7 +24210,7 @@ __export(pending_ask_exports, {
23754
24210
  queuePendingAsk: () => queuePendingAsk,
23755
24211
  resumePendingAsk: () => resumePendingAsk
23756
24212
  });
23757
- import chalk29 from "chalk";
24213
+ import chalk31 from "chalk";
23758
24214
  function looksLikeQuestion(input) {
23759
24215
  const text = input.trim();
23760
24216
  if (!text) return false;
@@ -23790,7 +24246,7 @@ function printFocusChip(ctx) {
23790
24246
  const period = ctx.scope.time_horizon ? ` \xB7 ${ctx.scope.time_horizon}` : "";
23791
24247
  console.log();
23792
24248
  console.log(
23793
- " " + chalk29.dim("Focus: ") + paint("accent", lens) + chalk29.dim(period) + chalk29.dim(" \u2014 type ") + chalk29.cyan("adjust") + chalk29.dim(" to change")
24249
+ " " + chalk31.dim("Focus: ") + paint("accent", lens) + chalk31.dim(period) + chalk31.dim(" \u2014 type ") + chalk31.cyan("adjust") + chalk31.dim(" to change")
23794
24250
  );
23795
24251
  console.log();
23796
24252
  }
@@ -23801,7 +24257,7 @@ async function resumePendingAsk(ctx) {
23801
24257
  if (canUseReplAi(ctx)) {
23802
24258
  console.log();
23803
24259
  console.log(
23804
- " " + chalk29.dim(
24260
+ " " + chalk31.dim(
23805
24261
  pending.keylessAnswered ? "Picking up your question with the connected engine\u2026" : "Picking up your question\u2026"
23806
24262
  )
23807
24263
  );
@@ -23834,7 +24290,7 @@ async function offerDemoToAnswer(ctx) {
23834
24290
  const go = await prompts.confirm("Use demo data to answer this?", true);
23835
24291
  if (!go) {
23836
24292
  console.log(
23837
- " " + chalk29.dim("Paste a CSV path when ready, or say ") + chalk29.cyan("use demo data") + chalk29.dim(".")
24293
+ " " + chalk31.dim("Paste a CSV path when ready, or say ") + chalk31.cyan("use demo data") + chalk31.dim(".")
23838
24294
  );
23839
24295
  console.log();
23840
24296
  return false;
@@ -23866,11 +24322,11 @@ __export(compute_exports2, {
23866
24322
  isComputeIntent: () => isComputeIntent,
23867
24323
  runConversationCompute: () => runConversationCompute
23868
24324
  });
23869
- import chalk30 from "chalk";
24325
+ import chalk32 from "chalk";
23870
24326
  async function runConversationCompute(ctx) {
23871
24327
  const lens = ctx.scope?.primary_lens ?? ctx.analysis.primary;
23872
24328
  ctx.computeInProgress = true;
23873
- const willAnswer = Boolean(ctx.pendingAsk?.text) && !ctx.strategistState;
24329
+ const willAnswer = Boolean(ctx.pendingAsk?.text) && !ctx.strategistState && ctx.thinkState?.step !== "awaiting_analysis";
23874
24330
  try {
23875
24331
  if (lens === "revenue_metrics") {
23876
24332
  const { runMetricsAnalysis: runMetricsAnalysis2, extractHeadlineMetrics: extractHeadlineMetrics2 } = await Promise.resolve().then(() => (init_metrics_analysis(), metrics_analysis_exports));
@@ -23898,6 +24354,7 @@ async function runConversationCompute(ctx) {
23898
24354
  interactive: !willAnswer
23899
24355
  });
23900
24356
  await resumeQueuedStrategist(ctx);
24357
+ await resumeQueuedThink(ctx);
23901
24358
  await closeComputeTurn(ctx, willAnswer, "revenue_metrics");
23902
24359
  creditGapCompute(ctx);
23903
24360
  creditMetricsComplete(ctx, false);
@@ -23917,11 +24374,12 @@ async function runConversationCompute(ctx) {
23917
24374
  invalidateGapAudit(ctx);
23918
24375
  saveSessionState(ctx);
23919
24376
  await resumeQueuedStrategist(ctx);
24377
+ await resumeQueuedThink(ctx);
23920
24378
  await closeComputeTurn(ctx, willAnswer, "gtm_health");
23921
24379
  creditGapCompute(ctx);
23922
24380
  return typeof summary === "string" ? summary : "Health analysis ready";
23923
24381
  } catch (err) {
23924
- console.error(" " + chalk30.red(String(err.message ?? err)));
24382
+ console.error(" " + chalk32.red(String(err.message ?? err)));
23925
24383
  return;
23926
24384
  } finally {
23927
24385
  ctx.computeInProgress = false;
@@ -23934,9 +24392,16 @@ async function resumeQueuedStrategist(ctx) {
23934
24392
  const { resumeStrategistAfterCompute: resumeStrategistAfterCompute2 } = await Promise.resolve().then(() => (init_strategist_flow(), strategist_flow_exports));
23935
24393
  await resumeStrategistAfterCompute2(ctx);
23936
24394
  }
24395
+ async function resumeQueuedThink(ctx) {
24396
+ if (ctx.thinkState?.step !== "awaiting_analysis") return;
24397
+ ctx.computeInProgress = false;
24398
+ const { resumeThinkAfterCompute: resumeThinkAfterCompute2 } = await Promise.resolve().then(() => (init_think_flow(), think_flow_exports));
24399
+ await resumeThinkAfterCompute2(ctx);
24400
+ }
23937
24401
  async function resumePendingAskAfterCompute(ctx) {
23938
24402
  if (!ctx.pendingAsk?.text) return false;
23939
24403
  if (ctx.strategistState) return false;
24404
+ if (ctx.thinkState?.step === "active" || ctx.thinkState?.step === "awaiting_analysis") return false;
23940
24405
  const { resumePendingAsk: resumePendingAsk2 } = await Promise.resolve().then(() => (init_pending_ask(), pending_ask_exports));
23941
24406
  return resumePendingAsk2(ctx);
23942
24407
  }
@@ -24405,6 +24870,7 @@ async function handleDraftStrategy(input) {
24405
24870
  if (!objective) return { error: "objective is required." };
24406
24871
  if (!isAnalysisReady2(ctx)) {
24407
24872
  ctx.strategistState = { step: "awaiting_analysis", objective, origin: "ai" };
24873
+ if (ctx.thinkState) ctx.thinkState = void 0;
24408
24874
  saveSessionState2(ctx);
24409
24875
  return {
24410
24876
  queued: true,
@@ -24413,6 +24879,7 @@ async function handleDraftStrategy(input) {
24413
24879
  };
24414
24880
  }
24415
24881
  ctx.strategistState = { step: "objective_confirm", objective, origin: "ai" };
24882
+ if (ctx.thinkState) ctx.thinkState = void 0;
24416
24883
  saveSessionState2(ctx);
24417
24884
  return {
24418
24885
  launched: true,
@@ -24420,6 +24887,32 @@ async function handleDraftStrategy(input) {
24420
24887
  note: "Strategist handoff armed. After your reply the user sees an objective confirmation card and the engine runs a full grounding/backcast/stress-test session. Keep your reply to one or two sentences introducing the handoff \u2014 do NOT write the plan yourself."
24421
24888
  };
24422
24889
  }
24890
+ async function handleUpdateThinkScratch(input) {
24891
+ const { getAgentContext: getAgentContext2 } = await Promise.resolve().then(() => (init_agent_context(), agent_context_exports));
24892
+ const { saveSessionState: saveSessionState2 } = await Promise.resolve().then(() => (init_context2(), context_exports));
24893
+ const ctx = getAgentContext2();
24894
+ if (!ctx) return { error: "No active session context." };
24895
+ if (!ctx.thinkState || ctx.thinkState.step !== "active") {
24896
+ return { error: "Think channel is not active." };
24897
+ }
24898
+ const asStringList = (value) => {
24899
+ if (!Array.isArray(value)) return void 0;
24900
+ return value.filter((v) => typeof v === "string").map((s) => s.trim()).filter(Boolean).slice(0, 12);
24901
+ };
24902
+ const open = asStringList(input.open_questions);
24903
+ const challenged = asStringList(input.challenged_assumptions);
24904
+ const hypotheses = asStringList(input.working_hypotheses);
24905
+ if (open) ctx.thinkState.open_questions = open;
24906
+ if (challenged) ctx.thinkState.challenged_assumptions = challenged;
24907
+ if (hypotheses) ctx.thinkState.working_hypotheses = hypotheses;
24908
+ saveSessionState2(ctx);
24909
+ return {
24910
+ updated: true,
24911
+ open_questions: ctx.thinkState.open_questions ?? [],
24912
+ challenged_assumptions: ctx.thinkState.challenged_assumptions ?? [],
24913
+ working_hypotheses: ctx.thinkState.working_hypotheses ?? []
24914
+ };
24915
+ }
24423
24916
  async function handleGetSessionBrief(input) {
24424
24917
  const raw = typeof input.session_id === "string" ? input.session_id.trim() : "";
24425
24918
  if (!raw) return { error: "session_id is required." };
@@ -24545,13 +25038,177 @@ var init_tool_handlers = __esm({
24545
25038
  audit_data_gaps: (_, __) => handleAuditDataGaps(),
24546
25039
  run_compute: (_, __) => handleRunCompute(),
24547
25040
  draft_handoff: (input, _) => handleDraftHandoff(input),
24548
- draft_strategy: (input, _) => handleDraftStrategy(input)
25041
+ draft_strategy: (input, _) => handleDraftStrategy(input),
25042
+ update_think_scratch: (input, _) => handleUpdateThinkScratch(input)
24549
25043
  };
24550
25044
  }
24551
25045
  });
24552
25046
 
24553
- // src/ai/agentic-loop.ts
25047
+ // src/ai/think-prompt.ts
24554
25048
  function companyContextSection3() {
25049
+ const block = buildCompanyProfileBlock();
25050
+ return block ? `COMPANY CONTEXT:
25051
+ ${block}
25052
+
25053
+ ` : "";
25054
+ }
25055
+ function operatorSection3() {
25056
+ const block = buildOperatorBlock();
25057
+ return block ? `${block}
25058
+
25059
+ ` : "";
25060
+ }
25061
+ function buildScratchBlock(state2) {
25062
+ if (!state2) return "";
25063
+ const lines = [];
25064
+ if (state2.seed) lines.push(`Seed topic: ${state2.seed}`);
25065
+ if (state2.open_questions?.length) {
25066
+ lines.push("Open questions:");
25067
+ for (const q of state2.open_questions) lines.push(`- ${q}`);
25068
+ }
25069
+ if (state2.challenged_assumptions?.length) {
25070
+ lines.push("Challenged assumptions:");
25071
+ for (const a of state2.challenged_assumptions) lines.push(`- ${a}`);
25072
+ }
25073
+ if (state2.working_hypotheses?.length) {
25074
+ lines.push("Working hypotheses:");
25075
+ for (const h of state2.working_hypotheses) lines.push(`- ${h}`);
25076
+ }
25077
+ if (lines.length === 0) return "";
25078
+ return `
25079
+ THINK SCRATCH (session working memory \u2014 update via update_think_scratch):
25080
+ ${lines.join("\n")}
25081
+ `;
25082
+ }
25083
+ function buildThinkWithMeSystemPrompt(opts = {}) {
25084
+ const sessionBlock = opts.sessionContext ? `
25085
+ PREVIOUS SESSION CONTEXT:
25086
+ The user resumed an earlier session. Here is what they were investigating before:
25087
+ ${opts.sessionContext}
25088
+ Treat this as already-established background. Pick up where it left off \u2014 do not re-introduce it as if it were new.
25089
+
25090
+ ` : "";
25091
+ const memorySection = opts.memoryBlock ? `
25092
+ WHAT YOU ALREADY KNOW ABOUT THIS BUSINESS (durable memory):
25093
+ ${opts.memoryBlock}
25094
+ Reference this naturally. Do not re-derive things you already know; build on them.
25095
+
25096
+ ` : "";
25097
+ const analysisSection = opts.analysisBlock ? `
25098
+ SESSION ANALYSIS CONTEXT:
25099
+ ${opts.analysisBlock}
25100
+ Use get_revenue_metrics and get_revenue_metrics_timeseries when the user asks about SaaS metrics, retention, or period trends.
25101
+
25102
+ ` : "";
25103
+ const artifactSection = opts.sessionArtifact ? `
25104
+ COMPLETED SESSION ANALYSIS:
25105
+ ${opts.sessionArtifact}
25106
+ Cite numbers from here; call tools when you need a new cut or to pressure-test a claim.
25107
+
25108
+ ` : "";
25109
+ const conversationSection = opts.conversationBlock ? `
25110
+ CONVERSATION STATE:
25111
+ ${opts.conversationBlock}
25112
+
25113
+ ` : "";
25114
+ const scratchSection = buildScratchBlock(opts.thinkState);
25115
+ const socraticCraft = `HOW YOU THINK WITH THE USER (socratic partner \u2014 not a search box, not a strategist):
25116
+ - You are a thinking partner. Prefer sharp questions that unlock the user's idea over dumping answers.
25117
+ - Protect imagination: give "what if" space before the smell-test \u2014 do not kill creativity in the first sentence.
25118
+ - Steelman the user's position before you attack it; then deliver one hard pushback grounded in evidence when possible.
25119
+ - Ground claims about THIS pipeline in tool results. Label speculation explicitly ("hypothesis:", "speculation:").
25120
+ - Each turn should ADVANCE the thread: a new question, a challenge, a synthesis, or a fork \u2014 never rehash.
25121
+ - If the question is ambiguous, ask at most ONE clarifying question. Otherwise choose a fork and state it.
25122
+ - Never invent a multi-week roadmap inline. When they want commitment, call draft_strategy with a crisp objective.
25123
+ - Keep open_questions, challenged_assumptions, and working_hypotheses current via update_think_scratch.
25124
+ - You have continuity via prior think-channel messages. Never repeat an angle already covered unless asked.`;
25125
+ const jobSection = `YOUR JOB (THINK CHANNEL \u2014 always deep):
25126
+ - Decide whether you need tools, a direct answer, or both. Do not re-call a tool whose result you already have.
25127
+ - Lead with the answer or the question that matters most, then structure.
25128
+ - When you use numbers, include dollar values where available and lead with financial impact.
25129
+ - Descriptive exploration stays in this channel; plan-of-attack questions hand off via draft_strategy.
25130
+ - After a successful draft_strategy tool result: reply with at most 1\u20132 sentences introducing the handoff. Do not write the plan.`;
25131
+ const formattingSection = `
25132
+ FORMATTING (your answer is rendered in a terminal via a small markdown renderer):
25133
+ - Use **bold** for every dollar figure, score, play name, and person name.
25134
+ - Use *italics* for conversational asides and your closing follow-up question.
25135
+ - Use ### for section headings \u2014 never # or ##. The renderer flattens depth.
25136
+ - For multi-point answers, prefer a one-line lead + bullet list over long paragraph blocks.
25137
+ - Keep paragraphs to 3-4 sentences.
25138
+ - Prefer short tables (\u22643 columns, \u22645 rows, cells \u226430 chars).
25139
+ - End with a dim horizontal rule (---) followed by one italicized follow-up question or fork.
25140
+
25141
+ ${USER_VISIBLE_STE_BLOCK}
25142
+ `;
25143
+ const commandSection = `PRESET COMMANDS (slash commands the user can type \u2014 you may SUGGEST these; you cannot run them):
25144
+ ${buildCommandCatalogBlock()}
25145
+
25146
+ COMMAND SUGGESTION RULES:
25147
+ - Suggest at most ONE command when it adds capability beyond your answer (e.g. \`/strategy\`, \`/handoff\`).
25148
+ - Never claim a command was run. Never invent flags.
25149
+ - Type \`done\` or \`cancel\` leaves the think channel back to ask \u203A.`;
25150
+ const stable = `You are a world-class GTM operating partner in a dedicated THINK WITH ME channel. The user wants collaborative exploration \u2014 imagination, pressure-testing, and evidence \u2014 not a slide deck and not a finished strategy plan.
25151
+
25152
+ ${companyContextSection3()}${operatorSection3()}${socraticCraft}
25153
+
25154
+ ANALYST INSTINCT (judgment a CEO pays for \u2014 apply by default):
25155
+ ${ANALYST_INSTINCT_BLOCK}
25156
+
25157
+ ${jobSection}
25158
+
25159
+ EXECUTION BIAS (how you work):
25160
+ ${EXECUTION_BIAS_BLOCK}
25161
+
25162
+ GTM ENGINEERING (how recommendations become systems):
25163
+ ${GTM_ENGINEERING_BLOCK}
25164
+
25165
+ OUTPUT DOCTRINE (how answers are structured for recall):
25166
+ ${PYRAMID_OUTPUT_BLOCK}
25167
+
25168
+ ${USER_VISIBLE_STE_BLOCK}
25169
+
25170
+ CONTEXT:
25171
+ The user's health scores and top divergences were included as JSON at the start of this conversation. Use them, the think-channel history, and SESSION STATE as background and as hints for which tools to call.
25172
+
25173
+ VITAL SIGNS EXPLAINED (with dollar translations):
25174
+ ${VITAL_SIGNS_BLOCK}
25175
+
25176
+ PLAYBOOK \u2014 name a play when it helps the user act (not a full program):
25177
+ ${buildPlaybookBlock()}
25178
+
25179
+ ${commandSection}
25180
+ ${formattingSection}
25181
+ OUTPUT RULES:
25182
+ - Respond in plain text markdown (not JSON). You do NOT need to emit the findings schema.
25183
+ - Include specific numbers from tool results, never guess.
25184
+ - When you have enough information, answer or ask \u2014 don't call tools you don't need.
25185
+
25186
+ SAFETY & EVIDENCE (non-negotiable):
25187
+ ${SAFETY_BLOCK}`;
25188
+ const dynamicSections = [
25189
+ sessionBlock,
25190
+ memorySection,
25191
+ analysisSection,
25192
+ artifactSection,
25193
+ conversationSection,
25194
+ scratchSection
25195
+ ].map((s) => s.trim()).filter(Boolean);
25196
+ const dynamic = [
25197
+ "SESSION STATE (current \u2014 changes as the session progresses):",
25198
+ ...dynamicSections,
25199
+ buildRuntimeBlock()
25200
+ ].join("\n\n");
25201
+ return { stable, dynamic };
25202
+ }
25203
+ var init_think_prompt = __esm({
25204
+ "src/ai/think-prompt.ts"() {
25205
+ "use strict";
25206
+ init_prompt_parts();
25207
+ }
25208
+ });
25209
+
25210
+ // src/ai/agentic-loop.ts
25211
+ function companyContextSection4() {
24555
25212
  const block = buildCompanyProfileBlock();
24556
25213
  if (!block) return "";
24557
25214
  return `COMPANY CONTEXT (use this to make every answer specific to the business \u2014 use industry-appropriate language, anchor dollar figures to their deal size):
@@ -24559,7 +25216,7 @@ ${block}
24559
25216
 
24560
25217
  `;
24561
25218
  }
24562
- function operatorSection3() {
25219
+ function operatorSection4() {
24563
25220
  const block = buildOperatorBlock();
24564
25221
  if (!block) return "";
24565
25222
  return `${block}
@@ -24569,7 +25226,7 @@ function operatorSection3() {
24569
25226
  function buildSystemPrompt2() {
24570
25227
  const stable = `You are an expert GTM health investigator. You have tools to query a local database of CRM and pipeline data. Your job is to investigate the health scores you've been given and discover the specific root causes behind any problems.
24571
25228
 
24572
- ${companyContextSection3()}${operatorSection3()}INVESTIGATION APPROACH:
25229
+ ${companyContextSection4()}${operatorSection4()}INVESTIGATION APPROACH:
24573
25230
  1. Start by examining the health summary to understand the overall picture
24574
25231
  2. Drill into the lowest-scoring vital signs using get_vital_sign_detail
24575
25232
  3. Check divergences to find segments that are significantly worse than average
@@ -24758,7 +25415,7 @@ ${buildPlaybookBlock()}
24758
25415
  ${commandSection}`;
24759
25416
  const stable = `You are a world-class GTM operating partner \u2014 the kind of analyst a CEO keeps on speed dial. You are exceptionally well-read, rigorous, and commercially sharp, and you have tools to query a local database of this company's CRM and pipeline data. The user is having an ongoing, free-form conversation with you about their go-to-market health and SaaS metrics.
24760
25417
 
24761
- ${companyContextSection3()}${operatorSection3()}${conversationRules}
25418
+ ${companyContextSection4()}${operatorSection4()}${conversationRules}
24762
25419
 
24763
25420
  ${analystSection}
24764
25421
 
@@ -24804,20 +25461,27 @@ async function* agenticFindings(computeResult, divergences, options) {
24804
25461
  assertReplAi(options.ctx);
24805
25462
  const mode = options.mode ?? "investigation";
24806
25463
  const experiment = options.experiment ?? "production";
24807
- const responseMode = experiment === "baseline" || experiment === "a" || experiment === "b" ? "deep" : options.responseMode ?? (options.sessionArtifact ? "brief" : "deep");
24808
- const useTools = mode === "investigation" || responseMode === "deep";
25464
+ const responseMode = mode === "think" ? "deep" : experiment === "baseline" || experiment === "a" || experiment === "b" ? "deep" : options.responseMode ?? (options.sessionArtifact ? "brief" : "deep");
25465
+ const useTools = mode === "investigation" || mode === "think" || responseMode === "deep";
24809
25466
  const maxTokens = mode === "fresh" && responseMode === "brief" ? BRIEF_MAX_TOKENS : DEEP_MAX_TOKENS;
24810
25467
  const surface = mode === "fresh" ? responseMode === "brief" ? "agentic_fresh_brief" : "agentic_investigation" : "agentic_investigation";
24811
25468
  const llmCfg = loadLlmConfig();
24812
25469
  const tier = tierForSurface(surface, llmCfg.tier);
24813
- const systemPrompt = mode === "fresh" ? buildFreshNlSystemPrompt(
25470
+ const systemPrompt = mode === "think" ? buildThinkWithMeSystemPrompt({
25471
+ sessionContext: options.sessionContext,
25472
+ memoryBlock: options.memoryBlock,
25473
+ analysisBlock: options.analysisBlock,
25474
+ conversationBlock: options.conversationBlock,
25475
+ sessionArtifact: options.sessionArtifact,
25476
+ thinkState: options.ctx.thinkState
25477
+ }) : mode === "fresh" ? buildFreshNlSystemPrompt(
24814
25478
  options.sessionContext,
24815
25479
  options.memoryBlock,
24816
25480
  options.analysisBlock,
24817
25481
  options.conversationBlock,
24818
25482
  { responseMode, sessionArtifact: options.sessionArtifact, experiment }
24819
25483
  ) : buildSystemPrompt2();
24820
- const tools2 = useTools ? mode === "fresh" ? buildFreshNlTools() : buildInvestigationTools() : [];
25484
+ const tools2 = useTools ? mode === "think" ? buildThinkTools() : mode === "fresh" ? buildFreshNlTools() : buildInvestigationTools() : [];
24821
25485
  const toolCtx = { computeResult, divergences };
24822
25486
  if (options.includeMetrics) {
24823
25487
  try {
@@ -24829,7 +25493,8 @@ async function* agenticFindings(computeResult, divergences, options) {
24829
25493
  const initialContext = buildInitialContext(computeResult, divergences, options.userQuestion);
24830
25494
  const priorRaw = options.priorMessages ?? [];
24831
25495
  const priorMessages = priorRaw.length > 0 && typeof priorRaw[0] === "object" && priorRaw[0] !== null && "content" in priorRaw[0] ? normalizeThread(priorRaw) : priorRaw;
24832
- const messages = mode === "fresh" && priorMessages.length > 0 && options.userQuestion ? [...priorMessages, { role: "user", content: options.userQuestion }] : [{ role: "user", content: initialContext }];
25496
+ const conversational = mode === "fresh" || mode === "think";
25497
+ const messages = conversational && priorMessages.length > 0 && options.userQuestion ? [...priorMessages, { role: "user", content: options.userQuestion }] : [{ role: "user", content: initialContext }];
24833
25498
  let lastMeta = { provider_used: "anthropic", model_used: "unknown" };
24834
25499
  const loopGuard = new ToolLoopGuard();
24835
25500
  const allowedTools = new Set(tools2.map((t) => t.name));
@@ -24859,7 +25524,7 @@ async function* agenticFindings(computeResult, divergences, options) {
24859
25524
  const response = await callLlm(messages, maxTokens, true);
24860
25525
  if (response.tool_calls.length === 0) {
24861
25526
  const fullText = response.text;
24862
- if (mode === "fresh") {
25527
+ if (conversational) {
24863
25528
  const findings3 = parseFindings(fullText);
24864
25529
  if (findings3.length > 0) {
24865
25530
  for (const finding of findings3) yield { type: "finding", finding };
@@ -24907,7 +25572,7 @@ async function* agenticFindings(computeResult, divergences, options) {
24907
25572
  });
24908
25573
  }
24909
25574
  }
24910
- if (mode === "fresh") {
25575
+ if (conversational) {
24911
25576
  messages.push({
24912
25577
  role: "user",
24913
25578
  content: "You've reached the tool budget. Please answer the user's question now with what you've learned."
@@ -24983,6 +25648,7 @@ var init_agentic_loop = __esm({
24983
25648
  init_thread();
24984
25649
  init_untrusted();
24985
25650
  init_prompt_parts();
25651
+ init_think_prompt();
24986
25652
  MAX_ITERATIONS = 10;
24987
25653
  INVESTIGATION_EVIDENCE_NUDGE_AFTER = 5;
24988
25654
  BRIEF_MAX_TOKENS = 768;