reasonix 0.34.0 → 0.35.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 (52) hide show
  1. package/dashboard/app.css +16 -14
  2. package/dashboard/dist/app.js +35 -15
  3. package/dashboard/dist/app.js.map +1 -1
  4. package/dist/cli/{chat-TL4HMNEQ.js → chat-AB5D7I3V.js} +9 -9
  5. package/dist/cli/{chunk-5SAMVHA3.js → chunk-GPHBJWCV.js} +395 -175
  6. package/dist/cli/chunk-GPHBJWCV.js.map +1 -0
  7. package/dist/cli/{chunk-F3ILWP2L.js → chunk-IDP65VCC.js} +2 -2
  8. package/dist/cli/{chunk-OERAGRJX.js → chunk-JJTOZPM3.js} +2 -2
  9. package/dist/cli/{chunk-U3V2ZQ5J.js → chunk-KJQIA4US.js} +6 -2
  10. package/dist/cli/chunk-KJQIA4US.js.map +1 -0
  11. package/dist/cli/{chunk-LNTORE5K.js → chunk-N2IC4XDL.js} +149 -35
  12. package/dist/cli/chunk-N2IC4XDL.js.map +1 -0
  13. package/dist/cli/{chunk-SA4UGZPG.js → chunk-RJ5GUVS2.js} +6 -1
  14. package/dist/cli/chunk-RJ5GUVS2.js.map +1 -0
  15. package/dist/cli/{chunk-Q36KBLSU.js → chunk-SN7YH6FC.js} +125 -1
  16. package/dist/cli/chunk-SN7YH6FC.js.map +1 -0
  17. package/dist/cli/{chunk-6TMHAK5D.js → chunk-ZU45XW3P.js} +2 -2
  18. package/dist/cli/code-XBEFHXVM.js +433 -0
  19. package/dist/cli/code-XBEFHXVM.js.map +1 -0
  20. package/dist/cli/{doctor-YASM64X6.js → doctor-A565GMWD.js} +4 -4
  21. package/dist/cli/index.js +15 -15
  22. package/dist/cli/{prompt-V47QKSAR.js → prompt-YEKXMNNV.js} +3 -3
  23. package/dist/cli/{replay-JEDLU7F2.js → replay-P2WC5N5X.js} +2 -2
  24. package/dist/cli/replay-P2WC5N5X.js.map +1 -0
  25. package/dist/cli/{run-NHD2RSTD.js → run-QBWJETS3.js} +6 -6
  26. package/dist/cli/{server-MC4A4WAJ.js → server-SMLVXIW4.js} +5 -5
  27. package/dist/cli/{sessions-ZHWJEW4L.js → sessions-55RIZVWG.js} +6 -6
  28. package/dist/cli/{setup-DK43MT47.js → setup-QXMONZ4P.js} +2 -2
  29. package/dist/cli/{version-O362UKPM.js → version-Q2HA3AAC.js} +6 -6
  30. package/dist/index.d.ts +5 -0
  31. package/dist/index.js +273 -31
  32. package/dist/index.js.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/cli/chunk-5SAMVHA3.js.map +0 -1
  35. package/dist/cli/chunk-LNTORE5K.js.map +0 -1
  36. package/dist/cli/chunk-Q36KBLSU.js.map +0 -1
  37. package/dist/cli/chunk-SA4UGZPG.js.map +0 -1
  38. package/dist/cli/chunk-U3V2ZQ5J.js.map +0 -1
  39. package/dist/cli/code-V6F4BKMG.js +0 -153
  40. package/dist/cli/code-V6F4BKMG.js.map +0 -1
  41. package/dist/cli/replay-JEDLU7F2.js.map +0 -1
  42. /package/dist/cli/{chat-TL4HMNEQ.js.map → chat-AB5D7I3V.js.map} +0 -0
  43. /package/dist/cli/{chunk-F3ILWP2L.js.map → chunk-IDP65VCC.js.map} +0 -0
  44. /package/dist/cli/{chunk-OERAGRJX.js.map → chunk-JJTOZPM3.js.map} +0 -0
  45. /package/dist/cli/{chunk-6TMHAK5D.js.map → chunk-ZU45XW3P.js.map} +0 -0
  46. /package/dist/cli/{doctor-YASM64X6.js.map → doctor-A565GMWD.js.map} +0 -0
  47. /package/dist/cli/{prompt-V47QKSAR.js.map → prompt-YEKXMNNV.js.map} +0 -0
  48. /package/dist/cli/{run-NHD2RSTD.js.map → run-QBWJETS3.js.map} +0 -0
  49. /package/dist/cli/{server-MC4A4WAJ.js.map → server-SMLVXIW4.js.map} +0 -0
  50. /package/dist/cli/{sessions-ZHWJEW4L.js.map → sessions-55RIZVWG.js.map} +0 -0
  51. /package/dist/cli/{setup-DK43MT47.js.map → setup-QXMONZ4P.js.map} +0 -0
  52. /package/dist/cli/{version-O362UKPM.js.map → version-Q2HA3AAC.js.map} +0 -0
@@ -34,7 +34,7 @@ import {
34
34
  toWholeFileEditBlock,
35
35
  walkFilesStream,
36
36
  webFetch
37
- } from "./chunk-LNTORE5K.js";
37
+ } from "./chunk-N2IC4XDL.js";
38
38
  import {
39
39
  McpClient,
40
40
  SseTransport,
@@ -50,7 +50,7 @@ import {
50
50
  } from "./chunk-XHQIK7B6.js";
51
51
  import {
52
52
  MemoryStore
53
- } from "./chunk-6TMHAK5D.js";
53
+ } from "./chunk-ZU45XW3P.js";
54
54
  import {
55
55
  KeystrokeProvider,
56
56
  SingleSelect,
@@ -71,7 +71,7 @@ import {
71
71
  } from "./chunk-MHDNZXJJ.js";
72
72
  import {
73
73
  runDoctorChecks
74
- } from "./chunk-F3ILWP2L.js";
74
+ } from "./chunk-IDP65VCC.js";
75
75
  import {
76
76
  countTokens
77
77
  } from "./chunk-DAEAAVDF.js";
@@ -97,7 +97,7 @@ import {
97
97
  resolveSlashAlias,
98
98
  savePlanState,
99
99
  suggestSlashCommands
100
- } from "./chunk-SA4UGZPG.js";
100
+ } from "./chunk-RJ5GUVS2.js";
101
101
  import {
102
102
  eventLogPath,
103
103
  openEventSink
@@ -119,7 +119,7 @@ import {
119
119
  SkillStore,
120
120
  memoryEnabled,
121
121
  readProjectMemory
122
- } from "./chunk-U3V2ZQ5J.js";
122
+ } from "./chunk-KJQIA4US.js";
123
123
  import {
124
124
  HOOK_EVENTS,
125
125
  formatHookOutcomeMessage,
@@ -127,7 +127,7 @@ import {
127
127
  loadHooks,
128
128
  projectSettingsPath,
129
129
  runHooks
130
- } from "./chunk-OERAGRJX.js";
130
+ } from "./chunk-JJTOZPM3.js";
131
131
  import {
132
132
  VERSION,
133
133
  compareVersions,
@@ -154,7 +154,7 @@ import {
154
154
  setLanguage,
155
155
  t,
156
156
  tObj
157
- } from "./chunk-Q36KBLSU.js";
157
+ } from "./chunk-SN7YH6FC.js";
158
158
  import {
159
159
  addProjectShellAllowed,
160
160
  clearProjectShellAllowed,
@@ -232,7 +232,7 @@ function buildMcpServerSummary(opts) {
232
232
  import { statSync } from "fs";
233
233
  import { resolve as resolve2 } from "path";
234
234
  import { Box as Box49, Text as Text52, useStdout as useStdout14 } from "ink";
235
- import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef8, useState as useState20 } from "react";
235
+ import React60, { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef9, useState as useState20 } from "react";
236
236
 
237
237
  // src/code/checkpoints.ts
238
238
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
@@ -2376,7 +2376,12 @@ function PlanStepListInner({ steps, statuses, focusStepId }) {
2376
2376
  const doneCount = statusList.filter((s) => s === "done").length;
2377
2377
  const pct = Math.round(doneCount / total * 100);
2378
2378
  const showProgress = doneCount > 0;
2379
- return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text13, { dimColor: true }, showProgress ? `${doneCount}/${total} done (${pct}%) \xB7 ${total} step${total === 1 ? "" : "s"}` : `${total} step${total === 1 ? "" : "s"}`)), /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, steps.map((step, i) => {
2379
+ return /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, /* @__PURE__ */ React15.createElement(Box12, null, /* @__PURE__ */ React15.createElement(Text13, { dimColor: true }, showProgress ? t(
2380
+ total === 1 ? "planFlow.stepList.counterDoneSingular" : "planFlow.stepList.counterDone",
2381
+ { done: doneCount, total, pct }
2382
+ ) : t(total === 1 ? "planFlow.stepList.counterSingular" : "planFlow.stepList.counter", {
2383
+ total
2384
+ }))), /* @__PURE__ */ React15.createElement(Box12, { flexDirection: "column" }, steps.map((step, i) => {
2380
2385
  const status2 = statusList[i];
2381
2386
  const isLast = i === total - 1;
2382
2387
  const isCur = focusStepId === step.id;
@@ -2413,25 +2418,25 @@ function PlanCheckpointConfirmInner({
2413
2418
  const isLast = total > 0 && completed >= total;
2414
2419
  const statuses = buildStatusMap(steps, completedStepIds, stepId, isLast);
2415
2420
  const subtitle = counter ? `${counter} \xB7 ${label}` : label;
2416
- return /* @__PURE__ */ React16.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: "Checkpoint \u2014 step done", metaRight: subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React16.createElement(
2421
+ return /* @__PURE__ */ React16.createElement(ApprovalCard, { tone: "ok", glyph: "\u26C1", title: t("planFlow.checkpoint.title"), metaRight: subtitle }, steps && steps.length > 0 ? /* @__PURE__ */ React16.createElement(Box13, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(PlanStepList, { steps, statuses, focusStepId: stepId })) : null, /* @__PURE__ */ React16.createElement(
2417
2422
  SingleSelect,
2418
2423
  {
2419
2424
  initialValue: isLast ? "stop" : "continue",
2420
2425
  items: [
2421
2426
  {
2422
2427
  value: "continue",
2423
- label: "Continue \u2014 run the next step",
2424
- hint: "Model resumes with the next step."
2428
+ label: t("planFlow.checkpoint.continue"),
2429
+ hint: t("planFlow.checkpoint.continueHint")
2425
2430
  },
2426
2431
  {
2427
2432
  value: "revise",
2428
- label: "Revise \u2014 give feedback before the next step",
2429
- hint: "Stay paused, type guidance; model adjusts the remaining plan."
2433
+ label: t("planFlow.checkpoint.revise"),
2434
+ hint: t("planFlow.checkpoint.reviseHint")
2430
2435
  },
2431
2436
  {
2432
2437
  value: "stop",
2433
- label: "Stop \u2014 end the plan here",
2434
- hint: "Model summarizes what was done and ends."
2438
+ label: t("planFlow.checkpoint.stop"),
2439
+ hint: t("planFlow.checkpoint.stopHint")
2435
2440
  }
2436
2441
  ],
2437
2442
  onSubmit: (v) => onChoose(v),
@@ -4886,53 +4891,89 @@ function SpanText({
4886
4891
  );
4887
4892
  }
4888
4893
 
4894
+ // src/cli/ui/plan-open-questions.ts
4895
+ var HEADER_RE = /^(#{1,6})\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear|待确认|开放问题|风险|未知|假设|不确定)(?:[\s::/、,,].*)?$/im;
4896
+ function extractOpenQuestionsSection(plan2) {
4897
+ const lines = plan2.split("\n");
4898
+ let startIdx = -1;
4899
+ let startLevel = 0;
4900
+ for (let i = 0; i < lines.length; i++) {
4901
+ const line = lines[i] ?? "";
4902
+ const m = line.match(HEADER_RE);
4903
+ if (m) {
4904
+ startIdx = i;
4905
+ startLevel = (m[1] ?? "#").length;
4906
+ break;
4907
+ }
4908
+ }
4909
+ if (startIdx === -1) return null;
4910
+ let endIdx = lines.length;
4911
+ for (let j = startIdx + 1; j < lines.length; j++) {
4912
+ const line = lines[j] ?? "";
4913
+ const lh = line.match(/^(#{1,6})\s+\S/);
4914
+ if (lh && (lh[1] ?? "").length <= startLevel) {
4915
+ endIdx = j;
4916
+ break;
4917
+ }
4918
+ }
4919
+ const block2 = lines.slice(startIdx, endIdx).join("\n").replace(/\s+$/g, "");
4920
+ return block2.length > 0 ? block2 : null;
4921
+ }
4922
+
4889
4923
  // src/cli/ui/PlanConfirm.tsx
4890
4924
  var PLAN_BODY_PREVIEW_LINES = 24;
4891
4925
  function PlanConfirmInner({ plan: plan2, steps, onChoose }) {
4892
4926
  const stepRows = steps?.length ?? 0;
4893
4927
  const hasSteps = stepRows > 0;
4928
+ const openQuestions = extractOpenQuestionsSection(plan2);
4894
4929
  const planLines = plan2.split("\n");
4895
4930
  const truncatedBody = planLines.length > PLAN_BODY_PREVIEW_LINES;
4896
4931
  const previewBody = truncatedBody ? planLines.slice(0, PLAN_BODY_PREVIEW_LINES).join("\n") : plan2;
4897
4932
  const previewRows = truncatedBody ? PLAN_BODY_PREVIEW_LINES : Math.min(planLines.length, PLAN_BODY_PREVIEW_LINES);
4898
4933
  const reservedFor = hasSteps ? stepRows : previewRows;
4899
- useReserveRows("modal", { min: 10, max: Math.max(16, reservedFor + 14) });
4900
- const hasOpenQuestions = /^#{1,6}\s*(open[-\s]?questions?|risks?|unknowns?|assumptions?|unclear)/im.test(plan2) || /^#{1,6}\s*(待确认|开放问题|风险|未知|假设|不确定)/im.test(plan2);
4934
+ const oqRows = openQuestions ? openQuestions.split("\n").length : 0;
4935
+ useReserveRows("modal", { min: 10, max: Math.max(16, reservedFor + oqRows + 14) });
4936
+ const refineLabel = t("planFlow.picker.refine");
4937
+ const bannerTemplate = t("planFlow.openQuestionsBanner");
4938
+ const [bannerBefore, bannerAfter] = bannerTemplate.split("{refine}");
4901
4939
  return /* @__PURE__ */ React18.createElement(
4902
4940
  ApprovalCard,
4903
4941
  {
4904
4942
  tone: "accent",
4905
4943
  glyph: "\u229E",
4906
- title: "Approve plan",
4907
- metaRight: "awaiting",
4944
+ title: t("planFlow.approveCardTitle"),
4945
+ metaRight: t("planFlow.approveCardMetaRight"),
4908
4946
  metaRightColor: CARD.plan.color
4909
4947
  },
4910
- hasOpenQuestions ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text15, { color: TONE.warn }, "\u25B2 the plan flags open questions or risks \u2014 pick ", /* @__PURE__ */ React18.createElement(Text15, { bold: true }, "refine"), " to write concrete answers before the model moves on.")) : null,
4911
- hasSteps ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(PlanStepList, { steps })) : plan2.trim().length > 0 ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(MarkdownView, { text: previewBody }), truncatedBody ? /* @__PURE__ */ React18.createElement(Text15, { color: FG.faint }, `\u2026 ${planLines.length - PLAN_BODY_PREVIEW_LINES} more line${planLines.length - PLAN_BODY_PREVIEW_LINES === 1 ? "" : "s"} above in scrollback`) : null) : null,
4948
+ openQuestions ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Text15, { color: TONE.warn }, bannerBefore ?? "", /* @__PURE__ */ React18.createElement(Text15, { bold: true }, refineLabel), bannerAfter ?? ""), /* @__PURE__ */ React18.createElement(Box15, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(Text15, { color: TONE.warn, bold: true }, t("planFlow.openQuestionsHeader")), /* @__PURE__ */ React18.createElement(MarkdownView, { text: openQuestions }))) : null,
4949
+ hasSteps ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(PlanStepList, { steps })) : plan2.trim().length > 0 ? /* @__PURE__ */ React18.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React18.createElement(MarkdownView, { text: previewBody }), truncatedBody ? /* @__PURE__ */ React18.createElement(Text15, { color: FG.faint }, t(
4950
+ planLines.length - PLAN_BODY_PREVIEW_LINES === 1 ? "planFlow.truncatedBodyMore" : "planFlow.truncatedBodyMorePlural",
4951
+ { n: planLines.length - PLAN_BODY_PREVIEW_LINES }
4952
+ )) : null) : null,
4912
4953
  /* @__PURE__ */ React18.createElement(
4913
4954
  SingleSelect,
4914
4955
  {
4915
- initialValue: hasOpenQuestions ? "refine" : "approve",
4956
+ initialValue: openQuestions ? "refine" : "approve",
4916
4957
  items: [
4917
4958
  {
4918
4959
  value: "approve",
4919
- label: "accept",
4920
- hint: "run it now, in order"
4960
+ label: t("planFlow.picker.accept"),
4961
+ hint: t("planFlow.picker.acceptHint")
4921
4962
  },
4922
4963
  {
4923
4964
  value: "refine",
4924
- label: "refine",
4925
- hint: "give the agent more guidance, draft a new plan"
4965
+ label: refineLabel,
4966
+ hint: t("planFlow.picker.refineHint")
4926
4967
  },
4927
4968
  {
4928
4969
  value: "revise",
4929
- label: "revise",
4930
- hint: "edit the plan inline before running (skip / reorder steps)"
4970
+ label: t("planFlow.picker.revise"),
4971
+ hint: t("planFlow.picker.reviseHint")
4931
4972
  },
4932
4973
  {
4933
4974
  value: "cancel",
4934
- label: "reject",
4935
- hint: "discard, agent will retry from scratch"
4975
+ label: t("planFlow.picker.reject"),
4976
+ hint: t("planFlow.picker.rejectHint")
4936
4977
  }
4937
4978
  ],
4938
4979
  onSubmit: (v) => onChoose(v),
@@ -4974,49 +5015,25 @@ function useElapsedSeconds() {
4974
5015
  }
4975
5016
 
4976
5017
  // src/cli/ui/PlanRefineInput.tsx
4977
- var MODES = {
4978
- approve: {
4979
- title: "approving \u2014 any last instructions?",
4980
- glyph: "\u25C7",
4981
- tone: "user",
4982
- cursorColor: CARD.user.color,
4983
- hint: "Answer questions the plan raised, add constraints, or just press Enter to approve as-is.",
4984
- blankHint: " (Enter with blank = approve without extra instructions.)"
4985
- },
4986
- refine: {
4987
- title: "refining \u2014 what should the model change?",
4988
- glyph: "\u270E",
4989
- tone: "warn",
4990
- cursorColor: CARD.warn.color,
4991
- hint: "Describe what's wrong or missing, or answer questions the plan raised.",
4992
- blankHint: " (Enter with blank = ask the model to list concrete questions.)"
4993
- },
4994
- reject: {
4995
- title: "rejecting \u2014 tell the model why (optional)",
4996
- glyph: "\u2717",
4997
- tone: "error",
4998
- cursorColor: CARD.error.color,
4999
- hint: "Say what the model got wrong about your goal, or what you actually want instead.",
5000
- blankHint: " (Enter with blank = cancel without explanation; the model will ask what you want.)"
5001
- },
5002
- "checkpoint-revise": {
5003
- title: "revising \u2014 what should change before the next step?",
5004
- glyph: "\u270E",
5005
- tone: "warn",
5006
- cursorColor: CARD.warn.color,
5007
- hint: "Scope change, skip steps, alternative approach \u2014 the model adjusts the remaining plan.",
5008
- blankHint: " (Enter with blank = continue with the current plan.)"
5009
- },
5010
- "choice-custom": {
5011
- title: "custom answer \u2014 type whatever fits",
5012
- glyph: "\u2325",
5013
- tone: "accent",
5014
- cursorColor: CARD.plan.color,
5015
- hint: "Free-form reply. The model reads it verbatim and proceeds \u2014 no need to match the listed options.",
5016
- blankHint: " (Enter with blank = ask the model what you actually want.)"
5017
- }
5018
+ var MODE_VISUALS = {
5019
+ approve: { glyph: "\u25C7", tone: "user", cursorColor: CARD.user.color },
5020
+ refine: { glyph: "\u270E", tone: "warn", cursorColor: CARD.warn.color },
5021
+ reject: { glyph: "\u2717", tone: "error", cursorColor: CARD.error.color },
5022
+ "checkpoint-revise": { glyph: "\u270E", tone: "warn", cursorColor: CARD.warn.color },
5023
+ "choice-custom": { glyph: "\u2325", tone: "accent", cursorColor: CARD.plan.color }
5018
5024
  };
5019
- function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
5025
+ function modeMeta(mode2) {
5026
+ const v = MODE_VISUALS[mode2];
5027
+ return {
5028
+ title: t(`planFlow.modes.${mode2}.title`),
5029
+ hint: t(`planFlow.modes.${mode2}.hint`),
5030
+ blankHint: t(`planFlow.modes.${mode2}.blankHint`),
5031
+ glyph: v.glyph,
5032
+ tone: v.tone,
5033
+ cursorColor: v.cursorColor
5034
+ };
5035
+ }
5036
+ function PlanRefineInput({ mode: mode2, questions, onSubmit, onCancel }) {
5020
5037
  const [value, setValue] = useState9("");
5021
5038
  useKeystroke((ev) => {
5022
5039
  if (ev.paste) {
@@ -5041,15 +5058,17 @@ function PlanRefineInput({ mode: mode2, onSubmit, onCancel }) {
5041
5058
  });
5042
5059
  const tick = useTick();
5043
5060
  const cursorOn = Math.floor(tick / 4) % 2 === 0;
5044
- const meta = MODES[mode2];
5061
+ const meta = modeMeta(mode2);
5062
+ const showQuestions = mode2 === "refine" && !!questions && questions.trim().length > 0;
5045
5063
  return /* @__PURE__ */ React20.createElement(
5046
5064
  ApprovalCard,
5047
5065
  {
5048
5066
  tone: meta.tone,
5049
5067
  glyph: meta.glyph,
5050
5068
  title: meta.title,
5051
- footerHint: "\u23CE send \xB7 esc return to picker"
5069
+ footerHint: t("planFlow.refineFooter")
5052
5070
  },
5071
+ showQuestions ? /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React20.createElement(Text16, { color: TONE.warn, bold: true }, t("planFlow.refineQuestionsHeading")), /* @__PURE__ */ React20.createElement(MarkdownView, { text: questions })) : null,
5053
5072
  /* @__PURE__ */ React20.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React20.createElement(Text16, { color: FG.sub }, meta.hint, value === "" ? meta.blankHint : "")),
5054
5073
  /* @__PURE__ */ React20.createElement(Box16, null, /* @__PURE__ */ React20.createElement(Text16, { color: meta.cursorColor, bold: true }, "\u203A "), /* @__PURE__ */ React20.createElement(Text16, null, value), /* @__PURE__ */ React20.createElement(Text16, { color: meta.cursorColor, bold: true }, cursorOn ? "\u258D" : " "))
5055
5074
  );
@@ -6856,31 +6875,64 @@ function useAgentSession({
6856
6875
  }
6857
6876
 
6858
6877
  // src/cli/ui/hooks/useChatScroll.ts
6859
- import { useCallback as useCallback2, useEffect as useEffect4, useState as useState14 } from "react";
6878
+ import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef2, useState as useState14 } from "react";
6860
6879
  var SCROLL_PAGE_ROWS = 3;
6880
+ var COALESCE_MS = 16;
6861
6881
  function useChatScroll() {
6862
6882
  const [scrollRows, setScrollRows] = useState14(0);
6863
6883
  const [pinned, setPinned] = useState14(true);
6864
6884
  const [maxScroll, setMaxScrollState] = useState14(0);
6885
+ const maxScrollRef = useRef2(0);
6886
+ const pendingDelta = useRef2(0);
6887
+ const flushTimer = useRef2(null);
6888
+ const flush = useCallback2(() => {
6889
+ flushTimer.current = null;
6890
+ const d = pendingDelta.current;
6891
+ pendingDelta.current = 0;
6892
+ if (d === 0) return;
6893
+ if (d < 0) setPinned(false);
6894
+ setScrollRows((o) => {
6895
+ const next = Math.max(0, Math.min(maxScrollRef.current, o + d));
6896
+ if (next >= maxScrollRef.current) setPinned(true);
6897
+ return next;
6898
+ });
6899
+ }, []);
6900
+ const schedule = useCallback2(
6901
+ (delta) => {
6902
+ pendingDelta.current += delta;
6903
+ if (flushTimer.current !== null) return;
6904
+ flushTimer.current = setTimeout(flush, COALESCE_MS);
6905
+ },
6906
+ [flush]
6907
+ );
6908
+ useEffect4(() => {
6909
+ return () => {
6910
+ if (flushTimer.current !== null) {
6911
+ clearTimeout(flushTimer.current);
6912
+ flushTimer.current = null;
6913
+ }
6914
+ };
6915
+ }, []);
6865
6916
  useEffect4(() => {
6866
6917
  if (pinned) setScrollRows(maxScroll);
6867
6918
  }, [pinned, maxScroll]);
6868
6919
  useEffect4(() => {
6869
6920
  if (scrollRows > maxScroll) setScrollRows(maxScroll);
6870
6921
  }, [scrollRows, maxScroll]);
6871
- const scrollUp = useCallback2(() => {
6872
- setPinned(false);
6873
- setScrollRows((o) => Math.max(0, o - SCROLL_PAGE_ROWS));
6922
+ const scrollUp = useCallback2(() => schedule(-SCROLL_PAGE_ROWS), [schedule]);
6923
+ const scrollDown = useCallback2(() => schedule(SCROLL_PAGE_ROWS), [schedule]);
6924
+ const jumpToBottom = useCallback2(() => {
6925
+ pendingDelta.current = 0;
6926
+ if (flushTimer.current !== null) {
6927
+ clearTimeout(flushTimer.current);
6928
+ flushTimer.current = null;
6929
+ }
6930
+ setPinned(true);
6931
+ }, []);
6932
+ const setMaxScroll = useCallback2((rows) => {
6933
+ maxScrollRef.current = rows;
6934
+ setMaxScrollState(rows);
6874
6935
  }, []);
6875
- const scrollDown = useCallback2(() => {
6876
- setScrollRows((o) => {
6877
- const next = Math.min(maxScroll, o + SCROLL_PAGE_ROWS);
6878
- if (next >= maxScroll) setPinned(true);
6879
- return next;
6880
- });
6881
- }, [maxScroll]);
6882
- const jumpToBottom = useCallback2(() => setPinned(true), []);
6883
- const setMaxScroll = useCallback2((rows) => setMaxScrollState(rows), []);
6884
6936
  return { scrollRows, pinned, scrollUp, scrollDown, jumpToBottom, setMaxScroll };
6885
6937
  }
6886
6938
 
@@ -6936,10 +6988,10 @@ function useCodeMode(opts) {
6936
6988
  }
6937
6989
 
6938
6990
  // src/cli/ui/hooks/useInputRecall.ts
6939
- import { useCallback as useCallback4, useRef as useRef2 } from "react";
6991
+ import { useCallback as useCallback4, useRef as useRef3 } from "react";
6940
6992
  function useInputRecall(setInput) {
6941
- const promptHistory = useRef2([]);
6942
- const historyCursor = useRef2(-1);
6993
+ const promptHistory = useRef3([]);
6994
+ const historyCursor = useRef3(-1);
6943
6995
  const recallPrev = useCallback4(() => {
6944
6996
  const hist = promptHistory.current;
6945
6997
  if (hist.length === 0) return;
@@ -6964,13 +7016,13 @@ function useInputRecall(setInput) {
6964
7016
  }
6965
7017
 
6966
7018
  // src/cli/ui/hooks/useLoopMode.ts
6967
- import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef3, useState as useState15 } from "react";
7019
+ import { useCallback as useCallback5, useEffect as useEffect5, useRef as useRef4, useState as useState15 } from "react";
6968
7020
  function useLoopMode(opts) {
6969
7021
  const { log, busyRef, handleSubmitRef } = opts;
6970
7022
  const [activeLoop, setActiveLoop] = useState15(null);
6971
- const activeLoopRef = useRef3(null);
6972
- const loopTimerRef = useRef3(null);
6973
- const loopFiringRef = useRef3(false);
7023
+ const activeLoopRef = useRef4(null);
7024
+ const loopTimerRef = useRef4(null);
7025
+ const loopFiringRef = useRef4(false);
6974
7026
  useEffect5(() => {
6975
7027
  activeLoopRef.current = activeLoop;
6976
7028
  }, [activeLoop]);
@@ -7699,7 +7751,7 @@ function useTranscriptWriter(transcriptRef, model2, prefixHash) {
7699
7751
 
7700
7752
  // src/cli/ui/layout/CardStream.tsx
7701
7753
  import { Box as Box44, Text as Text46, useBoxMetrics } from "ink";
7702
- import React53, { useEffect as useEffect7, useRef as useRef4 } from "react";
7754
+ import React53, { useEffect as useEffect7, useRef as useRef5 } from "react";
7703
7755
 
7704
7756
  // src/cli/ui/cards/CardRenderer.tsx
7705
7757
  import { Box as Box43, Text as Text45 } from "ink";
@@ -8809,6 +8861,7 @@ function ToolCard({ card }) {
8809
8861
  const cols = stdout?.columns ?? 80;
8810
8862
  const lineCells = Math.max(20, cols - 4);
8811
8863
  const argsLabel = formatArgsSummary(card.args);
8864
+ const subagentMarkdown = unwrapSubagentMarkdown(card);
8812
8865
  const allLines = card.output.length > 0 ? card.output.split("\n") : [];
8813
8866
  const tail = tailLinesFor(card.name);
8814
8867
  const truncated = allLines.length > tail;
@@ -8817,7 +8870,7 @@ function ToolCard({ card }) {
8817
8870
  const status2 = toolStatus(card);
8818
8871
  const headColor = headerColorFor(status2);
8819
8872
  const errColor = card.exitCode && card.exitCode !== 0 ? TONE.err : FG.sub;
8820
- const showBody = !card.rejected && visible.length > 0;
8873
+ const showBody = !card.rejected && (subagentMarkdown !== null || visible.length > 0);
8821
8874
  const meta = [];
8822
8875
  if (card.retry) {
8823
8876
  meta.push({ text: `\u21BB ${card.retry.attempt}/${card.retry.max}`, color: TONE.warn });
@@ -8836,7 +8889,7 @@ function ToolCard({ card }) {
8836
8889
  meta: meta.length > 0 ? meta : void 0,
8837
8890
  right: status2 === "running" ? /* @__PURE__ */ React48.createElement(Spinner, { kind: "braille", color: TONE_ACTIVE.brand, bold: true }) : void 0
8838
8891
  }
8839
- ), showBody && /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
8892
+ ), showBody && (subagentMarkdown !== null ? /* @__PURE__ */ React48.createElement(Markdown, { text: subagentMarkdown, width: lineCells }) : /* @__PURE__ */ React48.createElement(React48.Fragment, null, hidden > 0 ? /* @__PURE__ */ React48.createElement(Text42, { color: FG.faint }, `\u22EE ${hidden} earlier line${hidden === 1 ? "" : "s"} (use /tool to read full)`) : null, visible.map((line, i) => /* @__PURE__ */ React48.createElement(
8840
8893
  Text42,
8841
8894
  {
8842
8895
  key: `${card.id}:${hidden + i}`,
@@ -8844,7 +8897,21 @@ function ToolCard({ card }) {
8844
8897
  dimColor: !card.exitCode || card.exitCode === 0
8845
8898
  },
8846
8899
  clipToCells(line, lineCells) || " "
8847
- ))));
8900
+ )))));
8901
+ }
8902
+ function unwrapSubagentMarkdown(card) {
8903
+ if (card.name !== "spawn_subagent") return null;
8904
+ if (card.output.length === 0) return null;
8905
+ try {
8906
+ const parsed = JSON.parse(card.output);
8907
+ if (!parsed || typeof parsed !== "object") return null;
8908
+ const obj = parsed;
8909
+ if (obj.success !== true) return null;
8910
+ if (typeof obj.output !== "string") return null;
8911
+ return obj.output;
8912
+ } catch {
8913
+ return null;
8914
+ }
8848
8915
  }
8849
8916
  function toolStatus(card) {
8850
8917
  if (card.rejected) return "rejected";
@@ -9054,8 +9121,8 @@ function CardStream({
9054
9121
  suppressLive = false
9055
9122
  }) {
9056
9123
  const cards = useAgentState((s) => s.cards);
9057
- const outerRef = useRef4(null);
9058
- const innerRef = useRef4(null);
9124
+ const outerRef = useRef5(null);
9125
+ const innerRef = useRef5(null);
9059
9126
  const outer = useBoxMetrics(outerRef);
9060
9127
  const inner = useBoxMetrics(innerRef);
9061
9128
  const maxScroll = Math.max(0, inner.height - outer.height);
@@ -9287,6 +9354,8 @@ function Countdown({ endsAt, color = TONE.brand }) {
9287
9354
  var RULE_PAD = 4;
9288
9355
  var RULE_MIN = 20;
9289
9356
  var WALLET_MIN_COLS = 90;
9357
+ var VERSION_MIN_COLS = 70;
9358
+ var FEEDBACK_HINT_MIN_COLS = 100;
9290
9359
  function StatusRow() {
9291
9360
  const status2 = useAgentState((s) => s.status);
9292
9361
  const session = useAgentState((s) => s.session);
@@ -9304,7 +9373,7 @@ function StatusRow() {
9304
9373
  balance: status2.balance,
9305
9374
  currency: status2.balanceCurrency
9306
9375
  }
9307
- )));
9376
+ ), cols >= VERSION_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Sep, null), /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, `v${VERSION}`), cols >= FEEDBACK_HINT_MIN_COLS && /* @__PURE__ */ React56.createElement(React56.Fragment, null, /* @__PURE__ */ React56.createElement(Text49, { color: FG.faint }, " \xB7 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.meta }, "\u2691 "), /* @__PURE__ */ React56.createElement(Text49, { color: FG.sub }, "/feedback")))));
9308
9377
  }
9309
9378
  function WalletPill({
9310
9379
  sessionCostUsd,
@@ -10898,6 +10967,32 @@ var handlers10 = {
10898
10967
  budget
10899
10968
  };
10900
10969
 
10970
+ // src/cli/ui/slash/handlers/observability.ts
10971
+ import { release } from "os";
10972
+
10973
+ // src/cli/ui/clipboard.ts
10974
+ import { mkdtempSync, writeFileSync as writeFileSync4 } from "fs";
10975
+ import { tmpdir } from "os";
10976
+ import { join as join6 } from "path";
10977
+ var OSC_52_LIMIT = 75e3;
10978
+ function writeClipboard(text) {
10979
+ const dir = mkdtempSync(join6(tmpdir(), "reasonix-clip-"));
10980
+ const filePath = join6(dir, "clip.txt");
10981
+ let osc52 = false;
10982
+ if (text.length <= OSC_52_LIMIT) {
10983
+ const b64 = Buffer.from(text, "utf8").toString("base64");
10984
+ process.stdout.write(`\x1B]52;c;${b64}\x1B\\`);
10985
+ osc52 = true;
10986
+ }
10987
+ let writtenPath = null;
10988
+ try {
10989
+ writeFileSync4(filePath, text, "utf8");
10990
+ writtenPath = filePath;
10991
+ } catch {
10992
+ }
10993
+ return { osc52, filePath: writtenPath, size: text.length };
10994
+ }
10995
+
10901
10996
  // src/cli/ui/ctx-breakdown.tsx
10902
10997
  import { Box as Box48, Text as Text51 } from "ink";
10903
10998
  import React59 from "react";
@@ -10942,6 +11037,90 @@ function computeCtxBreakdown(loop2) {
10942
11037
  };
10943
11038
  }
10944
11039
 
11040
+ // src/cli/ui/feedback.ts
11041
+ var FEEDBACK_ISSUE_BASE = "https://github.com/esengine/DeepSeek-Reasonix/issues/new";
11042
+ var FEEDBACK_BODY_QUERY_LIMIT = 6e3;
11043
+ function buildFeedbackIssueUrl(diagnostic) {
11044
+ const trimmed = diagnostic.length > FEEDBACK_BODY_QUERY_LIMIT ? diagnostic.slice(0, FEEDBACK_BODY_QUERY_LIMIT) : diagnostic;
11045
+ return `${FEEDBACK_ISSUE_BASE}?body=${encodeURIComponent(trimmed)}`;
11046
+ }
11047
+ function buildFeedbackDiagnostic(input) {
11048
+ const lines = [];
11049
+ lines.push(`**Reasonix**: ${formatVersion(input.version, input.latestVersion)}`);
11050
+ lines.push(`**Platform**: ${input.platform} (${input.osRelease})`);
11051
+ lines.push(`**Terminal**: ${formatTerminal(input)}`);
11052
+ if (typeof input.cols === "number" && typeof input.rows === "number") {
11053
+ lines.push(`**Size**: ${input.cols}\xD7${input.rows}`);
11054
+ }
11055
+ lines.push(`**Node**: ${input.nodeVersion}`);
11056
+ lines.push(`**Locale**: ${input.locale}`);
11057
+ if (input.theme) lines.push(`**Theme**: ${input.theme}`);
11058
+ lines.push(`**Model**: ${formatModel(input.model, input.reasoningEffort)}`);
11059
+ const modeLine = formatMode(input.editMode, input.planMode);
11060
+ if (modeLine) lines.push(`**Mode**: ${modeLine}`);
11061
+ if (typeof input.mcpServerCount === "number") {
11062
+ lines.push(`**MCP**: ${input.mcpServerCount} server(s)`);
11063
+ }
11064
+ if (input.sessionId) lines.push(`**Session**: ${input.sessionId}`);
11065
+ lines.push("", "<!-- describe what you were doing when this happened -->", "");
11066
+ return lines.join("\n");
11067
+ }
11068
+ function formatVersion(installed, latest) {
11069
+ if (!latest) return installed;
11070
+ if (latest === installed) return `${installed} (latest)`;
11071
+ return `${installed} (latest: ${latest})`;
11072
+ }
11073
+ function formatModel(model2, effort) {
11074
+ return effort ? `${model2} \xB7 effort=${effort}` : model2;
11075
+ }
11076
+ function formatMode(editMode, planMode) {
11077
+ const parts = [];
11078
+ if (editMode) parts.push(`edit=${editMode}`);
11079
+ parts.push(`plan=${planMode ? "on" : "off"}`);
11080
+ return parts.join(" \xB7 ");
11081
+ }
11082
+ function formatTerminal(input) {
11083
+ const head = input.termProgram ?? "(unknown)";
11084
+ const env = [];
11085
+ if (input.termProgram) env.push(`TERM_PROGRAM=${input.termProgram}`);
11086
+ if (input.term) env.push(`TERM=${input.term}`);
11087
+ if (input.colorTerm) env.push(`COLORTERM=${input.colorTerm}`);
11088
+ if (input.inWindowsTerminal) env.push("WT_SESSION=set");
11089
+ if (input.inTmux) env.push("TMUX=set");
11090
+ if (input.inSsh) env.push("SSH_TTY=set");
11091
+ if (input.wslDistro) env.push(`WSL=${input.wslDistro}`);
11092
+ if (env.length === 0) return head;
11093
+ return `${head} (${env.join(", ")})`;
11094
+ }
11095
+
11096
+ // src/cli/ui/open-url.ts
11097
+ import { spawn } from "child_process";
11098
+ import { platform } from "os";
11099
+ function openUrl(url) {
11100
+ if (process.env.CI) return { opened: false, reason: "ci" };
11101
+ if (process.env.REASONIX_NO_OPEN) return { opened: false, reason: "disabled" };
11102
+ const os = platform();
11103
+ let cmd;
11104
+ let args;
11105
+ if (os === "win32") {
11106
+ cmd = "cmd";
11107
+ args = ["/c", "start", "", url];
11108
+ } else if (os === "darwin") {
11109
+ cmd = "open";
11110
+ args = [url];
11111
+ } else {
11112
+ cmd = "xdg-open";
11113
+ args = [url];
11114
+ }
11115
+ try {
11116
+ const child = spawn(cmd, args, { detached: true, stdio: "ignore" });
11117
+ child.unref();
11118
+ return { opened: true };
11119
+ } catch {
11120
+ return { opened: false, reason: "spawn-failed" };
11121
+ }
11122
+ }
11123
+
10945
11124
  // src/cli/ui/slash/handlers/observability.ts
10946
11125
  var context = (_args, loop2) => {
10947
11126
  const breakdown = computeCtxBreakdown(loop2);
@@ -10971,11 +11150,11 @@ var status = (_args, loop2, ctx) => {
10971
11150
  }) : t("handlers.observability.statusCtxNone");
10972
11151
  const cost2 = summary.totalCostUsd;
10973
11152
  const cacheLine = summary.turns > 3 ? (() => {
10974
- const cachePct = Math.round(summary.cacheHitRatio * 100);
11153
+ const cachePct = summary.cacheHitRatio * 100;
10975
11154
  return t("handlers.observability.statusCost", {
10976
11155
  cost: cost2.toFixed(4),
10977
11156
  bar: renderTinyBar(cachePct, 12),
10978
- pct: cachePct,
11157
+ pct: cachePct.toFixed(1),
10979
11158
  turns: summary.turns
10980
11159
  });
10981
11160
  })() : t("handlers.observability.statusCostCold", {
@@ -11114,11 +11293,48 @@ function estimateCost(userText, loop2) {
11114
11293
  ];
11115
11294
  return { info: lines.join("\n") };
11116
11295
  }
11296
+ var feedback = (_args, loop2, ctx) => {
11297
+ const themeName = resolveThemePreference(loadTheme(), process.env.REASONIX_THEME);
11298
+ const diagnostic = buildFeedbackDiagnostic({
11299
+ version: VERSION,
11300
+ latestVersion: ctx.latestVersion ?? void 0,
11301
+ platform: process.platform,
11302
+ osRelease: release(),
11303
+ termProgram: process.env.TERM_PROGRAM,
11304
+ term: process.env.TERM,
11305
+ colorTerm: process.env.COLORTERM,
11306
+ inWindowsTerminal: !!process.env.WT_SESSION,
11307
+ inTmux: !!process.env.TMUX,
11308
+ inSsh: !!process.env.SSH_TTY,
11309
+ wslDistro: process.env.WSL_DISTRO_NAME,
11310
+ cols: process.stdout.columns,
11311
+ rows: process.stdout.rows,
11312
+ nodeVersion: process.version,
11313
+ locale: getLanguage(),
11314
+ theme: themeName,
11315
+ model: loop2.model,
11316
+ reasoningEffort: loop2.reasoningEffort,
11317
+ editMode: ctx.editMode,
11318
+ planMode: ctx.planMode,
11319
+ mcpServerCount: ctx.mcpServers?.length ?? ctx.mcpSpecs?.length,
11320
+ sessionId: ctx.sessionId
11321
+ });
11322
+ writeClipboard(diagnostic);
11323
+ const url = buildFeedbackIssueUrl(diagnostic);
11324
+ const opened = openUrl(url);
11325
+ const lines = [
11326
+ opened.opened ? "\u25B8 issue page opened with the diagnostic block pre-filled. Just describe what you were doing and submit." : `\u25B8 couldn't open the browser (${opened.reason ?? "unknown"}). Diagnostic info is on your clipboard; open this URL manually: ${url}`,
11327
+ "",
11328
+ diagnostic
11329
+ ];
11330
+ return { info: lines.join("\n") };
11331
+ };
11117
11332
  var handlers11 = {
11118
11333
  context,
11119
11334
  status,
11120
11335
  compact,
11121
- cost
11336
+ cost,
11337
+ feedback
11122
11338
  };
11123
11339
 
11124
11340
  // src/cli/ui/slash/handlers/permissions.ts
@@ -11750,7 +11966,7 @@ function hydrateCardsFromMessages(messages) {
11750
11966
  }
11751
11967
 
11752
11968
  // src/cli/ui/useCompletionPickers.ts
11753
- import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useReducer as useReducer2, useRef as useRef5, useState as useState16 } from "react";
11969
+ import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo8, useReducer as useReducer2, useRef as useRef6, useState as useState16 } from "react";
11754
11970
  var SEARCH_DEBOUNCE_MS = 80;
11755
11971
  var SEARCH_FLUSH_MS = 50;
11756
11972
  var SEARCH_RESULT_CAP = 200;
@@ -11781,7 +11997,7 @@ function useCompletionPickers({
11781
11997
  });
11782
11998
  }, [slashMatches]);
11783
11999
  const [atSelected, setAtSelected] = useState16(0);
11784
- const recentFilesRef = useRef5([]);
12000
+ const recentFilesRef = useRef6([]);
11785
12001
  const recordRecentFile = useCallback8((p) => {
11786
12002
  const list2 = recentFilesRef.current;
11787
12003
  const i = list2.indexOf(p);
@@ -11954,10 +12170,10 @@ function toBrowseEntry(d) {
11954
12170
  }
11955
12171
  function useStreamingSearch(rootDir, filter, recentFilesRef) {
11956
12172
  const [, bumpRender] = useReducer2((x) => x + 1, 0);
11957
- const hitsRef = useRef5([]);
11958
- const scannedRef = useRef5(0);
11959
- const searchingRef = useRef5(false);
11960
- const rankedRef = useRef5([]);
12173
+ const hitsRef = useRef6([]);
12174
+ const scannedRef = useRef6(0);
12175
+ const searchingRef = useRef6(false);
12176
+ const rankedRef = useRef6([]);
11961
12177
  useEffect9(() => {
11962
12178
  if (filter === null) {
11963
12179
  hitsRef.current = [];
@@ -12029,13 +12245,13 @@ function rankSearchHits(hits, filter, recent) {
12029
12245
  }
12030
12246
 
12031
12247
  // src/cli/ui/useEditHistory.ts
12032
- import { useCallback as useCallback9, useRef as useRef6, useState as useState17 } from "react";
12248
+ import { useCallback as useCallback9, useRef as useRef7, useState as useState17 } from "react";
12033
12249
  function useEditHistory(codeMode) {
12034
- const editHistory = useRef6([]);
12035
- const nextHistoryId = useRef6(1);
12036
- const currentTurnEntry = useRef6(null);
12250
+ const editHistory = useRef7([]);
12251
+ const nextHistoryId = useRef7(1);
12252
+ const currentTurnEntry = useRef7(null);
12037
12253
  const [undoBanner, setUndoBanner] = useState17(null);
12038
- const undoTimeoutRef = useRef6(null);
12254
+ const undoTimeoutRef = useRef7(null);
12039
12255
  const recordEdit = useCallback9(
12040
12256
  (source, blocks, results, snaps) => {
12041
12257
  if (snaps.length === 0) return;
@@ -12332,7 +12548,7 @@ function useSessionInfo(loop2) {
12332
12548
  }
12333
12549
 
12334
12550
  // src/cli/ui/useSubagent.ts
12335
- import { useEffect as useEffect11, useRef as useRef7, useState as useState19 } from "react";
12551
+ import { useEffect as useEffect11, useRef as useRef8, useState as useState19 } from "react";
12336
12552
  function summariseInner(ev) {
12337
12553
  if (ev.role === "tool_start") {
12338
12554
  return {
@@ -12364,8 +12580,8 @@ function useSubagent({
12364
12580
  getWalletCurrency
12365
12581
  }) {
12366
12582
  const [activities, setActivities] = useState19([]);
12367
- const sinkRef = useRef7({ current: null });
12368
- const getWalletCurrencyRef = useRef7(getWalletCurrency);
12583
+ const sinkRef = useRef8({ current: null });
12584
+ const getWalletCurrencyRef = useRef8(getWalletCurrency);
12369
12585
  useEffect11(() => {
12370
12586
  getWalletCurrencyRef.current = getWalletCurrency;
12371
12587
  }, [getWalletCurrency]);
@@ -12512,7 +12728,7 @@ function AppInner({
12512
12728
  dumpStartupProfile();
12513
12729
  }, []);
12514
12730
  const [liveMcpServers, setLiveMcpServers] = useState20(() => mcpServers ?? []);
12515
- const abortedThisTurn = useRef8(false);
12731
+ const abortedThisTurn = useRef9(false);
12516
12732
  useEffect12(() => {
12517
12733
  busyRef.current = busy;
12518
12734
  }, [busy]);
@@ -12530,7 +12746,7 @@ function AppInner({
12530
12746
  stdout.write("\x1B[>4m");
12531
12747
  };
12532
12748
  }, [stdout]);
12533
- const walletCurrencyRef = useRef8(void 0);
12749
+ const walletCurrencyRef = useRef9(void 0);
12534
12750
  const { activities: subagentActivities, sinkRef: subagentSinkRef } = useSubagent({
12535
12751
  session,
12536
12752
  log,
@@ -12555,7 +12771,7 @@ function AppInner({
12555
12771
  hasUndoable,
12556
12772
  touchedPaths
12557
12773
  } = useEditHistory(codeMode);
12558
- const pendingEdits = useRef8([]);
12774
+ const pendingEdits = useRef9([]);
12559
12775
  const [pendingCount, setPendingCount] = useState20(0);
12560
12776
  const syncPendingCount = useCallback11(() => {
12561
12777
  setPendingCount(pendingEdits.current.length);
@@ -12566,22 +12782,22 @@ function AppInner({
12566
12782
  if (model2 === "deepseek-v4-pro") return "pro";
12567
12783
  return "auto";
12568
12784
  });
12569
- const editModeRef = useRef8(editMode);
12785
+ const editModeRef = useRef9(editMode);
12570
12786
  useEffect12(() => {
12571
12787
  editModeRef.current = editMode;
12572
12788
  if (codeMode) saveEditMode(editMode);
12573
12789
  }, [editMode, codeMode]);
12574
- const planModeRef = useRef8(false);
12575
- const currentRootDirRef = useRef8("");
12576
- const latestVersionRef = useRef8(null);
12790
+ const planModeRef = useRef9(false);
12791
+ const currentRootDirRef = useRef9("");
12792
+ const latestVersionRef = useRef9(null);
12577
12793
  const [pendingEditReview, setPendingEditReview] = useState20(null);
12578
12794
  const [walkthroughActive, setWalkthroughActive] = useState20(false);
12579
12795
  const [pendingTick, setPendingTick] = useState20(0);
12580
- const editReviewResolveRef = useRef8(null);
12581
- const turnEditPolicyRef = useRef8("ask");
12796
+ const editReviewResolveRef = useRef9(null);
12797
+ const turnEditPolicyRef = useRef9("ask");
12582
12798
  const [modeFlash, setModeFlash] = useState20(false);
12583
- const modeFlashTimeoutRef = useRef8(null);
12584
- const prevEditModeRef = useRef8(editMode);
12799
+ const modeFlashTimeoutRef = useRef9(null);
12800
+ const prevEditModeRef = useRef9(editMode);
12585
12801
  useEffect12(() => {
12586
12802
  if (prevEditModeRef.current === editMode) return;
12587
12803
  prevEditModeRef.current = editMode;
@@ -12613,23 +12829,23 @@ function AppInner({
12613
12829
  const [turnOnPro, setTurnOnPro] = useState20(false);
12614
12830
  const [queuedSubmit, setQueuedSubmit] = useState20(null);
12615
12831
  const { recallPrev, recallNext, pushHistory, resetCursor } = useInputRecall(setInput);
12616
- const assistantIterCounter = useRef8(0);
12617
- const atUrlCache = useRef8(/* @__PURE__ */ new Map());
12618
- const handleSubmitRef = useRef8(null);
12619
- const busyRef = useRef8(false);
12620
- const dashboardRef = useRef8(null);
12621
- const dashboardStartingRef = useRef8(null);
12622
- const eventSubscribersRef = useRef8(/* @__PURE__ */ new Set());
12623
- const activePickerResolverRef = useRef8(null);
12624
- const activePickerSnapshotRef = useRef8(null);
12625
- const activeViewerResolverRef = useRef8(null);
12626
- const activeViewerSnapshotRef = useRef8(null);
12832
+ const assistantIterCounter = useRef9(0);
12833
+ const atUrlCache = useRef9(/* @__PURE__ */ new Map());
12834
+ const handleSubmitRef = useRef9(null);
12835
+ const busyRef = useRef9(false);
12836
+ const dashboardRef = useRef9(null);
12837
+ const dashboardStartingRef = useRef9(null);
12838
+ const eventSubscribersRef = useRef9(/* @__PURE__ */ new Set());
12839
+ const activePickerResolverRef = useRef9(null);
12840
+ const activePickerSnapshotRef = useRef9(null);
12841
+ const activeViewerResolverRef = useRef9(null);
12842
+ const activeViewerSnapshotRef = useRef9(null);
12627
12843
  const [pendingReplayViewer, setPendingReplayViewer] = useState20(null);
12628
- const planStepsRef = useRef8(null);
12629
- const completedStepIdsRef = useRef8(/* @__PURE__ */ new Set());
12630
- const planBodyRef = useRef8(null);
12631
- const planSummaryRef = useRef8(null);
12632
- const toolStartedAtRef = useRef8(null);
12844
+ const planStepsRef = useRef9(null);
12845
+ const completedStepIdsRef = useRef9(/* @__PURE__ */ new Set());
12846
+ const planBodyRef = useRef9(null);
12847
+ const planSummaryRef = useRef9(null);
12848
+ const toolStartedAtRef = useRef9(null);
12633
12849
  const persistPlanState = useCallback11(() => {
12634
12850
  if (!session) return;
12635
12851
  const steps = planStepsRef.current;
@@ -12653,7 +12869,7 @@ function AppInner({
12653
12869
  lastPromptTokens: 0,
12654
12870
  lastTurnCostUsd: 0
12655
12871
  });
12656
- const transcriptRef = useRef8(null);
12872
+ const transcriptRef = useRef9(null);
12657
12873
  if (transcript && !transcriptRef.current) {
12658
12874
  transcriptRef.current = openTranscriptFile(transcript, {
12659
12875
  version: 1,
@@ -12662,8 +12878,8 @@ function AppInner({
12662
12878
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
12663
12879
  });
12664
12880
  }
12665
- const eventSinkRef = useRef8(null);
12666
- const eventizerRef = useRef8(null);
12881
+ const eventSinkRef = useRef9(null);
12882
+ const eventizerRef = useRef9(null);
12667
12883
  if (session && !eventSinkRef.current) {
12668
12884
  eventSinkRef.current = openEventSink(eventLogPath(session));
12669
12885
  eventizerRef.current = new Eventizer();
@@ -12675,7 +12891,7 @@ function AppInner({
12675
12891
  void eventSinkRef.current?.close();
12676
12892
  };
12677
12893
  }, []);
12678
- const loopRef = useRef8(null);
12894
+ const loopRef = useRef9(null);
12679
12895
  const loop2 = useMemo9(() => {
12680
12896
  if (loopRef.current) return loopRef.current;
12681
12897
  const client = new DeepSeekClient();
@@ -12781,8 +12997,8 @@ function AppInner({
12781
12997
  useEffect12(() => {
12782
12998
  latestVersionRef.current = latestVersion ?? null;
12783
12999
  }, [latestVersion]);
12784
- const balanceRef = useRef8(null);
12785
- const modelsRef = useRef8(null);
13000
+ const balanceRef = useRef9(null);
13001
+ const modelsRef = useRef9(null);
12786
13002
  useEffect12(() => {
12787
13003
  modelsRef.current = models;
12788
13004
  }, [models]);
@@ -12945,7 +13161,7 @@ function AppInner({
12945
13161
  if (progressSink.current) progressSink.current = null;
12946
13162
  };
12947
13163
  }, [progressSink]);
12948
- const sessionBannerShown = useRef8(false);
13164
+ const sessionBannerShown = useRef9(false);
12949
13165
  useEffect12(() => {
12950
13166
  if (sessionBannerShown.current) return;
12951
13167
  sessionBannerShown.current = true;
@@ -13217,7 +13433,7 @@ function AppInner({
13217
13433
  if (dashboardRef.current) return dashboardRef.current.url;
13218
13434
  if (dashboardStartingRef.current) return dashboardStartingRef.current;
13219
13435
  const startup = (async () => {
13220
- const { startDashboardServer } = await import("./server-MC4A4WAJ.js");
13436
+ const { startDashboardServer } = await import("./server-SMLVXIW4.js");
13221
13437
  const handle = await startDashboardServer({
13222
13438
  mode: "attached",
13223
13439
  configPath: defaultConfigPath(),
@@ -13652,6 +13868,7 @@ function AppInner({
13652
13868
  startDashboard,
13653
13869
  stopDashboard,
13654
13870
  getDashboardUrl,
13871
+ sessionId: session,
13655
13872
  jobs: codeMode?.jobs,
13656
13873
  postInfo: (text2) => log.pushInfo(text2),
13657
13874
  postDoctor: (checks) => log.showDoctor(checks),
@@ -14102,7 +14319,7 @@ function AppInner({
14102
14319
  },
14103
14320
  [pendingShell, codeMode, currentRootDir, log]
14104
14321
  );
14105
- const pendingGateIdRef = useRef8(null);
14322
+ const pendingGateIdRef = useRef9(null);
14106
14323
  useEffect12(() => {
14107
14324
  if (!busy && queuedSubmit !== null) {
14108
14325
  const text = queuedSubmit;
@@ -14118,7 +14335,8 @@ function AppInner({
14118
14335
  }
14119
14336
  if (choice === "refine" || choice === "approve") {
14120
14337
  if (pendingPlan) {
14121
- setStagedInput({ plan: pendingPlan, mode: choice });
14338
+ const questions = extractOpenQuestionsSection(pendingPlan) ?? void 0;
14339
+ setStagedInput({ plan: pendingPlan, mode: choice, questions });
14122
14340
  setPendingPlan(null);
14123
14341
  } else if (choice === "approve") {
14124
14342
  setStagedInput({ plan: "", mode: "approve" });
@@ -14133,13 +14351,14 @@ function AppInner({
14133
14351
  return;
14134
14352
  }
14135
14353
  if (pendingPlan) {
14136
- setStagedInput({ plan: pendingPlan, mode: "reject" });
14354
+ const questions = extractOpenQuestionsSection(pendingPlan) ?? void 0;
14355
+ setStagedInput({ plan: pendingPlan, mode: "reject", questions });
14137
14356
  setPendingPlan(null);
14138
14357
  }
14139
14358
  },
14140
14359
  [pendingPlan]
14141
14360
  );
14142
- const handlePlanConfirmRef = useRef8(handlePlanConfirm);
14361
+ const handlePlanConfirmRef = useRef9(handlePlanConfirm);
14143
14362
  useEffect12(() => {
14144
14363
  handlePlanConfirmRef.current = handlePlanConfirm;
14145
14364
  }, [handlePlanConfirm]);
@@ -14148,7 +14367,7 @@ function AppInner({
14148
14367
  []
14149
14368
  );
14150
14369
  const handleStagedInputSubmit = useCallback11(
14151
- async (feedback, override) => {
14370
+ async (feedback2, override) => {
14152
14371
  const staged = override ?? stagedInput;
14153
14372
  if (override) {
14154
14373
  setPendingPlan(null);
@@ -14156,7 +14375,7 @@ function AppInner({
14156
14375
  setStagedInput(null);
14157
14376
  }
14158
14377
  if (!staged) return;
14159
- const trimmed = feedback.trim();
14378
+ const trimmed = feedback2.trim();
14160
14379
  let synthetic;
14161
14380
  let marker;
14162
14381
  if (staged.mode === "approve") {
@@ -14216,8 +14435,8 @@ ${trimmed}
14216
14435
  Stay in plan mode \u2014 address the feedback (explore more if needed), then submit an improved submit_plan call. Don't propose a near-identical plan unless you explain why the feedback doesn't apply.`;
14217
14436
  marker = `\u25B8 refining \u2014 ${trimmed.length > 50 ? `${trimmed.slice(0, 50)}\u2026` : trimmed}`;
14218
14437
  } else {
14219
- synthetic = "The plan needs refinement, but the user didn't give specifics. Ask them one or two concrete questions \u2014 scope, approach, file boundaries, or the risks you flagged \u2014 then wait for their answer before submitting an updated plan.";
14220
- marker = "\u25B8 refining \u2014 asking the model to clarify";
14438
+ synthetic = "The plan needs refinement. The user saw your open questions / risks block and chose not to answer specifics. Pick the safest default for each open question, call those defaults out explicitly in the new plan, and submit the refined submit_plan. Do not re-ask \u2014 the user already saw the questions.";
14439
+ marker = "\u25B8 refining \u2014 using safe defaults";
14221
14440
  }
14222
14441
  }
14223
14442
  const gateId = pendingGateIdRef.current;
@@ -14233,7 +14452,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14233
14452
  },
14234
14453
  [stagedInput, togglePlanMode, persistPlanState, agentStore, log]
14235
14454
  );
14236
- const handleStagedInputSubmitRef = useRef8(handleStagedInputSubmit);
14455
+ const handleStagedInputSubmitRef = useRef9(handleStagedInputSubmit);
14237
14456
  useEffect12(() => {
14238
14457
  handleStagedInputSubmitRef.current = handleStagedInputSubmit;
14239
14458
  }, [handleStagedInputSubmit]);
@@ -14262,7 +14481,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14262
14481
  },
14263
14482
  [pendingChoice]
14264
14483
  );
14265
- const handleShellConfirmRef = useRef8(handleShellConfirm);
14484
+ const handleShellConfirmRef = useRef9(handleShellConfirm);
14266
14485
  useEffect12(() => {
14267
14486
  handleShellConfirmRef.current = handleShellConfirm;
14268
14487
  }, [handleShellConfirm]);
@@ -14325,11 +14544,11 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14325
14544
  }
14326
14545
  });
14327
14546
  }, []);
14328
- const pendingPlanRef = useRef8(null);
14547
+ const pendingPlanRef = useRef9(null);
14329
14548
  useEffect12(() => {
14330
14549
  pendingPlanRef.current = pendingPlan;
14331
14550
  }, [pendingPlan]);
14332
- const handleChoiceConfirmRef = useRef8(handleChoiceConfirm);
14551
+ const handleChoiceConfirmRef = useRef9(handleChoiceConfirm);
14333
14552
  useEffect12(() => {
14334
14553
  handleChoiceConfirmRef.current = handleChoiceConfirm;
14335
14554
  }, [handleChoiceConfirm]);
@@ -14382,7 +14601,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14382
14601
  },
14383
14602
  [pendingCheckpoint, codeMode, touchedPaths, log]
14384
14603
  );
14385
- const handleCheckpointConfirmRef = useRef8(handleCheckpointConfirm);
14604
+ const handleCheckpointConfirmRef = useRef9(handleCheckpointConfirm);
14386
14605
  useEffect12(() => {
14387
14606
  handleCheckpointConfirmRef.current = handleCheckpointConfirm;
14388
14607
  }, [handleCheckpointConfirm]);
@@ -14411,7 +14630,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14411
14630
  },
14412
14631
  [codeMode, touchedPaths, log]
14413
14632
  );
14414
- const handleAutoCheckpointContinueRef = useRef8(handleAutoCheckpointContinue);
14633
+ const handleAutoCheckpointContinueRef = useRef9(handleAutoCheckpointContinue);
14415
14634
  useEffect12(() => {
14416
14635
  handleAutoCheckpointContinueRef.current = handleAutoCheckpointContinue;
14417
14636
  }, [handleAutoCheckpointContinue]);
@@ -14420,12 +14639,12 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14420
14639
  []
14421
14640
  );
14422
14641
  const handleCheckpointReviseSubmit = useCallback11(
14423
- (feedback, snapOverride) => {
14642
+ (feedback2, snapOverride) => {
14424
14643
  const snap = snapOverride;
14425
14644
  setStagedCheckpointRevise(null);
14426
14645
  if (!snap) return;
14427
14646
  const label = snap.title ? `${snap.stepId} \xB7 ${snap.title}` : snap.stepId;
14428
- const trimmed = feedback.trim();
14647
+ const trimmed = feedback2.trim();
14429
14648
  const gid = pendingGateIdRef.current;
14430
14649
  if (gid !== null) {
14431
14650
  pauseGate.resolve(
@@ -14446,7 +14665,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14446
14665
  setStagedCheckpointRevise(null);
14447
14666
  if (snap) setPendingCheckpoint(snap);
14448
14667
  }, [stagedCheckpointRevise]);
14449
- const handleCheckpointReviseSubmitRef = useRef8(handleCheckpointReviseSubmit);
14668
+ const handleCheckpointReviseSubmitRef = useRef9(handleCheckpointReviseSubmit);
14450
14669
  useEffect12(() => {
14451
14670
  handleCheckpointReviseSubmitRef.current = handleCheckpointReviseSubmit;
14452
14671
  }, [handleCheckpointReviseSubmit]);
@@ -14497,7 +14716,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14497
14716
  },
14498
14717
  [pendingRevision, persistPlanState, agentStore, log]
14499
14718
  );
14500
- const handleReviseConfirmRef = useRef8(handleReviseConfirm);
14719
+ const handleReviseConfirmRef = useRef9(handleReviseConfirm);
14501
14720
  useEffect12(() => {
14502
14721
  handleReviseConfirmRef.current = handleReviseConfirm;
14503
14722
  }, [handleReviseConfirm]);
@@ -14525,6 +14744,7 @@ Stay in plan mode \u2014 address the feedback (explore more if needed), then sub
14525
14744
  PlanRefineInput,
14526
14745
  {
14527
14746
  mode: stagedInput.mode,
14747
+ questions: stagedInput.questions,
14528
14748
  onSubmit: handleStagedInputSubmit,
14529
14749
  onCancel: handleStagedInputCancel
14530
14750
  }
@@ -14815,7 +15035,7 @@ import React62, { useState as useState21 } from "react";
14815
15035
 
14816
15036
  // src/cli/ui/MaskedInput.tsx
14817
15037
  import { Text as Text53, useInput } from "ink";
14818
- import React61, { useRef as useRef9 } from "react";
15038
+ import React61, { useRef as useRef10 } from "react";
14819
15039
  function stripPasteMarkers(s) {
14820
15040
  return s.replace(/\u001b?\[20[01]~/g, "").replace(/\u001b/g, "");
14821
15041
  }
@@ -14826,7 +15046,7 @@ function MaskedInput({
14826
15046
  mask = "\u2022",
14827
15047
  placeholder = ""
14828
15048
  }) {
14829
- const valueRef = useRef9(value);
15049
+ const valueRef = useRef10(value);
14830
15050
  valueRef.current = value;
14831
15051
  useInput((input, key) => {
14832
15052
  if (key.return) {
@@ -15254,4 +15474,4 @@ async function chatCommand(opts) {
15254
15474
  export {
15255
15475
  chatCommand
15256
15476
  };
15257
- //# sourceMappingURL=chunk-5SAMVHA3.js.map
15477
+ //# sourceMappingURL=chunk-GPHBJWCV.js.map