@linghun/tui 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/agent-completion-finalizer.js +3 -3
  2. package/dist/background-control-runtime.js +55 -55
  3. package/dist/cache-command-runtime.js +3 -3
  4. package/dist/capability-runtime.js +34 -34
  5. package/dist/{chunk-TJLC3QAS.js → chunk-36ZWUJQS.js} +1 -1
  6. package/dist/{chunk-DTK5NBTV.js → chunk-4BFCUJX6.js} +95 -11
  7. package/dist/{chunk-YH6UIHNF.js → chunk-4QWCNMP6.js} +2 -2
  8. package/dist/{chunk-WKMBK5UP.js → chunk-4TO2LDMP.js} +1 -1
  9. package/dist/{chunk-QG2FJ3NR.js → chunk-5OZEJQBH.js} +3 -3
  10. package/dist/{chunk-J7ZE2JKP.js → chunk-6C32YAB5.js} +19 -7
  11. package/dist/{chunk-W3KHJNSH.js → chunk-6CHUZ2NF.js} +2 -2
  12. package/dist/{chunk-I3NTAIMF.js → chunk-6DBBXNEG.js} +3 -3
  13. package/dist/{chunk-GDQQNPBP.js → chunk-6GXIGN5W.js} +1 -1
  14. package/dist/{chunk-QLRTQHTR.js → chunk-6JGRNES6.js} +2 -2
  15. package/dist/{chunk-AZU7HXIT.js → chunk-6JPUBF7B.js} +18 -18
  16. package/dist/{chunk-KO64OFSG.js → chunk-7C6T7RKJ.js} +1 -1
  17. package/dist/{chunk-LDABZV5V.js → chunk-7RZE45OT.js} +1 -1
  18. package/dist/{chunk-4E56DWEZ.js → chunk-7XAOTGHZ.js} +5 -5
  19. package/dist/{chunk-MLUIOBKL.js → chunk-7ZMDQZ22.js} +4 -4
  20. package/dist/{chunk-X7A22JHP.js → chunk-A4H3UTJZ.js} +1 -1
  21. package/dist/{chunk-D3UTL2QX.js → chunk-ATY7WBIT.js} +1 -1
  22. package/dist/{chunk-ZOSK2UEU.js → chunk-BBK5BA5C.js} +99 -117
  23. package/dist/{chunk-7TYK55JT.js → chunk-BEDD7OFL.js} +5 -5
  24. package/dist/{chunk-SRZIA6B4.js → chunk-BNC4F63N.js} +1 -1
  25. package/dist/{chunk-LIPZJNXS.js → chunk-CQCJGMXG.js} +4 -4
  26. package/dist/{chunk-L2GU3PWU.js → chunk-DEIYY6NI.js} +324 -16
  27. package/dist/{chunk-5CXN4JLE.js → chunk-EGHM55EV.js} +4 -4
  28. package/dist/{chunk-HIIYRATQ.js → chunk-ESAACKVG.js} +11 -7
  29. package/dist/{chunk-O6MKVGVK.js → chunk-G7O26P5X.js} +1 -1
  30. package/dist/{chunk-APJIC2O5.js → chunk-GTIZNO5O.js} +84 -0
  31. package/dist/{chunk-UOHZQIVL.js → chunk-GXFYUZAM.js} +1 -1
  32. package/dist/{chunk-Y5ZV47XC.js → chunk-GYHEUVR2.js} +7 -7
  33. package/dist/{chunk-QTDGRZMZ.js → chunk-HJOC5WUV.js} +1 -1
  34. package/dist/{chunk-KOULRCYJ.js → chunk-HMGYFENJ.js} +2 -2
  35. package/dist/{chunk-SYBNJZEL.js → chunk-HPMBSOQ4.js} +1 -1
  36. package/dist/{chunk-4K6UB524.js → chunk-IPZZGDUU.js} +1 -1
  37. package/dist/{chunk-JJQETFCR.js → chunk-IQS34W5A.js} +4 -4
  38. package/dist/{chunk-WOBNOBB5.js → chunk-J7AAPUTV.js} +3 -3
  39. package/dist/{chunk-6CI6TKLN.js → chunk-JAVRQ3LM.js} +1 -1
  40. package/dist/{chunk-VCSRBS47.js → chunk-JLAJZPOC.js} +1 -1
  41. package/dist/{chunk-CD54BQJ5.js → chunk-JMUAQUQQ.js} +4 -4
  42. package/dist/{chunk-NL4M3V5D.js → chunk-KKZBBCHK.js} +1 -1
  43. package/dist/{chunk-RMLTVKOY.js → chunk-L4YVE3RG.js} +2 -2
  44. package/dist/{chunk-F6TVBCZV.js → chunk-LWW2IAFC.js} +1 -1
  45. package/dist/{chunk-VAGL7CNR.js → chunk-NMOVU75L.js} +4 -4
  46. package/dist/{chunk-K56D3X7S.js → chunk-NWZ44SFI.js} +112 -5
  47. package/dist/{chunk-DYDTLRHB.js → chunk-OH35XDD4.js} +2 -2
  48. package/dist/{chunk-BOV4K7FP.js → chunk-OI5TZ37D.js} +36 -1
  49. package/dist/{chunk-LQTVYUT3.js → chunk-OJTMM5CV.js} +2 -2
  50. package/dist/{chunk-SILJJAK2.js → chunk-OMWSM2DA.js} +2 -2
  51. package/dist/{chunk-HW2TBXVK.js → chunk-OPVRII63.js} +1 -1
  52. package/dist/{chunk-XWRHWM4H.js → chunk-OV5OT66G.js} +11 -11
  53. package/dist/{chunk-F43AMWLZ.js → chunk-PDTJVJVD.js} +1 -1
  54. package/dist/{chunk-DDXS2RDZ.js → chunk-PHPEPZAA.js} +1 -1
  55. package/dist/{chunk-UDQT5CWK.js → chunk-PI6T2AGS.js} +1 -1
  56. package/dist/{chunk-3BPKJMIV.js → chunk-Q57WS7YZ.js} +4 -4
  57. package/dist/{chunk-33E6RDCY.js → chunk-QD4SCW4A.js} +229 -192
  58. package/dist/{chunk-QJTET7EZ.js → chunk-QXV2N4F2.js} +4 -4
  59. package/dist/{chunk-RFSSKGCE.js → chunk-RDTVAQBD.js} +239 -75
  60. package/dist/{chunk-SOPYWTFV.js → chunk-RRUI3VWQ.js} +1 -1
  61. package/dist/{chunk-IN42UISW.js → chunk-SRJ4XWOR.js} +10 -5
  62. package/dist/{chunk-6RJVTUWI.js → chunk-T6UOCF5D.js} +5 -1
  63. package/dist/{chunk-P277M7Z5.js → chunk-TO6IN4LA.js} +201 -5
  64. package/dist/{chunk-VTQL23UM.js → chunk-TVNWAEJR.js} +1 -1
  65. package/dist/chunk-TY4KIVA6.js +50 -0
  66. package/dist/{chunk-UT2TYK2A.js → chunk-TYTVAFGB.js} +1 -1
  67. package/dist/{chunk-OMZYPQVA.js → chunk-UGYFQF6M.js} +1 -1
  68. package/dist/{chunk-JGDIO2NF.js → chunk-UO3KYTBU.js} +1 -1
  69. package/dist/{chunk-MXPBYB54.js → chunk-UYU4QN3P.js} +2 -2
  70. package/dist/{chunk-J6CYFWSW.js → chunk-VDQTNA4W.js} +20 -1
  71. package/dist/{chunk-KI7C6ZOD.js → chunk-VIJ7GDKI.js} +1 -1
  72. package/dist/{chunk-NKFKOEYX.js → chunk-WCMHJ6SS.js} +1 -1
  73. package/dist/{chunk-EORRZP3F.js → chunk-WX2OTJXL.js} +1 -1
  74. package/dist/{chunk-CRQORMFF.js → chunk-X37FSYAX.js} +1 -1
  75. package/dist/chunk-X7HMDZZQ.js +85 -0
  76. package/dist/{chunk-624A7BBJ.js → chunk-XYY5LRSF.js} +4 -4
  77. package/dist/{chunk-CDVYF7RU.js → chunk-YBTXLLO5.js} +4 -4
  78. package/dist/{chunk-UN53MBAR.js → chunk-YGXPS5F2.js} +2 -2
  79. package/dist/chunk-YQNK7HK3.js +87 -0
  80. package/dist/{chunk-KJVHLTQR.js → chunk-Z265MCGC.js} +12 -8
  81. package/dist/{chunk-RM5QMOFY.js → chunk-ZKPQ4KLK.js} +1 -1
  82. package/dist/{chunk-4UER2AKI.js → chunk-ZPFOP557.js} +190 -0
  83. package/dist/command-panel-runtime.js +33 -33
  84. package/dist/compact-cache-command-runtime.js +55 -55
  85. package/dist/compact-preflight-runtime.js +20 -20
  86. package/dist/connector-runtime.js +35 -35
  87. package/dist/deep-compact-runtime.js +6 -6
  88. package/dist/deferred-tools-catalog.js +5 -5
  89. package/dist/details-status-runtime.js +33 -33
  90. package/dist/evidence-runtime.d.ts.map +1 -1
  91. package/dist/evidence-runtime.js +12 -11
  92. package/dist/extension-command-runtime.js +7 -7
  93. package/dist/extension-slash-runtime.js +34 -34
  94. package/dist/failure-learning-command-runtime.js +35 -35
  95. package/dist/failure-learning-presenter.js +4 -4
  96. package/dist/failure-learning-runtime.js +3 -3
  97. package/dist/final-answer-gate.d.ts +1 -0
  98. package/dist/final-answer-gate.d.ts.map +1 -1
  99. package/dist/final-answer-gate.js +4 -2
  100. package/dist/git-command-runtime.js +34 -34
  101. package/dist/handoff-session-runtime.js +8 -8
  102. package/dist/headless-bench-runtime.d.ts +19 -1
  103. package/dist/headless-bench-runtime.d.ts.map +1 -1
  104. package/dist/headless-bench-runtime.js +3 -1
  105. package/dist/index-result-presenter.js +5 -5
  106. package/dist/index-runtime.js +5 -5
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +143 -69
  109. package/dist/job-agent-command-runtime.js +33 -33
  110. package/dist/job-runner-presenter.js +3 -3
  111. package/dist/job-runtime.js +9 -9
  112. package/dist/mcp-index-command-runtime.js +5 -5
  113. package/dist/mcp-index-runtime.js +38 -38
  114. package/dist/mcp-sse-runtime.js +3 -3
  115. package/dist/mcp-stdio-runtime.js +4 -4
  116. package/dist/memory-command-runtime.js +35 -35
  117. package/dist/memory-extraction-runtime.js +3 -3
  118. package/dist/memory-rules-runtime.js +3 -3
  119. package/dist/meta-scheduler-runtime.js +2 -2
  120. package/dist/model-command-runtime.js +34 -34
  121. package/dist/model-loop-runtime.d.ts +1 -1
  122. package/dist/model-loop-runtime.d.ts.map +1 -1
  123. package/dist/model-loop-runtime.js +1 -1
  124. package/dist/model-prompt-runtime.js +10 -10
  125. package/dist/model-stream-runtime.d.ts.map +1 -1
  126. package/dist/model-stream-runtime.js +55 -55
  127. package/dist/model-tool-runtime.d.ts +1 -0
  128. package/dist/model-tool-runtime.d.ts.map +1 -1
  129. package/dist/model-tool-runtime.js +57 -55
  130. package/dist/pending-details-presenter.js +3 -3
  131. package/dist/permission-approval-runtime.js +55 -55
  132. package/dist/permission-continuation-runtime.d.ts.map +1 -1
  133. package/dist/permission-continuation-runtime.js +4 -4
  134. package/dist/process-command-runtime.js +4 -4
  135. package/dist/process-guard.d.ts +3 -0
  136. package/dist/process-guard.d.ts.map +1 -1
  137. package/dist/process-guard.js +5 -1
  138. package/dist/provider-loop-runtime.js +3 -3
  139. package/dist/remote-command-runtime.js +34 -34
  140. package/dist/runner-runtime.js +8 -8
  141. package/dist/runtime-status-presenter.js +3 -3
  142. package/dist/runtime-status-snapshot.js +4 -4
  143. package/dist/shell/components/AgentProgressTree.js +2 -2
  144. package/dist/shell/components/BackgroundTaskOverlay.js +2 -2
  145. package/dist/shell/components/BtwPanel.js +2 -2
  146. package/dist/shell/components/CommandPanel.js +2 -2
  147. package/dist/shell/components/Composer.d.ts +16 -2
  148. package/dist/shell/components/Composer.d.ts.map +1 -1
  149. package/dist/shell/components/Composer.js +9 -7
  150. package/dist/shell/components/ConfigPanel.js +2 -2
  151. package/dist/shell/components/HelpPanel.js +2 -2
  152. package/dist/shell/components/HistorySearchPanel.js +2 -2
  153. package/dist/shell/components/MessageMarkdown.d.ts +23 -0
  154. package/dist/shell/components/MessageMarkdown.d.ts.map +1 -1
  155. package/dist/shell/components/MessageMarkdown.js +5 -3
  156. package/dist/shell/components/MouseInputRouter.js +5 -80
  157. package/dist/shell/components/OutputLine.d.ts.map +1 -1
  158. package/dist/shell/components/OutputLine.js +5 -3
  159. package/dist/shell/components/ProductBlock.d.ts.map +1 -1
  160. package/dist/shell/components/ProductBlock.js +4 -4
  161. package/dist/shell/components/ScrollViewport.js +3 -82
  162. package/dist/shell/components/SessionsPanel.js +2 -2
  163. package/dist/shell/components/ShellApp.d.ts.map +1 -1
  164. package/dist/shell/components/ShellApp.js +28 -23
  165. package/dist/shell/components/SlashSuggestions.js +2 -2
  166. package/dist/shell/components/StatusFooter.js +2 -2
  167. package/dist/shell/components/StatusTray.d.ts.map +1 -1
  168. package/dist/shell/components/StatusTray.js +2 -1
  169. package/dist/shell/components/StructuredDiff.js +2 -2
  170. package/dist/shell/components/TaskListView.js +2 -2
  171. package/dist/shell/components/TaskSuggestionBar.js +2 -2
  172. package/dist/shell/components/WorkflowProgressView.js +2 -2
  173. package/dist/shell/components/useAnchoredCursor.d.ts +6 -9
  174. package/dist/shell/components/useAnchoredCursor.d.ts.map +1 -1
  175. package/dist/shell/components/useAnchoredCursor.js +1 -1
  176. package/dist/shell/ink-renderer.d.ts.map +1 -1
  177. package/dist/shell/ink-renderer.js +28 -23
  178. package/dist/shell/models/transcript-selection-state.js +2 -2
  179. package/dist/shell/plain-renderer.d.ts.map +1 -1
  180. package/dist/shell/plain-renderer.js +2 -2
  181. package/dist/shell/text-utils.d.ts +16 -0
  182. package/dist/shell/text-utils.d.ts.map +1 -1
  183. package/dist/shell/text-utils.js +3 -1
  184. package/dist/shell/view-model.js +14 -14
  185. package/dist/slash-command-runtime.js +55 -55
  186. package/dist/slash-dispatch.js +4 -4
  187. package/dist/startup-runtime.js +2 -2
  188. package/dist/tool-output-presenter.d.ts +1 -0
  189. package/dist/tool-output-presenter.d.ts.map +1 -1
  190. package/dist/tool-output-presenter.js +3 -1
  191. package/dist/tui-agent-job-runtime.js +11 -11
  192. package/dist/tui-context-runtime.d.ts +2 -0
  193. package/dist/tui-context-runtime.d.ts.map +1 -1
  194. package/dist/tui-data-types.d.ts +1 -0
  195. package/dist/tui-data-types.d.ts.map +1 -1
  196. package/dist/tui-details-runtime.js +10 -10
  197. package/dist/tui-memory-runtime.js +5 -5
  198. package/dist/tui-output-surface.js +15 -15
  199. package/dist/tui-permission-runtime.js +5 -5
  200. package/dist/tui-state-runtime.js +4 -4
  201. package/dist/verification-command-runtime.js +12 -12
  202. package/dist/workflow-command-runtime.js +33 -33
  203. package/package.json +5 -5
  204. package/dist/chunk-GW5YDCRZ.js +0 -42
@@ -0,0 +1,87 @@
1
+ import {
2
+ computeScrollViewportOffset
3
+ } from "./chunk-JPXSFZFC.js";
4
+
5
+ // src/shell/components/ScrollViewport.tsx
6
+ import { Box } from "@linghun/ink-runtime";
7
+ import { useEffect, useRef, useState } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ function TranscriptViewport({
10
+ scroll,
11
+ virtualRange,
12
+ onOverflowChange,
13
+ onMeasure,
14
+ onGeometry,
15
+ children
16
+ }) {
17
+ const viewportRef = useRef(null);
18
+ const contentRef = useRef(null);
19
+ const [maxOffset, setMaxOffset] = useState(0);
20
+ const maxOffsetRef = useRef(0);
21
+ const lastReportedOverflow = useRef(void 0);
22
+ const lastReportedMeasure = useRef(void 0);
23
+ const lastReportedGeometry = useRef(void 0);
24
+ const lastDimKey = useRef("");
25
+ useEffect(() => {
26
+ const viewportNode = viewportRef.current?.yogaNode;
27
+ const contentNode = contentRef.current?.yogaNode;
28
+ if (!viewportNode || !contentNode) return;
29
+ const viewportHeight = viewportNode.getComputedHeight();
30
+ const viewportWidth = viewportNode.getComputedWidth();
31
+ const measuredContentHeight = contentNode.getComputedHeight();
32
+ const contentHeight = virtualRange?.estimatedContentHeight ?? measuredContentHeight;
33
+ const dimKey = `${viewportHeight}:${contentHeight}`;
34
+ if (dimKey === lastDimKey.current) return;
35
+ lastDimKey.current = dimKey;
36
+ const nextMax = Math.max(0, Math.floor(contentHeight - viewportHeight));
37
+ const nextOffset = computeScrollViewportOffset(nextMax, scroll);
38
+ const measureKey = `${viewportHeight}:${contentHeight}`;
39
+ if (onMeasure && lastReportedMeasure.current !== measureKey) {
40
+ lastReportedMeasure.current = measureKey;
41
+ onMeasure({ viewportHeight, contentHeight });
42
+ }
43
+ if (onGeometry) {
44
+ const origin = computeAbsolutePosition(viewportRef.current);
45
+ const geometry = {
46
+ x: Math.floor(origin.x),
47
+ y: Math.floor(origin.y),
48
+ width: Math.floor(viewportWidth),
49
+ height: Math.floor(viewportHeight),
50
+ contentHeight: Math.floor(contentHeight),
51
+ topOffset: nextOffset.topOffset
52
+ };
53
+ const geometryKey = `${geometry.x}:${geometry.y}:${geometry.width}:${geometry.height}:${geometry.contentHeight}:${geometry.topOffset}`;
54
+ if (lastReportedGeometry.current !== geometryKey) {
55
+ lastReportedGeometry.current = geometryKey;
56
+ onGeometry(geometry);
57
+ }
58
+ }
59
+ if (maxOffsetRef.current !== nextMax) {
60
+ maxOffsetRef.current = nextMax;
61
+ setMaxOffset(nextMax);
62
+ }
63
+ const hasOverflow = nextMax > 0;
64
+ if (onOverflowChange && lastReportedOverflow.current !== hasOverflow) {
65
+ lastReportedOverflow.current = hasOverflow;
66
+ onOverflowChange(hasOverflow);
67
+ }
68
+ });
69
+ const { marginTop } = computeScrollViewportOffset(maxOffset, scroll);
70
+ const contentMarginTop = virtualRange && virtualRange.estimatedContentHeight > 0 ? marginTop + virtualRange.topSpacer : marginTop;
71
+ return /* @__PURE__ */ jsx(Box, { ref: viewportRef, flexDirection: "column", flexGrow: 1, minHeight: 0, overflow: "hidden", children: /* @__PURE__ */ jsx(Box, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginTop: contentMarginTop, children }) });
72
+ }
73
+ function computeAbsolutePosition(node) {
74
+ let current = node ?? void 0;
75
+ let x = 0;
76
+ let y = 0;
77
+ while (current?.yogaNode) {
78
+ x += current.yogaNode.getComputedLeft();
79
+ y += current.yogaNode.getComputedTop();
80
+ current = current.parentNode;
81
+ }
82
+ return { x, y };
83
+ }
84
+
85
+ export {
86
+ TranscriptViewport
87
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MOJL4X4L.js";
4
4
  import {
5
5
  MessageMarkdown
6
- } from "./chunk-DTK5NBTV.js";
6
+ } from "./chunk-4BFCUJX6.js";
7
7
  import {
8
8
  MessageResponse
9
9
  } from "./chunk-L5GOCMZP.js";
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  fitText,
15
15
  wrapText
16
- } from "./chunk-APJIC2O5.js";
16
+ } from "./chunk-GTIZNO5O.js";
17
17
 
18
18
  // src/shell/components/ProductBlock.tsx
19
19
  import { Box, Text } from "@linghun/ink-runtime";
@@ -49,6 +49,9 @@ function messageBody(block, nextAction) {
49
49
  }
50
50
  return (block.fullText ?? block.summary ?? "").trim();
51
51
  }
52
+ function messageResponseBodyWidth(width) {
53
+ return Math.max(8, width - 5);
54
+ }
52
55
  function ProductBlock({
53
56
  block,
54
57
  theme,
@@ -60,9 +63,10 @@ function ProductBlock({
60
63
  if (block.kind === "user" || block.kind === "command" && block.messageKind === "user_text") {
61
64
  const body = (block.fullText ?? block.title ?? "").trim();
62
65
  if (!body) return null;
66
+ const bodyWidth = Math.max(8, width - 2);
63
67
  return /* @__PURE__ */ jsxs(Box, { marginTop: 1, marginBottom: 1, flexDirection: "row", children: [
64
68
  /* @__PURE__ */ jsx(Text, { color: theme.inactive ?? theme.muted, children: "\u2502 " }),
65
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: wrapText(body, Math.max(8, width - 2)).map((line, idx) => /* @__PURE__ */ jsx(
69
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: bodyWidth, children: wrapText(body, bodyWidth).map((line, idx) => /* @__PURE__ */ jsx(
66
70
  Text,
67
71
  {
68
72
  backgroundColor: theme.mode === "no-color" ? void 0 : theme.userBackground,
@@ -98,7 +102,7 @@ function ProductBlock({
98
102
  theme,
99
103
  dim,
100
104
  tone,
101
- wrapWidth: Math.max(8, width - 4),
105
+ wrapWidth: messageResponseBodyWidth(width),
102
106
  selectionLineIndexes: block.selectionLineIndexes,
103
107
  selectionLineRanges: block.selectionLineRanges
104
108
  }
@@ -163,7 +167,7 @@ function ProductBlock({
163
167
  text: body,
164
168
  theme,
165
169
  tone: "error",
166
- wrapWidth: Math.max(8, width - 4),
170
+ wrapWidth: messageResponseBodyWidth(width),
167
171
  selectionLineIndexes: block.selectionLineIndexes,
168
172
  selectionLineRanges: block.selectionLineRanges
169
173
  }
@@ -196,13 +200,13 @@ function ProductBlock({
196
200
  titleVisible ? /* @__PURE__ */ jsxs(Text, { children: [
197
201
  /* @__PURE__ */ jsx(Text, { color: theme.status[block.status], children: getStatusMarker(block.status, theme.mode === "no-color") }),
198
202
  " ",
199
- block.title
203
+ fitText(block.title, Math.max(8, innerWidth - 2))
200
204
  ] }) : summaryAsMarker ? /* @__PURE__ */ jsxs(Text, { color: theme.status[block.status], children: [
201
205
  getStatusMarker(block.status, theme.mode === "no-color"),
202
206
  " ",
203
- block.summary
207
+ fitText(block.summary, Math.max(8, innerWidth - 2))
204
208
  ] }) : null,
205
- !summaryAsMarker && summaryTrimmed ? /* @__PURE__ */ jsx(Text, { children: block.summary }) : null,
209
+ !summaryAsMarker && summaryTrimmed ? wrapText(block.summary, innerWidth).map((line, index) => /* @__PURE__ */ jsx(Text, { children: line }, `${index}-${line}`)) : null,
206
210
  block.detail ? /* @__PURE__ */ jsx(Text, { color: theme.inactive ?? theme.muted, children: fitText(block.detail, innerWidth) }) : null,
207
211
  nextAction ? /* @__PURE__ */ jsx(CtrlOToExpand, { theme, hint: fitText(nextAction, innerWidth) }) : null
208
212
  ]
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  formatElapsedSince
3
- } from "./chunk-UDQT5CWK.js";
3
+ } from "./chunk-PI6T2AGS.js";
4
4
 
5
5
  // src/runtime-status-snapshot.ts
6
6
  function createRuntimeStatusSnapshot(input) {
@@ -55,6 +55,10 @@ async function resolveHeadlessBenchConfig(input) {
55
55
  testTimeoutMs,
56
56
  maxRepairAttempts,
57
57
  requiredArtifacts,
58
+ validationContract: createValidationContract({
59
+ prompt: input.prompt,
60
+ requiredArtifacts
61
+ }),
58
62
  preflight: input.options?.preflight ?? parseBoolean(env.LINGHUN_HEADLESS_PREFLIGHT) ?? true,
59
63
  environmentSetupRetries
60
64
  };
@@ -77,6 +81,7 @@ async function runHeadlessEnvironmentPreflight(projectPath) {
77
81
  function createHeadlessBenchInitialPrompt(input) {
78
82
  if (!input.config.enabled) return input.originalPrompt;
79
83
  const required = input.config.requiredArtifacts.length ? `Required artifacts detected: ${input.config.requiredArtifacts.join(", ")}. Verify they exist and are readable before final.` : "No explicit output artifact path was detected; still verify observable task completion.";
84
+ const contract = formatValidationContractPromptLines(input.config.validationContract);
80
85
  const test = input.config.testCommand ? `Official test command available: ${input.config.testCommand}. Prefer it over ad-hoc smoke tests before final.` : "No official test command was detected; use the strongest task-local verification available.";
81
86
  const preflight = input.preflight ? `Environment preflight: ${input.preflight.summary}` : "";
82
87
  return [
@@ -85,9 +90,11 @@ function createHeadlessBenchInitialPrompt(input) {
85
90
  "[Linghun headless bench guard]",
86
91
  test,
87
92
  required,
93
+ ...contract,
88
94
  preflight,
89
95
  formatInitialProfileStrategy(input.config.profile),
90
96
  "If rg is unavailable, use grep/find/sed/awk fallbacks instead of failing the task.",
97
+ ...formatCommonBenchStabilityGuidance(),
91
98
  "Do not claim completion from a self-written smoke test when an official test entrypoint is available."
92
99
  ].filter(Boolean).join("\n");
93
100
  }
@@ -217,7 +224,9 @@ function createHeadlessBenchRepairPrompt(input) {
217
224
  "Continue from the current workspace. Do not restart from scratch unless necessary.",
218
225
  "Use the official test failure and current files to make the smallest fix, then rerun the official test or artifact check.",
219
226
  formatRepairProfileStrategy(input.failure.category, input.profile ?? "generic"),
227
+ ...formatCommonBenchStabilityGuidance(),
220
228
  input.preflight?.missingTools.includes("rg") ? "rg is missing in this environment; use grep/find/sed/awk fallbacks." : "",
229
+ ...formatValidationContractPromptLines(input.validationContract),
221
230
  artifactLine,
222
231
  logLine,
223
232
  "",
@@ -228,6 +237,183 @@ function createHeadlessBenchRepairPrompt(input) {
228
237
  input.originalPrompt
229
238
  ].filter(Boolean).join("\n");
230
239
  }
240
+ function createValidationContract(input) {
241
+ const items = [];
242
+ for (const path of input.requiredArtifacts) {
243
+ pushValidationContractItem(items, {
244
+ id: `artifact:${path}`,
245
+ kind: "artifact",
246
+ path,
247
+ requiredTool: "Bash.artifact"
248
+ });
249
+ }
250
+ for (const target of detectExplicitServiceTargets(input.prompt)) {
251
+ const semanticTokens = detectServiceSemanticTokens(input.prompt);
252
+ const semantic = semanticTokens.length >= 2 && hasSemanticServiceExpectation(input.prompt);
253
+ const validationTarget = semantic ? normalizeServiceReadinessTarget(target) : target;
254
+ pushValidationContractItem(items, {
255
+ id: `service:${validationTarget}`,
256
+ kind: "service",
257
+ target: validationTarget,
258
+ validation: semantic ? "semantic" : "readiness",
259
+ ...semantic ? { semanticTokens } : {},
260
+ requiredTool: "Bash.service"
261
+ });
262
+ }
263
+ if (hasPreservationRequirement(input.prompt)) {
264
+ for (const path of detectEngineeringArtifactTargets(input.prompt)) {
265
+ pushValidationContractItem(items, {
266
+ id: `preservation:${path}`,
267
+ kind: "preservation",
268
+ path,
269
+ requiredTool: "Bash.artifact"
270
+ });
271
+ }
272
+ }
273
+ for (const path of uniqueStrings([
274
+ ...input.requiredArtifacts.filter(isBinaryLikePath),
275
+ ...detectEngineeringArtifactTargets(input.prompt).filter(
276
+ (path2) => isBinaryLikePath(path2) || hasBinaryRequirementNearPath(input.prompt, path2)
277
+ )
278
+ ])) {
279
+ pushValidationContractItem(items, {
280
+ id: `binary:${path}`,
281
+ kind: "binary",
282
+ path,
283
+ requiredTool: "Bash.binary"
284
+ });
285
+ }
286
+ return { items };
287
+ }
288
+ function pushValidationContractItem(items, item) {
289
+ if (items.some(
290
+ (existing) => existing.kind === item.kind && existing.path === item.path && normalizeContractTarget(existing.target) === normalizeContractTarget(item.target)
291
+ )) {
292
+ return;
293
+ }
294
+ items.push(item);
295
+ }
296
+ function formatValidationContractPromptLines(contract) {
297
+ if (!contract?.items.length) return [];
298
+ return [
299
+ "Validation contract: before final, satisfy each item with the required explicit tool.",
300
+ ...contract.items.map((item) => {
301
+ const subject = item.path ?? item.target ?? item.id;
302
+ const semantic = item.kind === "service" && item.validation === "semantic" ? `; also run semantic request/response probes for expected fields/values (${(item.semanticTokens ?? []).join(", ")}) including representative and adversarial cases` : "";
303
+ return `- ${item.kind}: ${subject}; required Bash input: ${formatValidationContractToolInput(item)}${semantic}`;
304
+ })
305
+ ];
306
+ }
307
+ function formatValidationContractToolInput(item) {
308
+ if (item.requiredTool === "Bash.service") {
309
+ const target = item.target ?? "http://127.0.0.1:PORT/";
310
+ const url = target.startsWith("http://") || target.startsWith("https://") ? target : `http://${target}`;
311
+ return `{ "service": { "action": "fetch", "url": ${JSON.stringify(url)}, "expectStatus": 200, "retry": 5 } }`;
312
+ }
313
+ if (item.requiredTool === "Bash.binary") {
314
+ return `{ "binary": { "path": ${JSON.stringify(item.path ?? "PATH")} } }`;
315
+ }
316
+ if (item.kind === "preservation") {
317
+ return `{ "artifact": { "path": ${JSON.stringify(item.path ?? "PATH")}, "preserve": { "mode": "compareNormalizedHtml", "expectedPath": "EXPECTED_PATH" } } }`;
318
+ }
319
+ return `{ "artifact": { "path": ${JSON.stringify(item.path ?? "PATH")} } }`;
320
+ }
321
+ function detectExplicitServiceTargets(prompt) {
322
+ const targets = [];
323
+ const urlPattern = /https?:\/\/(?:localhost|127\.0\.0\.1)(?::\d{1,5})?(?:\/[^\s`"')\]}<>]*)?/giu;
324
+ for (const match of prompt.matchAll(urlPattern)) {
325
+ targets.push(normalizeServiceTarget(match[0]));
326
+ }
327
+ const hostPortPattern = /\b(?:localhost|127\.0\.0\.1):\d{1,5}\b/giu;
328
+ for (const match of prompt.matchAll(hostPortPattern)) {
329
+ targets.push(normalizeServiceTarget(match[0]));
330
+ }
331
+ if (hasExplicitServicePortContext(prompt)) {
332
+ const portPattern = /\b(?:port\s+(\d{1,5})|listen(?:ing)?(?:\s+on)?\s+(?:port\s+)?(\d{1,5})|localhost\s+port\s+(\d{1,5})|127\.0\.0\.1\s+port\s+(\d{1,5}))\b/giu;
333
+ for (const match of prompt.matchAll(portPattern)) {
334
+ const port = match[1] ?? match[2] ?? match[3] ?? match[4];
335
+ if (port) targets.push(`127.0.0.1:${port}`);
336
+ }
337
+ }
338
+ return uniqueStrings(targets).filter(hasValidServicePort);
339
+ }
340
+ function hasExplicitServicePortContext(prompt) {
341
+ return /\b(?:service|server|serve|listen|http|endpoint|health|localhost|127\.0\.0\.1)\b/iu.test(prompt);
342
+ }
343
+ function hasSemanticServiceExpectation(prompt) {
344
+ return /\b(?:api|endpoint|json|response|respond|return|schema|field|classification|sentiment|confidence|prediction|inference|request)\b|接口|响应|返回|字段|分类|预测/iu.test(
345
+ prompt
346
+ );
347
+ }
348
+ function detectServiceSemanticTokens(prompt) {
349
+ const tokens = [];
350
+ for (const match of prompt.matchAll(/["']([A-Za-z][A-Za-z0-9_-]{1,39})["']\s*:/gu)) {
351
+ tokens.push(match[1]);
352
+ }
353
+ for (const match of prompt.matchAll(/\b(?:positive|negative|true|false|pass|fail|success|error|valid|invalid)\b/giu)) {
354
+ tokens.push(match[0].toLowerCase());
355
+ }
356
+ return uniqueStrings(tokens).slice(0, 8);
357
+ }
358
+ function normalizeServiceTarget(value) {
359
+ return value.replace(/[),.;!?]+$/u, "");
360
+ }
361
+ function normalizeServiceReadinessTarget(target) {
362
+ try {
363
+ const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
364
+ return target.startsWith("http://") || target.startsWith("https://") ? url.origin : `${url.hostname}:${url.port || (url.protocol === "https:" ? "443" : "80")}`;
365
+ } catch {
366
+ return target;
367
+ }
368
+ }
369
+ function normalizeContractTarget(target) {
370
+ if (!target) return void 0;
371
+ try {
372
+ const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
373
+ const port = url.port || (url.protocol === "https:" ? "443" : "80");
374
+ const path = url.pathname.replace(/\/$/u, "");
375
+ return `${url.hostname}:${port}${path}`;
376
+ } catch {
377
+ return target.replace(/\/$/u, "");
378
+ }
379
+ }
380
+ function hasValidServicePort(target) {
381
+ try {
382
+ const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
383
+ const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
384
+ return Number.isInteger(port) && port > 0 && port <= 65535;
385
+ } catch {
386
+ return false;
387
+ }
388
+ }
389
+ function hasPreservationRequirement(prompt) {
390
+ return /(?:\bpreserve\b|\bclean\b|\boriginal\b|\bunchanged\b|don't modify|do not modify|不要修改|保持原样|保留原始)/iu.test(
391
+ prompt
392
+ );
393
+ }
394
+ function isBinaryLikePath(path) {
395
+ return /\.(?:bin|elf|so|dll|dylib|exe|o|a|class|wasm|7z|zip|tar|gz|xz|bz2)$/iu.test(path);
396
+ }
397
+ function hasBinaryRequirementNearPath(prompt, path) {
398
+ const index = prompt.indexOf(path);
399
+ if (index < 0) return false;
400
+ const window = prompt.slice(Math.max(0, index - 80), Math.min(prompt.length, index + path.length + 80));
401
+ return /(?:\bbinary\b|\bELF\b|二进制)/iu.test(window);
402
+ }
403
+ function formatCommonBenchStabilityGuidance() {
404
+ return [
405
+ "Command environment: prefer python3 over bare python. If a command reports python not found, treat it as recoverable and retry with python3.",
406
+ 'Python dependencies: before relying on optional imports, probe with python3 -c "import X"; install only when appropriate, otherwise use a stdlib fallback.',
407
+ "Services: after starting HTTP/gRPC/server processes, poll the port or health endpoint with a bounded timeout and inspect logs before final verification.",
408
+ "Time budget: build the smallest verifiable solution first, run focused checks early, and avoid long blind builds/training runs near the deadline.",
409
+ "Verifier alignment: read task-local tests/verifier expectations and confirm output path, filename, port, and answer format instead of only matching examples.",
410
+ "Artifact checks: match validation commands to the artifact language or file type; do not run shell syntax checks on Python/JS/C++ source files.",
411
+ "Preservation tasks: when unchanged/clean/original content must survive, avoid parser/serializer round-trips unless tests allow reformatting; make targeted edits and compare preserved regions.",
412
+ "Sanitizer/filter tasks: run negative clean-sample checks that compare parser-normalized or whitespace-stripped output against the original; unsafe-case smoke tests alone are not enough.",
413
+ "Answer extraction: inspect tests/expected files for required count, ordering, and multi-line answers; do not stop at the first plausible value when the verifier expects multiple outputs.",
414
+ "Puzzle answer tasks: if multiple equally optimal or valid answers can exist and the output format allows a list, enumerate all required answers rather than a single example."
415
+ ];
416
+ }
231
417
  async function detectHeadlessBenchTaskProfile(input) {
232
418
  const files = await listProjectFiles(input.projectPath, 220);
233
419
  const haystack = `${input.prompt}
@@ -367,6 +553,9 @@ function formatRepairProfileStrategy(category, profile) {
367
553
  if (category === "missing_artifact") {
368
554
  return "Repair route: generate or write the required artifact now, then verify it exists, is readable, and is non-empty.";
369
555
  }
556
+ if (category === "validation_contract") {
557
+ return "Repair route: run the required explicit validation tool for the contract item, then repair any failed evidence before final.";
558
+ }
370
559
  if (category === "test_timeout") {
371
560
  return "Repair route: narrow validation to focused tests or logs first; avoid repeatedly launching full expensive runs.";
372
561
  }
@@ -627,6 +816,7 @@ export {
627
816
  collectHeadlessArtifactChecklist,
628
817
  classifyEnvironmentSetupFailure,
629
818
  createHeadlessBenchRepairPrompt,
819
+ createValidationContract,
630
820
  detectHeadlessBenchTaskProfile,
631
821
  detectEngineeringTaskProfile,
632
822
  classifyHeadlessFailure,
@@ -3,61 +3,61 @@ import {
3
3
  getCommandPanelRowText,
4
4
  getCommandPanelSelectableRows,
5
5
  showCommandPanel
6
- } from "./chunk-AZU7HXIT.js";
6
+ } from "./chunk-6JPUBF7B.js";
7
7
  import "./chunk-V7GDHHBL.js";
8
8
  import "./chunk-GCMH5P4W.js";
9
- import "./chunk-DDXS2RDZ.js";
10
- import "./chunk-4E56DWEZ.js";
11
- import "./chunk-CDVYF7RU.js";
12
- import "./chunk-UN53MBAR.js";
13
- import "./chunk-DYDTLRHB.js";
14
- import "./chunk-4K6UB524.js";
9
+ import "./chunk-PHPEPZAA.js";
10
+ import "./chunk-7XAOTGHZ.js";
11
+ import "./chunk-YBTXLLO5.js";
12
+ import "./chunk-YGXPS5F2.js";
13
+ import "./chunk-OH35XDD4.js";
14
+ import "./chunk-IPZZGDUU.js";
15
15
  import "./chunk-PBIPV4LD.js";
16
- import "./chunk-VAGL7CNR.js";
17
- import "./chunk-CD54BQJ5.js";
16
+ import "./chunk-NMOVU75L.js";
17
+ import "./chunk-JMUAQUQQ.js";
18
18
  import "./chunk-L4XXW6Y5.js";
19
19
  import "./chunk-CRSLDQOA.js";
20
20
  import "./chunk-VIBENDE3.js";
21
- import "./chunk-4UER2AKI.js";
22
- import "./chunk-QG2FJ3NR.js";
23
- import "./chunk-KOULRCYJ.js";
24
- import "./chunk-J6CYFWSW.js";
21
+ import "./chunk-ZPFOP557.js";
22
+ import "./chunk-5OZEJQBH.js";
23
+ import "./chunk-HMGYFENJ.js";
24
+ import "./chunk-VDQTNA4W.js";
25
25
  import "./chunk-E72U7WW7.js";
26
- import "./chunk-HIIYRATQ.js";
27
- import "./chunk-NKFKOEYX.js";
26
+ import "./chunk-ESAACKVG.js";
27
+ import "./chunk-WCMHJ6SS.js";
28
28
  import "./chunk-3AKXDMVS.js";
29
29
  import "./chunk-H3T4EF5F.js";
30
30
  import "./chunk-NSIKYD3X.js";
31
31
  import "./chunk-FRIMDSRU.js";
32
32
  import "./chunk-RBOQJFIZ.js";
33
- import "./chunk-KI7C6ZOD.js";
34
- import "./chunk-7TYK55JT.js";
35
- import "./chunk-J7ZE2JKP.js";
36
- import "./chunk-BOV4K7FP.js";
33
+ import "./chunk-VIJ7GDKI.js";
34
+ import "./chunk-BEDD7OFL.js";
35
+ import "./chunk-6C32YAB5.js";
37
36
  import "./chunk-KTWV5JC5.js";
38
37
  import "./chunk-PGNALDEH.js";
39
- import "./chunk-UDQT5CWK.js";
38
+ import "./chunk-PI6T2AGS.js";
40
39
  import "./chunk-6SMM5CMP.js";
41
- import "./chunk-I3NTAIMF.js";
42
- import "./chunk-L2GU3PWU.js";
40
+ import "./chunk-6DBBXNEG.js";
41
+ import "./chunk-DEIYY6NI.js";
43
42
  import "./chunk-RDGM4RUE.js";
44
43
  import "./chunk-O7S3HYE6.js";
44
+ import "./chunk-OI5TZ37D.js";
45
45
  import "./chunk-IWUIOLMF.js";
46
- import "./chunk-MLUIOBKL.js";
47
- import "./chunk-LQTVYUT3.js";
48
- import "./chunk-K56D3X7S.js";
46
+ import "./chunk-7ZMDQZ22.js";
47
+ import "./chunk-OJTMM5CV.js";
48
+ import "./chunk-NWZ44SFI.js";
49
49
  import "./chunk-BFVPLGAC.js";
50
50
  import "./chunk-6USL33ZO.js";
51
51
  import "./chunk-4EIC5BCT.js";
52
52
  import "./chunk-AO4CXI37.js";
53
- import "./chunk-GDQQNPBP.js";
54
- import "./chunk-RMLTVKOY.js";
55
- import "./chunk-UT2TYK2A.js";
56
- import "./chunk-QLRTQHTR.js";
53
+ import "./chunk-6GXIGN5W.js";
54
+ import "./chunk-L4YVE3RG.js";
55
+ import "./chunk-TYTVAFGB.js";
56
+ import "./chunk-6JGRNES6.js";
57
57
  import "./chunk-ZJK25VFP.js";
58
58
  import "./chunk-5H7RRF7C.js";
59
59
  import "./chunk-4EP3TUFF.js";
60
- import "./chunk-EORRZP3F.js";
60
+ import "./chunk-WX2OTJXL.js";
61
61
  import "./chunk-QBCGAIU7.js";
62
62
  import "./chunk-K4FSYBSY.js";
63
63
  import "./chunk-3LT6OWQ2.js";
@@ -67,9 +67,9 @@ import "./chunk-OZMX3E35.js";
67
67
  import "./chunk-URNQUECO.js";
68
68
  import "./chunk-WV6YJGZR.js";
69
69
  import "./chunk-4T5DJW54.js";
70
- import "./chunk-SYBNJZEL.js";
71
- import "./chunk-OMZYPQVA.js";
72
- import "./chunk-APJIC2O5.js";
70
+ import "./chunk-HPMBSOQ4.js";
71
+ import "./chunk-UGYFQF6M.js";
72
+ import "./chunk-GTIZNO5O.js";
73
73
  import "./chunk-HAEU6OTS.js";
74
74
  import "./chunk-MVONSJEN.js";
75
75
  import "./chunk-LHHKPGLX.js";