@linghun/tui 0.1.1 → 0.1.2

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 (186) hide show
  1. package/dist/agent-completion-finalizer.js +3 -3
  2. package/dist/background-control-runtime.js +52 -52
  3. package/dist/cache-command-runtime.js +3 -3
  4. package/dist/capability-runtime.js +32 -32
  5. package/dist/{chunk-TJLC3QAS.js → chunk-36ZWUJQS.js} +1 -1
  6. package/dist/{chunk-624A7BBJ.js → chunk-3MRYQO7X.js} +4 -4
  7. package/dist/{chunk-QJTET7EZ.js → chunk-3PG7I3LA.js} +4 -4
  8. package/dist/{chunk-J7ZE2JKP.js → chunk-42ZZUF7P.js} +3 -3
  9. package/dist/{chunk-DTK5NBTV.js → chunk-4BFCUJX6.js} +95 -11
  10. package/dist/{chunk-YH6UIHNF.js → chunk-4QWCNMP6.js} +2 -2
  11. package/dist/{chunk-WKMBK5UP.js → chunk-4TO2LDMP.js} +1 -1
  12. package/dist/{chunk-5CXN4JLE.js → chunk-5IFNLTOF.js} +4 -4
  13. package/dist/{chunk-W3KHJNSH.js → chunk-6CHUZ2NF.js} +2 -2
  14. package/dist/{chunk-I3NTAIMF.js → chunk-6DBBXNEG.js} +3 -3
  15. package/dist/{chunk-GDQQNPBP.js → chunk-6GXIGN5W.js} +1 -1
  16. package/dist/{chunk-QLRTQHTR.js → chunk-6JGRNES6.js} +2 -2
  17. package/dist/{chunk-WOBNOBB5.js → chunk-7BHMBWG2.js} +3 -3
  18. package/dist/{chunk-KO64OFSG.js → chunk-7C6T7RKJ.js} +1 -1
  19. package/dist/{chunk-RFSSKGCE.js → chunk-7R4YXN7Z.js} +176 -37
  20. package/dist/{chunk-LDABZV5V.js → chunk-7RZE45OT.js} +1 -1
  21. package/dist/{chunk-MLUIOBKL.js → chunk-7ZMDQZ22.js} +4 -4
  22. package/dist/{chunk-X7A22JHP.js → chunk-A4H3UTJZ.js} +1 -1
  23. package/dist/{chunk-QG2FJ3NR.js → chunk-AGI6GFFL.js} +3 -3
  24. package/dist/{chunk-D3UTL2QX.js → chunk-ATY7WBIT.js} +1 -1
  25. package/dist/{chunk-ZOSK2UEU.js → chunk-BBK5BA5C.js} +99 -117
  26. package/dist/{chunk-SRZIA6B4.js → chunk-BNC4F63N.js} +1 -1
  27. package/dist/{chunk-4E56DWEZ.js → chunk-CJRJR7TP.js} +4 -4
  28. package/dist/{chunk-SILJJAK2.js → chunk-DIDRFIIW.js} +1 -1
  29. package/dist/{chunk-HIIYRATQ.js → chunk-EKYXI6C7.js} +11 -7
  30. package/dist/{chunk-Y5ZV47XC.js → chunk-FGGY5KNM.js} +7 -7
  31. package/dist/{chunk-APJIC2O5.js → chunk-GTIZNO5O.js} +84 -0
  32. package/dist/{chunk-UOHZQIVL.js → chunk-GXFYUZAM.js} +1 -1
  33. package/dist/{chunk-DDXS2RDZ.js → chunk-HGCTHBUY.js} +1 -1
  34. package/dist/{chunk-QTDGRZMZ.js → chunk-HJOC5WUV.js} +1 -1
  35. package/dist/{chunk-DYDTLRHB.js → chunk-HPIHFENG.js} +2 -2
  36. package/dist/{chunk-SYBNJZEL.js → chunk-HPMBSOQ4.js} +1 -1
  37. package/dist/{chunk-LIPZJNXS.js → chunk-HPQ2IHOW.js} +4 -4
  38. package/dist/{chunk-KOULRCYJ.js → chunk-HZ5XNKWS.js} +1 -1
  39. package/dist/{chunk-4K6UB524.js → chunk-IPZZGDUU.js} +1 -1
  40. package/dist/{chunk-6CI6TKLN.js → chunk-JAVRQ3LM.js} +1 -1
  41. package/dist/{chunk-VCSRBS47.js → chunk-JLAJZPOC.js} +1 -1
  42. package/dist/{chunk-UN53MBAR.js → chunk-JY3LI63F.js} +2 -2
  43. package/dist/{chunk-RMLTVKOY.js → chunk-L4YVE3RG.js} +2 -2
  44. package/dist/{chunk-P277M7Z5.js → chunk-LBC75QAB.js} +1 -1
  45. package/dist/{chunk-F6TVBCZV.js → chunk-LWW2IAFC.js} +1 -1
  46. package/dist/{chunk-L2GU3PWU.js → chunk-NK4NMYF5.js} +49 -7
  47. package/dist/{chunk-MXPBYB54.js → chunk-O2U4XQVM.js} +2 -2
  48. package/dist/{chunk-LQTVYUT3.js → chunk-OJTMM5CV.js} +2 -2
  49. package/dist/{chunk-HW2TBXVK.js → chunk-OPVRII63.js} +1 -1
  50. package/dist/{chunk-CDVYF7RU.js → chunk-OSFBVVEP.js} +4 -4
  51. package/dist/{chunk-F43AMWLZ.js → chunk-PDTJVJVD.js} +1 -1
  52. package/dist/{chunk-UDQT5CWK.js → chunk-PI6T2AGS.js} +1 -1
  53. package/dist/{chunk-AZU7HXIT.js → chunk-PPUOHBAK.js} +17 -17
  54. package/dist/{chunk-33E6RDCY.js → chunk-QD4SCW4A.js} +229 -192
  55. package/dist/{chunk-SOPYWTFV.js → chunk-RRUI3VWQ.js} +1 -1
  56. package/dist/{chunk-IN42UISW.js → chunk-SRJ4XWOR.js} +10 -5
  57. package/dist/{chunk-6RJVTUWI.js → chunk-T6UOCF5D.js} +5 -1
  58. package/dist/{chunk-VTQL23UM.js → chunk-TVNWAEJR.js} +1 -1
  59. package/dist/chunk-TY4KIVA6.js +50 -0
  60. package/dist/{chunk-UT2TYK2A.js → chunk-TYTVAFGB.js} +1 -1
  61. package/dist/{chunk-OMZYPQVA.js → chunk-UGYFQF6M.js} +1 -1
  62. package/dist/{chunk-VAGL7CNR.js → chunk-UIKN3CDF.js} +4 -4
  63. package/dist/{chunk-JGDIO2NF.js → chunk-UO3KYTBU.js} +1 -1
  64. package/dist/{chunk-KI7C6ZOD.js → chunk-VIJ7GDKI.js} +1 -1
  65. package/dist/{chunk-NKFKOEYX.js → chunk-WCMHJ6SS.js} +1 -1
  66. package/dist/{chunk-EORRZP3F.js → chunk-WX2OTJXL.js} +1 -1
  67. package/dist/{chunk-BOV4K7FP.js → chunk-WXTHKLNH.js} +9 -1
  68. package/dist/{chunk-CRQORMFF.js → chunk-X37FSYAX.js} +1 -1
  69. package/dist/{chunk-XWRHWM4H.js → chunk-X7E34LKV.js} +11 -11
  70. package/dist/chunk-X7HMDZZQ.js +85 -0
  71. package/dist/{chunk-CD54BQJ5.js → chunk-YDTJ7UBG.js} +4 -4
  72. package/dist/{chunk-K56D3X7S.js → chunk-YKOXJQGX.js} +34 -2
  73. package/dist/{chunk-7TYK55JT.js → chunk-YLOJWSHB.js} +5 -5
  74. package/dist/{chunk-O6MKVGVK.js → chunk-YMEMN5FG.js} +1 -1
  75. package/dist/chunk-YQNK7HK3.js +87 -0
  76. package/dist/{chunk-KJVHLTQR.js → chunk-Z265MCGC.js} +12 -8
  77. package/dist/{chunk-3BPKJMIV.js → chunk-ZF36LULR.js} +4 -4
  78. package/dist/{chunk-JJQETFCR.js → chunk-ZJDPYOTK.js} +4 -4
  79. package/dist/{chunk-RM5QMOFY.js → chunk-ZKPQ4KLK.js} +1 -1
  80. package/dist/command-panel-runtime.js +31 -31
  81. package/dist/compact-cache-command-runtime.js +52 -52
  82. package/dist/compact-preflight-runtime.js +20 -20
  83. package/dist/connector-runtime.js +33 -33
  84. package/dist/deep-compact-runtime.js +6 -6
  85. package/dist/deferred-tools-catalog.js +5 -5
  86. package/dist/details-status-runtime.js +31 -31
  87. package/dist/evidence-runtime.d.ts.map +1 -1
  88. package/dist/evidence-runtime.js +11 -11
  89. package/dist/extension-command-runtime.js +6 -6
  90. package/dist/extension-slash-runtime.js +32 -32
  91. package/dist/failure-learning-command-runtime.js +33 -33
  92. package/dist/failure-learning-presenter.js +4 -4
  93. package/dist/failure-learning-runtime.js +3 -3
  94. package/dist/final-answer-gate.js +2 -2
  95. package/dist/git-command-runtime.js +32 -32
  96. package/dist/handoff-session-runtime.js +8 -8
  97. package/dist/index-result-presenter.js +5 -5
  98. package/dist/index-runtime.js +5 -5
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +65 -59
  101. package/dist/job-agent-command-runtime.js +31 -31
  102. package/dist/job-runner-presenter.js +3 -3
  103. package/dist/job-runtime.js +8 -8
  104. package/dist/mcp-index-command-runtime.js +4 -4
  105. package/dist/mcp-index-runtime.js +36 -36
  106. package/dist/mcp-sse-runtime.js +3 -3
  107. package/dist/mcp-stdio-runtime.js +3 -3
  108. package/dist/memory-command-runtime.js +33 -33
  109. package/dist/memory-extraction-runtime.js +3 -3
  110. package/dist/memory-rules-runtime.js +3 -3
  111. package/dist/model-command-runtime.js +32 -32
  112. package/dist/model-loop-runtime.d.ts +1 -1
  113. package/dist/model-loop-runtime.d.ts.map +1 -1
  114. package/dist/model-loop-runtime.js +1 -1
  115. package/dist/model-prompt-runtime.js +10 -10
  116. package/dist/model-stream-runtime.js +52 -52
  117. package/dist/model-tool-runtime.d.ts +1 -0
  118. package/dist/model-tool-runtime.d.ts.map +1 -1
  119. package/dist/model-tool-runtime.js +54 -52
  120. package/dist/pending-details-presenter.js +3 -3
  121. package/dist/permission-approval-runtime.js +52 -52
  122. package/dist/permission-continuation-runtime.d.ts.map +1 -1
  123. package/dist/permission-continuation-runtime.js +4 -4
  124. package/dist/process-command-runtime.js +3 -3
  125. package/dist/provider-loop-runtime.js +3 -3
  126. package/dist/remote-command-runtime.js +32 -32
  127. package/dist/runner-runtime.js +7 -7
  128. package/dist/runtime-status-presenter.js +3 -3
  129. package/dist/runtime-status-snapshot.js +4 -4
  130. package/dist/shell/components/AgentProgressTree.js +2 -2
  131. package/dist/shell/components/BackgroundTaskOverlay.js +2 -2
  132. package/dist/shell/components/BtwPanel.js +2 -2
  133. package/dist/shell/components/CommandPanel.js +2 -2
  134. package/dist/shell/components/Composer.d.ts +16 -2
  135. package/dist/shell/components/Composer.d.ts.map +1 -1
  136. package/dist/shell/components/Composer.js +9 -7
  137. package/dist/shell/components/ConfigPanel.js +2 -2
  138. package/dist/shell/components/HelpPanel.js +2 -2
  139. package/dist/shell/components/HistorySearchPanel.js +2 -2
  140. package/dist/shell/components/MessageMarkdown.d.ts +23 -0
  141. package/dist/shell/components/MessageMarkdown.d.ts.map +1 -1
  142. package/dist/shell/components/MessageMarkdown.js +5 -3
  143. package/dist/shell/components/MouseInputRouter.js +5 -80
  144. package/dist/shell/components/OutputLine.d.ts.map +1 -1
  145. package/dist/shell/components/OutputLine.js +5 -3
  146. package/dist/shell/components/ProductBlock.d.ts.map +1 -1
  147. package/dist/shell/components/ProductBlock.js +4 -4
  148. package/dist/shell/components/ScrollViewport.js +3 -82
  149. package/dist/shell/components/SessionsPanel.js +2 -2
  150. package/dist/shell/components/ShellApp.d.ts.map +1 -1
  151. package/dist/shell/components/ShellApp.js +28 -23
  152. package/dist/shell/components/SlashSuggestions.js +2 -2
  153. package/dist/shell/components/StatusFooter.js +2 -2
  154. package/dist/shell/components/StatusTray.d.ts.map +1 -1
  155. package/dist/shell/components/StatusTray.js +2 -1
  156. package/dist/shell/components/StructuredDiff.js +2 -2
  157. package/dist/shell/components/TaskListView.js +2 -2
  158. package/dist/shell/components/TaskSuggestionBar.js +2 -2
  159. package/dist/shell/components/WorkflowProgressView.js +2 -2
  160. package/dist/shell/components/useAnchoredCursor.d.ts +6 -9
  161. package/dist/shell/components/useAnchoredCursor.d.ts.map +1 -1
  162. package/dist/shell/components/useAnchoredCursor.js +1 -1
  163. package/dist/shell/ink-renderer.d.ts.map +1 -1
  164. package/dist/shell/ink-renderer.js +28 -23
  165. package/dist/shell/models/transcript-selection-state.js +2 -2
  166. package/dist/shell/plain-renderer.d.ts.map +1 -1
  167. package/dist/shell/plain-renderer.js +2 -2
  168. package/dist/shell/text-utils.d.ts +16 -0
  169. package/dist/shell/text-utils.d.ts.map +1 -1
  170. package/dist/shell/text-utils.js +3 -1
  171. package/dist/shell/view-model.js +14 -14
  172. package/dist/slash-command-runtime.js +52 -52
  173. package/dist/slash-dispatch.js +4 -4
  174. package/dist/startup-runtime.js +2 -2
  175. package/dist/tool-output-presenter.d.ts.map +1 -1
  176. package/dist/tool-output-presenter.js +1 -1
  177. package/dist/tui-agent-job-runtime.js +10 -10
  178. package/dist/tui-details-runtime.js +9 -9
  179. package/dist/tui-memory-runtime.js +5 -5
  180. package/dist/tui-output-surface.js +15 -15
  181. package/dist/tui-permission-runtime.js +5 -5
  182. package/dist/tui-state-runtime.js +4 -4
  183. package/dist/verification-command-runtime.js +11 -11
  184. package/dist/workflow-command-runtime.js +31 -31
  185. package/package.json +4 -4
  186. package/dist/chunk-GW5YDCRZ.js +0 -42
@@ -6,10 +6,10 @@ import {
6
6
  } from "./chunk-JBLVBO3U.js";
7
7
  import {
8
8
  useAnchoredCursor
9
- } from "./chunk-GW5YDCRZ.js";
9
+ } from "./chunk-TY4KIVA6.js";
10
10
  import {
11
11
  SlashSuggestions
12
- } from "./chunk-HW2TBXVK.js";
12
+ } from "./chunk-OPVRII63.js";
13
13
  import {
14
14
  resolveTerminalInteractionModes
15
15
  } from "./chunk-F46N43MG.js";
@@ -32,21 +32,20 @@ import {
32
32
  formatUnknownSlashCommand,
33
33
  getCoreSlashCandidates,
34
34
  getSlashPrefixCandidates
35
- } from "./chunk-4K6UB524.js";
35
+ } from "./chunk-IPZZGDUU.js";
36
36
  import {
37
37
  resolveKeybinding
38
38
  } from "./chunk-6SMM5CMP.js";
39
39
  import {
40
40
  charWidth,
41
- composerMaxWidth,
42
- fitText,
43
- taskComposerMaxWidth
44
- } from "./chunk-APJIC2O5.js";
41
+ computeWrappedInputState,
42
+ fitText
43
+ } from "./chunk-GTIZNO5O.js";
45
44
 
46
45
  // src/shell/components/Composer.tsx
47
46
  import { Box, Text, useInput } from "@linghun/ink-runtime";
48
47
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
49
- import { jsx, jsxs } from "react/jsx-runtime";
48
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
50
49
  function createEditBuffer(text = "") {
51
50
  return { chars: Array.from(text), cursor: Array.from(text).length };
52
51
  }
@@ -201,7 +200,7 @@ function buildVisualLines(buf, maxWidth) {
201
200
  const isFirstRawLine = rawIndex === 0;
202
201
  let startChar = 0;
203
202
  while (startChar < chars.length || chars.length === 0 && startChar === 0) {
204
- const prompt = isFirstRawLine && startChar === 0 ? PROMPT_MARKER : PROMPT_MARKER_CONTINUATION;
203
+ const prompt = isFirstRawLine && startChar === 0 ? PROMPT_MARKER : "";
205
204
  const promptWidth = displayWidthOf(prompt);
206
205
  const budget = Math.max(4, composerWidth - promptWidth);
207
206
  let width = 0;
@@ -236,6 +235,10 @@ function isWordBoundary(ch) {
236
235
  function sanitizeComposerInput(value) {
237
236
  return sanitizeTerminalText(value);
238
237
  }
238
+ function sanitizeComposerPasteInput(value) {
239
+ const sanitized = sanitizeComposerInput(value);
240
+ return sanitized.replace(/[ \t\f\v]+\n/g, "\n").replace(/\n[ \t\f\v]+/g, "\n").replace(/[ \t\f\v]{2,}/g, " ").replace(/[ \t\f\v]+\n[ \t\f\v]*/g, "\n").replace(/[ \t\f\v]+$/g, "");
241
+ }
239
242
  var MAX_HISTORY = 100;
240
243
  function createInputHistory() {
241
244
  return { entries: [], position: -1, draft: "" };
@@ -323,7 +326,6 @@ function isMultilineEnterSequence2(input) {
323
326
  }
324
327
  var COMPOSER_MAX_VISIBLE_LINES = 5;
325
328
  var PROMPT_MARKER = "\u203A ";
326
- var PROMPT_MARKER_CONTINUATION = " ".repeat(displayWidthOf(PROMPT_MARKER));
327
329
  var PERMISSION_ACTION_ORDER = [
328
330
  "allow_once",
329
331
  "allow_always_tool",
@@ -335,13 +337,15 @@ var OWNER_PASTE_THRESHOLD = PASTE_THRESHOLD;
335
337
  var PASTE_COMPLETION_TIMEOUT_MS = 100;
336
338
  var DOUBLE_PRESS_WINDOW_MS = 1e3;
337
339
  var HINT_NOTICE_DECAY_MS = 1500;
338
- function Composer({ view, onInput, capability }) {
340
+ var INLINE_CURSOR_BLINK_MS = 530;
341
+ function Composer({ view, onInput, capability, layout }) {
339
342
  const [buffer, setBuffer] = useState(createEditBuffer());
340
343
  const bufferRef = useRef(buffer);
341
344
  const [slashSelection, setSlashSelection] = useState(0);
342
345
  const [slashHidden, setSlashHidden] = useState(false);
343
346
  const [permissionFocus, setPermissionFocus] = useState("allow_once");
344
347
  const [hintNotice, setHintNotice] = useState(void 0);
348
+ const [cursorBlinkOn, setCursorBlinkOn] = useState(true);
345
349
  const historyRef = useRef(createInputHistory());
346
350
  const pasteChunksRef = useRef([]);
347
351
  const pasteTimerRef = useRef(null);
@@ -353,7 +357,17 @@ function Composer({ view, onInput, capability }) {
353
357
  const chordBufferRef = useRef([]);
354
358
  const undoRingRef = useRef(createUndoRing());
355
359
  const stashRef = useRef(createPromptStash());
356
- const maxWidth = view.viewMode === "task" || view.viewMode === "pending" ? taskComposerMaxWidth(view.width) : composerMaxWidth(view.width);
360
+ const composerLayout = useMemo(
361
+ () => layout ?? {
362
+ width: Math.max(40, view.width - 6),
363
+ paddingLeft: 2,
364
+ paddingRight: 2,
365
+ prefixWidth: displayWidthOf(PROMPT_MARKER),
366
+ minContentWidth: 4
367
+ },
368
+ [layout, view.width]
369
+ );
370
+ const maxWidth = composerLayout.width;
357
371
  const noColor = view.themeMode === "no-color";
358
372
  const theme = useMemo(() => createShellTheme(noColor), [noColor]);
359
373
  const anchorRef = useRef(null);
@@ -458,7 +472,7 @@ function Composer({ view, onInput, capability }) {
458
472
  }
459
473
  pastePendingRef.current = false;
460
474
  if (chunks.length === 0) return;
461
- const joined = sanitizeComposerInput(chunks.join(""));
475
+ const joined = sanitizeComposerPasteInput(chunks.join(""));
462
476
  if (!joined) return;
463
477
  const next = bufferInsert(bufferRef.current, joined);
464
478
  bufferRef.current = next;
@@ -488,6 +502,14 @@ function Composer({ view, onInput, capability }) {
488
502
  if (hintTimerRef.current) clearTimeout(hintTimerRef.current);
489
503
  };
490
504
  }, []);
505
+ useEffect(() => {
506
+ if (permissionActive) return;
507
+ setCursorBlinkOn(true);
508
+ const timer = setInterval(() => {
509
+ setCursorBlinkOn((current) => !current);
510
+ }, INLINE_CURSOR_BLINK_MS);
511
+ return () => clearInterval(timer);
512
+ }, [permissionActive]);
491
513
  useInput(
492
514
  (input, key) => {
493
515
  if (input === "\x1B[I" || input === "\x1B[O" || input === "[I" || input === "[O") {
@@ -1137,33 +1159,18 @@ function Composer({ view, onInput, capability }) {
1137
1159
  { isActive: true }
1138
1160
  );
1139
1161
  const placeholderText = view.permission || view.composer.setupActive ? view.composer.placeholder : view.viewMode === "task" || view.viewMode === "pending" ? view.composer.taskPlaceholder : view.composer.placeholder;
1140
- const composerInnerWidth = Math.max(8, maxWidth - 4);
1141
- const { lines, truncatedAbove, truncatedBelow, cursorCol, cursorRow } = useMemo(
1162
+ const { visualLines, cursorCol, cursorRow } = useMemo(
1142
1163
  () => formatComposerRenderLines({
1143
1164
  buffer,
1144
1165
  placeholder: placeholderText,
1145
1166
  masking: view.composer.masking,
1146
1167
  noColor,
1147
- maxWidth: composerInnerWidth
1168
+ layout: composerLayout
1148
1169
  }),
1149
- [buffer, placeholderText, view.composer.masking, noColor, composerInnerWidth]
1170
+ [buffer, placeholderText, view.composer.masking, noColor, composerLayout]
1150
1171
  );
1151
- void truncatedAbove;
1152
- void truncatedBelow;
1153
1172
  const showSuggestions = !permissionActive && slashCandidates.length > 0 && slashSelection >= 0 && !slashHidden;
1154
- const declaredRow = composerCursorAnchorRowOffset({
1155
- textAnchorRowBase: view.viewMode === "home" ? 0 : 1,
1156
- permissionActive,
1157
- permissionActionCount: permissionActions.length,
1158
- showSuggestions,
1159
- slashCandidateCount: slashCandidates.length,
1160
- cursorRow
1161
- });
1162
- useAnchoredCursor(
1163
- permissionActive ? null : { row: declaredRow, col: cursorCol },
1164
- anchorRef,
1165
- capability
1166
- );
1173
+ useAnchoredCursor(null, anchorRef, capability);
1167
1174
  const placeholderColor = noColor ? void 0 : "gray";
1168
1175
  const color = text ? void 0 : placeholderColor;
1169
1176
  const ghostSuffix = useMemo(() => {
@@ -1191,7 +1198,7 @@ function Composer({ view, onInput, capability }) {
1191
1198
  actions: permissionActions,
1192
1199
  focused: permissionFocus,
1193
1200
  theme,
1194
- width: composerInnerWidth,
1201
+ width: composerContentWidth(composerLayout),
1195
1202
  language: view.language
1196
1203
  }
1197
1204
  ) : null,
@@ -1202,29 +1209,21 @@ function Composer({ view, onInput, capability }) {
1202
1209
  selectedIndex: slashSelectionClamped,
1203
1210
  theme,
1204
1211
  language: view.language,
1205
- width: composerInnerWidth,
1212
+ width: composerContentWidth(composerLayout),
1206
1213
  hint: view.language === "en-US" ? "Tab accept \xB7 \u2191\u2193 pick \xB7 Esc hide \xB7 Enter submit" : "Tab \u9009\u4E2D \xB7 \u2191\u2193 \u5207\u6362 \xB7 Esc \u9690\u85CF \xB7 Enter \u63D0\u4EA4"
1207
1214
  }
1208
1215
  ) : null,
1209
- /* @__PURE__ */ jsxs(Box, { width: "100%", flexDirection: "row", alignItems: "flex-start", children: [
1210
- /* @__PURE__ */ jsx(Text, { color: theme.muted, dimColor: !text, children: PROMPT_MARKER }),
1211
- /* @__PURE__ */ jsx(
1212
- Box,
1213
- {
1214
- ref: anchorRef,
1215
- flexDirection: "column",
1216
- width: Math.max(4, composerInnerWidth - displayWidthOf(PROMPT_MARKER)),
1217
- children: lines.map((line, index) => {
1218
- return /* @__PURE__ */ jsxs(Text, { color, bold: Boolean(text), children: [
1219
- sliceWidth(line, Math.max(4, composerInnerWidth - displayWidthOf(PROMPT_MARKER))),
1220
- index === lines.length - 1 && ghostSuffix ? /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: ghostSuffix }) : null
1221
- ] }, `${index}-${line}`);
1222
- })
1223
- }
1224
- )
1225
- ] }),
1226
- showUnknownHint ? /* @__PURE__ */ jsx(Text, { color: theme.muted, children: fitText(formatUnknownSlashCommand(text, view.language), composerInnerWidth) }) : null,
1227
- hintNotice ? /* @__PURE__ */ jsx(Text, { color: theme.muted, children: fitText(hintNotice, composerInnerWidth) }) : null
1216
+ /* @__PURE__ */ jsx(Box, { ref: anchorRef, width: "100%", flexDirection: "column", children: visualLines.map((line, index) => {
1217
+ const clippedLine = line.text;
1218
+ const showInlineCursor = !permissionActive && index === cursorRow;
1219
+ return /* @__PURE__ */ jsxs(Text, { color, bold: Boolean(text), children: [
1220
+ /* @__PURE__ */ jsx(Text, { color: theme.muted, dimColor: !text, children: line.prefix }),
1221
+ showInlineCursor ? renderInlineComposerCursor(clippedLine, cursorCol, cursorBlinkOn) : clippedLine,
1222
+ index === visualLines.length - 1 && ghostSuffix ? /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: ghostSuffix }) : null
1223
+ ] }, `${index}-${line.prefix}-${line.text}`);
1224
+ }) }),
1225
+ showUnknownHint ? /* @__PURE__ */ jsx(Text, { color: theme.muted, children: fitText(formatUnknownSlashCommand(text, view.language), composerContentWidth(composerLayout)) }) : null,
1226
+ hintNotice ? /* @__PURE__ */ jsx(Text, { color: theme.muted, children: fitText(hintNotice, composerContentWidth(composerLayout)) }) : null
1228
1227
  ]
1229
1228
  }
1230
1229
  );
@@ -1324,7 +1323,8 @@ function formatComposerRenderLines({
1324
1323
  placeholder,
1325
1324
  masking,
1326
1325
  noColor,
1327
- maxWidth
1326
+ maxWidth,
1327
+ layout
1328
1328
  }) {
1329
1329
  void noColor;
1330
1330
  const text = bufferToString(buffer);
@@ -1332,85 +1332,69 @@ function formatComposerRenderLines({
1332
1332
  if (!displayText) {
1333
1333
  return {
1334
1334
  lines: [placeholder],
1335
+ visualLines: [{ prefix: PROMPT_MARKER, text: placeholder }],
1335
1336
  truncatedAbove: 0,
1336
1337
  truncatedBelow: 0,
1337
1338
  cursorCol: 0,
1338
1339
  cursorRow: 0
1339
1340
  };
1340
1341
  }
1341
- const rawLines = displayText.split("\n");
1342
- const { row: cursorLineIndex, col: cursorCharCol } = getCursorLinePosition(buffer);
1343
- const composerWidth = Math.max(8, maxWidth ?? 80);
1344
- const softLines = [];
1345
- let cursorSoftIndex = 0;
1346
- let cursorOutCol = 0;
1347
- for (let rawIndex = 0; rawIndex < rawLines.length; rawIndex++) {
1348
- const rawLine = rawLines[rawIndex] ?? "";
1349
- const chars = Array.from(masking ? "*".repeat(Array.from(rawLine).length) : rawLine);
1350
- let startChar = 0;
1351
- while (startChar < chars.length || chars.length === 0 && startChar === 0) {
1352
- const budget = Math.max(4, composerWidth - displayWidthOf(PROMPT_MARKER));
1353
- let width = 0;
1354
- let endChar = startChar;
1355
- while (endChar < chars.length) {
1356
- const next = charWidth(chars[endChar] ?? "");
1357
- if (width > 0 && width + next > budget) break;
1358
- width += next;
1359
- endChar++;
1360
- }
1361
- if (endChar === startChar && chars.length > 0) endChar++;
1362
- const text2 = chars.slice(startChar, endChar).join("");
1363
- const softIndex = softLines.length;
1364
- softLines.push({ text: text2, rawLineIndex: rawIndex, startChar, endChar });
1365
- if (rawIndex === cursorLineIndex && cursorCharCol >= startChar && cursorCharCol <= endChar) {
1366
- cursorSoftIndex = softIndex;
1367
- let cursorWidth = 0;
1368
- for (let i = startChar; i < cursorCharCol && i < chars.length; i++) {
1369
- cursorWidth += charWidth(chars[i] ?? "");
1370
- }
1371
- cursorOutCol = cursorWidth;
1372
- }
1373
- if (chars.length === 0) break;
1374
- startChar = endChar;
1375
- }
1376
- }
1377
- const totalLines = softLines.length;
1342
+ const wrapped = computeWrappedInputState({
1343
+ text: displayText,
1344
+ cursorOffset: buffer.cursor,
1345
+ width: layout?.width ?? maxWidth ?? 80,
1346
+ prefixWidth: layout?.prefixWidth ?? displayWidthOf(PROMPT_MARKER),
1347
+ paddingLeft: layout?.paddingLeft ?? 4,
1348
+ paddingRight: layout?.paddingRight ?? 0,
1349
+ minContentWidth: layout?.minContentWidth ?? 4
1350
+ });
1351
+ const totalLines = wrapped.lines.length;
1378
1352
  let startLine = 0;
1379
1353
  let endLineExclusive = totalLines;
1380
1354
  if (totalLines > COMPOSER_MAX_VISIBLE_LINES) {
1381
1355
  const half = Math.floor(COMPOSER_MAX_VISIBLE_LINES / 2);
1382
- startLine = Math.max(0, cursorSoftIndex - half);
1356
+ startLine = Math.max(0, wrapped.cursorRow - half);
1383
1357
  endLineExclusive = startLine + COMPOSER_MAX_VISIBLE_LINES;
1384
1358
  if (endLineExclusive > totalLines) {
1385
1359
  endLineExclusive = totalLines;
1386
1360
  startLine = Math.max(0, endLineExclusive - COMPOSER_MAX_VISIBLE_LINES);
1387
1361
  }
1388
1362
  }
1389
- const renderedLines = softLines.slice(startLine, endLineExclusive).map((line) => line.text);
1363
+ const renderedLines = wrapped.lines.slice(startLine, endLineExclusive);
1390
1364
  const truncatedAbove = startLine;
1391
1365
  const truncatedBelow = totalLines - endLineExclusive;
1392
- const cursorVisibleRow = Math.max(
1393
- 0,
1394
- Math.min(cursorSoftIndex - startLine, renderedLines.length - 1)
1395
- );
1366
+ const cursorVisibleRow = Math.max(0, Math.min(wrapped.cursorRow - startLine, renderedLines.length - 1));
1396
1367
  return {
1397
1368
  lines: renderedLines,
1369
+ visualLines: renderedLines.map((line, index) => ({
1370
+ prefix: startLine + index === 0 ? PROMPT_MARKER : "",
1371
+ text: line
1372
+ })),
1398
1373
  truncatedAbove,
1399
1374
  truncatedBelow,
1400
- cursorCol: maxWidth && cursorOutCol > maxWidth ? maxWidth : cursorOutCol,
1375
+ cursorCol: Math.min(wrapped.cursorCol, Math.max(4, wrapped.contentWidth)),
1401
1376
  cursorRow: cursorVisibleRow
1402
1377
  };
1403
1378
  }
1404
- function sliceWidth(value, max) {
1405
- let width = 0;
1406
- let result = "";
1407
- for (const ch of value) {
1408
- const next = width + charWidth(ch);
1409
- if (next > max) break;
1410
- result += ch;
1411
- width = next;
1412
- }
1413
- return result;
1379
+ function composerContentWidth(layout) {
1380
+ return computeWrappedInputState({
1381
+ text: "",
1382
+ cursorOffset: 0,
1383
+ width: layout.width,
1384
+ prefixWidth: layout.prefixWidth,
1385
+ paddingLeft: layout.paddingLeft,
1386
+ paddingRight: layout.paddingRight,
1387
+ minContentWidth: layout.minContentWidth
1388
+ }).contentWidth;
1389
+ }
1390
+ function renderInlineComposerCursor(line, col, visible) {
1391
+ const { before, cursorChar, after } = splitLineAtDisplayCol(line, col);
1392
+ const cursorCell = cursorChar || " ";
1393
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1394
+ before,
1395
+ visible ? /* @__PURE__ */ jsx(Text, { inverse: true, children: cursorCell }) : cursorCell,
1396
+ after
1397
+ ] });
1414
1398
  }
1415
1399
  function getCursorLinePosition(buffer) {
1416
1400
  let row = 0;
@@ -1451,21 +1435,18 @@ function splitLineAtDisplayCol(line, col) {
1451
1435
  return { before, cursorChar, after };
1452
1436
  }
1453
1437
  function composerCursorAnchorRowOffset({
1454
- textAnchorRowBase = 1,
1438
+ textAnchorRowBase = 0,
1455
1439
  permissionActive,
1456
1440
  permissionActionCount,
1457
1441
  showSuggestions,
1458
1442
  slashCandidateCount,
1459
1443
  cursorRow
1460
1444
  }) {
1461
- let offset = 0;
1462
- if (permissionActive) {
1463
- offset += 2 + Math.max(0, permissionActionCount) + 2;
1464
- }
1465
- if (showSuggestions) {
1466
- offset += Math.max(0, slashCandidateCount) + 1;
1467
- }
1468
- return offset + Math.max(0, textAnchorRowBase) + Math.max(0, cursorRow);
1445
+ void permissionActive;
1446
+ void permissionActionCount;
1447
+ void showSuggestions;
1448
+ void slashCandidateCount;
1449
+ return Math.max(0, textAnchorRowBase) + Math.max(0, cursorRow);
1469
1450
  }
1470
1451
  function hasSelectableCommandPanelRows(panel) {
1471
1452
  return Boolean(
@@ -1532,6 +1513,7 @@ export {
1532
1513
  bufferMoveVisualUp,
1533
1514
  bufferMoveVisualDown,
1534
1515
  sanitizeComposerInput,
1516
+ sanitizeComposerPasteInput,
1535
1517
  createInputHistory,
1536
1518
  historyAdd,
1537
1519
  historyUp,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sanitizeDiagnosticText
3
- } from "./chunk-OMZYPQVA.js";
3
+ } from "./chunk-UGYFQF6M.js";
4
4
 
5
5
  // src/mcp-sse-runtime.ts
6
6
  var MCP_SSE_TIMEOUT_MS = 15e3;
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  rememberBackgroundTask
3
- } from "./chunk-CDVYF7RU.js";
3
+ } from "./chunk-OSFBVVEP.js";
4
4
  import {
5
5
  createProcessGuard
6
6
  } from "./chunk-J6CYFWSW.js";
7
7
  import {
8
8
  formatBackgroundTask
9
- } from "./chunk-UDQT5CWK.js";
9
+ } from "./chunk-PI6T2AGS.js";
10
10
  import {
11
11
  LINGHUN_VERIFICATION_COMMAND_TIMEOUT_MS
12
12
  } from "./chunk-IWUIOLMF.js";
13
13
  import {
14
14
  isRecord
15
- } from "./chunk-QLRTQHTR.js";
15
+ } from "./chunk-6JGRNES6.js";
16
16
  import {
17
17
  truncateDisplay,
18
18
  writeLine
19
- } from "./chunk-OMZYPQVA.js";
19
+ } from "./chunk-UGYFQF6M.js";
20
20
 
21
21
  // src/verification-command-runtime.ts
22
22
  import { spawn } from "child_process";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-J6CYFWSW.js";
4
4
  import {
5
5
  sanitizeDiagnosticText
6
- } from "./chunk-OMZYPQVA.js";
6
+ } from "./chunk-UGYFQF6M.js";
7
7
 
8
8
  // src/mcp-stdio-runtime.ts
9
9
  import { spawn } from "child_process";
@@ -2,7 +2,7 @@ import {
2
2
  buildTranscriptScreenBuffer,
3
3
  selectionLineIndexesForBlock,
4
4
  selectionLineRangesForBlock
5
- } from "./chunk-NKFKOEYX.js";
5
+ } from "./chunk-WCMHJ6SS.js";
6
6
  import {
7
7
  buildHelpPanelData
8
8
  } from "./chunk-3AKXDMVS.js";
@@ -24,16 +24,16 @@ import {
24
24
  formatPermissionModeLabel,
25
25
  permissionModeColor,
26
26
  permissionModeSymbol
27
- } from "./chunk-KI7C6ZOD.js";
27
+ } from "./chunk-VIJ7GDKI.js";
28
28
  import {
29
29
  sanitizeMainScreenLeakage
30
- } from "./chunk-7TYK55JT.js";
30
+ } from "./chunk-YLOJWSHB.js";
31
31
  import {
32
32
  SLASH_COMMAND_REGISTRY
33
33
  } from "./chunk-PGNALDEH.js";
34
34
  import {
35
35
  formatElapsedSince
36
- } from "./chunk-UDQT5CWK.js";
36
+ } from "./chunk-PI6T2AGS.js";
37
37
  import {
38
38
  DEFAULT_KEYBINDINGS
39
39
  } from "./chunk-6SMM5CMP.js";
@@ -42,7 +42,7 @@ import {
42
42
  } from "./chunk-K4FSYBSY.js";
43
43
  import {
44
44
  truncateMiddle
45
- } from "./chunk-APJIC2O5.js";
45
+ } from "./chunk-GTIZNO5O.js";
46
46
 
47
47
  // src/shell/view-model.ts
48
48
  import { basename } from "path";
@@ -1136,7 +1136,9 @@ function buildPermissionExplanationLinesFromVerdict(verdict, risk, language) {
1136
1136
  function inferSemanticByToolName(toolName) {
1137
1137
  if (toolName === "Bash") return "destructive";
1138
1138
  if (toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") return "mutating";
1139
- if (toolName === "Read" || toolName === "Glob" || toolName === "Grep") return "readonly";
1139
+ if (toolName === "Read" || toolName === "ReadSnippets" || toolName === "SourcePack" || toolName === "Glob" || toolName === "Grep") {
1140
+ return "readonly";
1141
+ }
1140
1142
  if (toolName === "WebSearch" || toolName === "WebFetch") return "network";
1141
1143
  return "unknown";
1142
1144
  }
@@ -1169,9 +1171,11 @@ function buildPermissionActionSummary(language, toolName, input) {
1169
1171
  const path = str("file_path") ?? str("path");
1170
1172
  if (path) return zh ? `\u4FEE\u6539\u6587\u4EF6\uFF1A${path}` : `Edit file: ${path}`;
1171
1173
  }
1172
- if (toolName === "Read") {
1174
+ if (toolName === "Read" || toolName === "ReadSnippets" || toolName === "SourcePack") {
1173
1175
  const path = str("path") ?? str("file_path");
1174
1176
  if (path) return zh ? `\u8BFB\u53D6\u6587\u4EF6\uFF1A${path}` : `Read file: ${path}`;
1177
+ if (toolName === "ReadSnippets") return zh ? "\u8BFB\u53D6\u4EE3\u7801\u7247\u6BB5" : "Read snippets";
1178
+ if (toolName === "SourcePack") return zh ? "\u5B9A\u4F4D\u4EE3\u7801\u7247\u6BB5" : "Locate source snippets";
1175
1179
  }
1176
1180
  if (toolName === "Glob" || toolName === "Grep") {
1177
1181
  const target = str("pattern") ?? str("path");
@@ -3,19 +3,19 @@ import {
3
3
  decideMemoryExtraction,
4
4
  refreshAutoMemoryFiles,
5
5
  writeAutoMemoryFiles
6
- } from "./chunk-VTQL23UM.js";
6
+ } from "./chunk-TVNWAEJR.js";
7
7
  import {
8
8
  showCommandPanel
9
- } from "./chunk-AZU7HXIT.js";
9
+ } from "./chunk-PPUOHBAK.js";
10
10
  import {
11
11
  writeErrorLine
12
- } from "./chunk-DYDTLRHB.js";
12
+ } from "./chunk-HPIHFENG.js";
13
13
  import {
14
14
  createHandoffPacket,
15
15
  formatResumePacket,
16
16
  hydrateResumeContext,
17
17
  validateHandoffPacket
18
- } from "./chunk-MLUIOBKL.js";
18
+ } from "./chunk-7ZMDQZ22.js";
19
19
  import {
20
20
  createEvidenceBackedMemoryCandidates,
21
21
  createLinghunMdTemplate,
@@ -33,15 +33,15 @@ import {
33
33
  removeMemoryRecord,
34
34
  writeMemoryLearningMode,
35
35
  writeMemoryRecord
36
- } from "./chunk-LQTVYUT3.js";
36
+ } from "./chunk-OJTMM5CV.js";
37
37
  import {
38
38
  pathExists,
39
39
  summarizeProjectRules
40
- } from "./chunk-QLRTQHTR.js";
40
+ } from "./chunk-6JGRNES6.js";
41
41
  import {
42
42
  formatError,
43
43
  writeLine
44
- } from "./chunk-OMZYPQVA.js";
44
+ } from "./chunk-UGYFQF6M.js";
45
45
 
46
46
  // src/memory-command-runtime.ts
47
47
  import { writeFile } from "fs/promises";
@@ -47,6 +47,89 @@ function displayWidth(value) {
47
47
  for (const char of value) width += charWidth(char);
48
48
  return width;
49
49
  }
50
+ function computeWrappedInputState(input) {
51
+ const normalizedText = String(input.text ?? "").replace(/\r/g, "");
52
+ const chars = Array.from(normalizedText);
53
+ const cursorOffset = clamp(input.cursorOffset, 0, chars.length);
54
+ const safeWidth = Math.max(0, Math.floor(Number.isFinite(input.width) ? input.width : 0));
55
+ const safePrefixWidth = Math.max(0, Math.floor(input.prefixWidth ?? 0));
56
+ const safePaddingLeft = Math.max(0, Math.floor(input.paddingLeft ?? 0));
57
+ const safePaddingRight = Math.max(0, Math.floor(input.paddingRight ?? 0));
58
+ const safeMinContentWidth = Math.max(0, Math.floor(input.minContentWidth ?? 0));
59
+ const contentWidth = Math.max(
60
+ safeMinContentWidth,
61
+ safeWidth - safePaddingLeft - safePaddingRight
62
+ );
63
+ const firstLineWidth = Math.max(1, contentWidth - safePrefixWidth);
64
+ const wrappedLines = [];
65
+ let cursorRow = 0;
66
+ let cursorCol = 0;
67
+ let cursorResolved = false;
68
+ const logicalLines = normalizedText.split("\n");
69
+ let logicalLineStart = 0;
70
+ let fallbackLineStart = 0;
71
+ let fallbackLineChars = [];
72
+ for (let logicalIndex = 0; logicalIndex < logicalLines.length; logicalIndex += 1) {
73
+ const lineText = logicalLines[logicalIndex] ?? "";
74
+ const lineChars = Array.from(lineText);
75
+ const lineStartOffset = logicalLineStart;
76
+ const lineEndOffset = lineStartOffset + lineChars.length;
77
+ const wrapWidth = logicalIndex === 0 ? firstLineWidth : Math.max(1, contentWidth);
78
+ const segments = wrapInputLine(lineChars, wrapWidth);
79
+ fallbackLineStart = lineStartOffset;
80
+ fallbackLineChars = lineChars;
81
+ for (const segment of segments) {
82
+ const segmentText = lineChars.slice(segment.start, segment.end).join("");
83
+ wrappedLines.push(segmentText);
84
+ if (!cursorResolved && cursorOffset >= lineStartOffset && cursorOffset <= lineEndOffset) {
85
+ const lineCursorOffset = cursorOffset - lineStartOffset;
86
+ if (lineCursorOffset >= segment.start && lineCursorOffset <= segment.end) {
87
+ cursorRow = wrappedLines.length - 1;
88
+ cursorCol = displayWidth(lineChars.slice(segment.start, lineCursorOffset).join(""));
89
+ cursorResolved = true;
90
+ }
91
+ }
92
+ }
93
+ logicalLineStart += lineChars.length + 1;
94
+ }
95
+ if (!cursorResolved) {
96
+ cursorRow = Math.max(0, wrappedLines.length - 1);
97
+ cursorCol = displayWidth(
98
+ fallbackLineChars.slice(0, clamp(cursorOffset - fallbackLineStart, 0, fallbackLineChars.length)).join("")
99
+ );
100
+ if (chars.length === 0) cursorCol = 0;
101
+ }
102
+ return {
103
+ lines: wrappedLines.length > 0 ? wrappedLines : [""],
104
+ cursorRow,
105
+ cursorCol,
106
+ contentWidth
107
+ };
108
+ }
109
+ function wrapInputLine(chars, wrapWidth) {
110
+ const safeWrapWidth = Math.max(1, Math.floor(wrapWidth));
111
+ const segments = [];
112
+ let start = 0;
113
+ while (start < chars.length || chars.length === 0 && start === 0) {
114
+ let end = start;
115
+ let width = 0;
116
+ while (end < chars.length) {
117
+ const nextWidth = charWidth(chars[end] ?? "");
118
+ if (width > 0 && width + nextWidth > safeWrapWidth) break;
119
+ width += nextWidth;
120
+ end += 1;
121
+ }
122
+ if (end === start && chars.length > 0) end += 1;
123
+ segments.push({ start, end });
124
+ if (chars.length === 0) break;
125
+ start = end;
126
+ }
127
+ return segments;
128
+ }
129
+ function clamp(value, min, max) {
130
+ if (!Number.isFinite(value)) return min;
131
+ return Math.min(max, Math.max(min, Math.floor(value)));
132
+ }
50
133
  function truncateDisplay(value, max) {
51
134
  const normalized = String(value || "").replace(/\s+/gu, " ").trim();
52
135
  if (displayWidth(normalized) <= max) return normalized;
@@ -140,6 +223,7 @@ export {
140
223
  wrapText,
141
224
  charWidth,
142
225
  displayWidth,
226
+ computeWrappedInputState,
143
227
  truncateDisplay,
144
228
  truncateMiddle,
145
229
  composerMaxWidth,
@@ -5,7 +5,7 @@ import {
5
5
  fitText,
6
6
  lineChar,
7
7
  wrapText
8
- } from "./chunk-APJIC2O5.js";
8
+ } from "./chunk-GTIZNO5O.js";
9
9
 
10
10
  // src/shell/components/CommandPanel.tsx
11
11
  import { Box, Text } from "@linghun/ink-runtime";
@@ -4,7 +4,7 @@ import {
4
4
  formatPermissionSummary,
5
5
  getHardDenyReason,
6
6
  isPlanAllowedTool
7
- } from "./chunk-J7ZE2JKP.js";
7
+ } from "./chunk-42ZZUF7P.js";
8
8
  import {
9
9
  classifyToolRequest
10
10
  } from "./chunk-LHHKPGLX.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  truncateDisplay
3
- } from "./chunk-OMZYPQVA.js";
3
+ } from "./chunk-UGYFQF6M.js";
4
4
 
5
5
  // src/pending-details-presenter.ts
6
6
  import { relative } from "path";