@kenkaiiii/ggcoder 4.3.230 → 4.3.231

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 (182) hide show
  1. package/dist/core/goal-controller.d.ts +27 -6
  2. package/dist/core/goal-controller.d.ts.map +1 -1
  3. package/dist/core/goal-controller.js +246 -141
  4. package/dist/core/goal-controller.js.map +1 -1
  5. package/dist/core/goal-controller.test.js +210 -79
  6. package/dist/core/goal-controller.test.js.map +1 -1
  7. package/dist/core/goal-engine.d.ts +61 -0
  8. package/dist/core/goal-engine.d.ts.map +1 -0
  9. package/dist/core/goal-engine.js +123 -0
  10. package/dist/core/goal-engine.js.map +1 -0
  11. package/dist/core/goal-engine.test.d.ts +2 -0
  12. package/dist/core/goal-engine.test.d.ts.map +1 -0
  13. package/dist/core/goal-engine.test.js +295 -0
  14. package/dist/core/goal-engine.test.js.map +1 -0
  15. package/dist/core/goal-integration.d.ts +80 -0
  16. package/dist/core/goal-integration.d.ts.map +1 -0
  17. package/dist/core/goal-integration.js +296 -0
  18. package/dist/core/goal-integration.js.map +1 -0
  19. package/dist/core/goal-integration.test.d.ts +2 -0
  20. package/dist/core/goal-integration.test.d.ts.map +1 -0
  21. package/dist/core/goal-integration.test.js +369 -0
  22. package/dist/core/goal-integration.test.js.map +1 -0
  23. package/dist/core/goal-prerequisites.test.js +37 -1
  24. package/dist/core/goal-prerequisites.test.js.map +1 -1
  25. package/dist/core/goal-store.d.ts +80 -1
  26. package/dist/core/goal-store.d.ts.map +1 -1
  27. package/dist/core/goal-store.js +232 -65
  28. package/dist/core/goal-store.js.map +1 -1
  29. package/dist/core/goal-store.test.js +111 -2
  30. package/dist/core/goal-store.test.js.map +1 -1
  31. package/dist/core/goal-worker.d.ts.map +1 -1
  32. package/dist/core/goal-worker.js +55 -4
  33. package/dist/core/goal-worker.js.map +1 -1
  34. package/dist/core/goal-worker.test.js +75 -6
  35. package/dist/core/goal-worker.test.js.map +1 -1
  36. package/dist/core/goal-worktree.d.ts +55 -1
  37. package/dist/core/goal-worktree.d.ts.map +1 -1
  38. package/dist/core/goal-worktree.js +164 -1
  39. package/dist/core/goal-worktree.js.map +1 -1
  40. package/dist/core/goal-worktree.test.js +226 -4
  41. package/dist/core/goal-worktree.test.js.map +1 -1
  42. package/dist/system-prompt.d.ts.map +1 -1
  43. package/dist/system-prompt.js +9 -6
  44. package/dist/system-prompt.js.map +1 -1
  45. package/dist/system-prompt.test.js +1 -1
  46. package/dist/system-prompt.test.js.map +1 -1
  47. package/dist/tools/edit-diff.d.ts +17 -4
  48. package/dist/tools/edit-diff.d.ts.map +1 -1
  49. package/dist/tools/edit-diff.js +78 -16
  50. package/dist/tools/edit-diff.js.map +1 -1
  51. package/dist/tools/edit-diff.test.js +31 -1
  52. package/dist/tools/edit-diff.test.js.map +1 -1
  53. package/dist/tools/edit-robustness.test.d.ts +2 -0
  54. package/dist/tools/edit-robustness.test.d.ts.map +1 -0
  55. package/dist/tools/edit-robustness.test.js +415 -0
  56. package/dist/tools/edit-robustness.test.js.map +1 -0
  57. package/dist/tools/edit.d.ts.map +1 -1
  58. package/dist/tools/edit.js +15 -16
  59. package/dist/tools/edit.js.map +1 -1
  60. package/dist/tools/edit.test.js +23 -12
  61. package/dist/tools/edit.test.js.map +1 -1
  62. package/dist/tools/goals.d.ts +9 -1
  63. package/dist/tools/goals.d.ts.map +1 -1
  64. package/dist/tools/goals.js +78 -25
  65. package/dist/tools/goals.js.map +1 -1
  66. package/dist/tools/goals.test.js +142 -11
  67. package/dist/tools/goals.test.js.map +1 -1
  68. package/dist/ui/App.d.ts +9 -1
  69. package/dist/ui/App.d.ts.map +1 -1
  70. package/dist/ui/App.js +78 -16
  71. package/dist/ui/App.js.map +1 -1
  72. package/dist/ui/components/ChatLayout.d.ts +8 -1
  73. package/dist/ui/components/ChatLayout.d.ts.map +1 -1
  74. package/dist/ui/components/ChatLayout.js +4 -1
  75. package/dist/ui/components/ChatLayout.js.map +1 -1
  76. package/dist/ui/components/ChatScreen.d.ts +14 -1
  77. package/dist/ui/components/ChatScreen.d.ts.map +1 -1
  78. package/dist/ui/components/ChatScreen.js +3 -2
  79. package/dist/ui/components/ChatScreen.js.map +1 -1
  80. package/dist/ui/components/InputArea.d.ts +13 -1
  81. package/dist/ui/components/InputArea.d.ts.map +1 -1
  82. package/dist/ui/components/InputArea.js +96 -12
  83. package/dist/ui/components/InputArea.js.map +1 -1
  84. package/dist/ui/components/TranscriptViewport.d.ts +34 -0
  85. package/dist/ui/components/TranscriptViewport.d.ts.map +1 -0
  86. package/dist/ui/components/TranscriptViewport.js +45 -0
  87. package/dist/ui/components/TranscriptViewport.js.map +1 -0
  88. package/dist/ui/footer-jump-regression.test.d.ts +2 -0
  89. package/dist/ui/footer-jump-regression.test.d.ts.map +1 -0
  90. package/dist/ui/footer-jump-regression.test.js +167 -0
  91. package/dist/ui/footer-jump-regression.test.js.map +1 -0
  92. package/dist/ui/goal-events.d.ts +1 -1
  93. package/dist/ui/goal-events.d.ts.map +1 -1
  94. package/dist/ui/goal-events.js +2 -2
  95. package/dist/ui/goal-events.js.map +1 -1
  96. package/dist/ui/goal-events.test.js +2 -2
  97. package/dist/ui/goal-events.test.js.map +1 -1
  98. package/dist/ui/goal-lifecycle-orchestration.test.js +13 -97
  99. package/dist/ui/goal-lifecycle-orchestration.test.js.map +1 -1
  100. package/dist/ui/goal-progress.d.ts.map +1 -1
  101. package/dist/ui/goal-progress.js +0 -1
  102. package/dist/ui/goal-progress.js.map +1 -1
  103. package/dist/ui/goal-run-helpers.d.ts +0 -4
  104. package/dist/ui/goal-run-helpers.d.ts.map +1 -1
  105. package/dist/ui/goal-run-helpers.js +2 -21
  106. package/dist/ui/goal-run-helpers.js.map +1 -1
  107. package/dist/ui/hooks/useChatLayoutMeasurements.d.ts +8 -0
  108. package/dist/ui/hooks/useChatLayoutMeasurements.d.ts.map +1 -1
  109. package/dist/ui/hooks/useChatLayoutMeasurements.js +2 -0
  110. package/dist/ui/hooks/useChatLayoutMeasurements.js.map +1 -1
  111. package/dist/ui/hooks/useGoalOrchestration.d.ts +2 -1
  112. package/dist/ui/hooks/useGoalOrchestration.d.ts.map +1 -1
  113. package/dist/ui/hooks/useGoalOrchestration.js +198 -80
  114. package/dist/ui/hooks/useGoalOrchestration.js.map +1 -1
  115. package/dist/ui/hooks/useTerminalSize.d.ts +8 -1
  116. package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
  117. package/dist/ui/hooks/useTerminalSize.js +12 -2
  118. package/dist/ui/hooks/useTerminalSize.js.map +1 -1
  119. package/dist/ui/hooks/useTranscriptHistory.d.ts +1 -1
  120. package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -1
  121. package/dist/ui/hooks/useTranscriptHistory.js +23 -9
  122. package/dist/ui/hooks/useTranscriptHistory.js.map +1 -1
  123. package/dist/ui/hooks/useTranscriptHistory.test.d.ts +2 -0
  124. package/dist/ui/hooks/useTranscriptHistory.test.d.ts.map +1 -0
  125. package/dist/ui/hooks/useTranscriptHistory.test.js +61 -0
  126. package/dist/ui/hooks/useTranscriptHistory.test.js.map +1 -0
  127. package/dist/ui/hooks/useTranscriptScroll.d.ts +30 -0
  128. package/dist/ui/hooks/useTranscriptScroll.d.ts.map +1 -0
  129. package/dist/ui/hooks/useTranscriptScroll.js +44 -0
  130. package/dist/ui/hooks/useTranscriptScroll.js.map +1 -0
  131. package/dist/ui/hooks/useTranscriptScroll.test.d.ts +2 -0
  132. package/dist/ui/hooks/useTranscriptScroll.test.d.ts.map +1 -0
  133. package/dist/ui/hooks/useTranscriptScroll.test.js +119 -0
  134. package/dist/ui/hooks/useTranscriptScroll.test.js.map +1 -0
  135. package/dist/ui/live-area-clamp.test.js +11 -2
  136. package/dist/ui/live-area-clamp.test.js.map +1 -1
  137. package/dist/ui/render.d.ts +8 -0
  138. package/dist/ui/render.d.ts.map +1 -1
  139. package/dist/ui/render.js +69 -7
  140. package/dist/ui/render.js.map +1 -1
  141. package/dist/ui/stores/transcript-scroll-store.d.ts +27 -0
  142. package/dist/ui/stores/transcript-scroll-store.d.ts.map +1 -0
  143. package/dist/ui/stores/transcript-scroll-store.js +73 -0
  144. package/dist/ui/stores/transcript-scroll-store.js.map +1 -0
  145. package/dist/ui/stores/transcript-scroll-store.test.d.ts +2 -0
  146. package/dist/ui/stores/transcript-scroll-store.test.d.ts.map +1 -0
  147. package/dist/ui/stores/transcript-scroll-store.test.js +73 -0
  148. package/dist/ui/stores/transcript-scroll-store.test.js.map +1 -0
  149. package/dist/ui/testing/screen-recorder.d.ts +29 -0
  150. package/dist/ui/testing/screen-recorder.d.ts.map +1 -0
  151. package/dist/ui/testing/screen-recorder.js +179 -0
  152. package/dist/ui/testing/screen-recorder.js.map +1 -0
  153. package/dist/ui/transcript/TranscriptRenderer.d.ts.map +1 -1
  154. package/dist/ui/transcript/TranscriptRenderer.js +1 -1
  155. package/dist/ui/transcript/TranscriptRenderer.js.map +1 -1
  156. package/dist/ui/transcript/spacing.d.ts +1 -0
  157. package/dist/ui/transcript/spacing.d.ts.map +1 -1
  158. package/dist/ui/transcript/spacing.js +7 -0
  159. package/dist/ui/transcript/spacing.js.map +1 -1
  160. package/dist/ui/transcript/spacing.test.js +29 -0
  161. package/dist/ui/transcript/spacing.test.js.map +1 -1
  162. package/dist/ui/transcript/transcript-lines.d.ts +32 -0
  163. package/dist/ui/transcript/transcript-lines.d.ts.map +1 -0
  164. package/dist/ui/transcript/transcript-lines.js +82 -0
  165. package/dist/ui/transcript/transcript-lines.js.map +1 -0
  166. package/dist/ui/transcript/transcript-lines.test.d.ts +2 -0
  167. package/dist/ui/transcript/transcript-lines.test.d.ts.map +1 -0
  168. package/dist/ui/transcript/transcript-lines.test.js +76 -0
  169. package/dist/ui/transcript/transcript-lines.test.js.map +1 -0
  170. package/dist/ui/transcript-viewport-pinning.test.d.ts +2 -0
  171. package/dist/ui/transcript-viewport-pinning.test.d.ts.map +1 -0
  172. package/dist/ui/transcript-viewport-pinning.test.js +148 -0
  173. package/dist/ui/transcript-viewport-pinning.test.js.map +1 -0
  174. package/dist/ui/tui-simulation.test.d.ts +2 -0
  175. package/dist/ui/tui-simulation.test.d.ts.map +1 -0
  176. package/dist/ui/tui-simulation.test.js +138 -0
  177. package/dist/ui/tui-simulation.test.js.map +1 -0
  178. package/dist/ui/tui-terminal-recorder.test.d.ts +2 -0
  179. package/dist/ui/tui-terminal-recorder.test.d.ts.map +1 -0
  180. package/dist/ui/tui-terminal-recorder.test.js +134 -0
  181. package/dist/ui/tui-terminal-recorder.test.js.map +1 -0
  182. package/package.json +5 -5
package/dist/ui/App.d.ts CHANGED
@@ -20,7 +20,7 @@ export { getNextThinkingLevel } from "./thinking-level.js";
20
20
  export { appendGoalProgressDraft, completedItemsWithDurableGoalTerminalProgress, formatGoalTerminalProgress, getGoalContinuationChoiceKey, routeGoalSyntheticEvent, truncateGoalProgressText, } from "./goal-progress.js";
21
21
  export { getChatControlsLayoutDecision, getDoneFlushDecision, getGoalActivationPaneTransition, getGoalSetupFinishedPaneTransition, getGoalSetupPaneTransitionAfterRun, getScrollStabilizationDecision, getStaticHistoryKey, hasParagraphBreakLiveUserMessage, isTallLiveUserMessage, nextGoalModeAfterAgentDone, shouldHideHistoryForOverlayView, shouldHideStaticItemsForOverlayView, shouldResetUIForGoalSetupPaneTransition, shouldStabilizeOverlayPaneRerender, shouldTopSpaceAfterPrintedAgentBoundary, shouldTopSpaceAssistantAfterToolBoundary, shouldTopSpaceStreamingAssistant, } from "./layout-decisions.js";
22
22
  export { getNextGeneratedItemId, isActiveItem, partitionCompleted, pinStreamingTextBeforeToolBoundary, } from "./item-helpers.js";
23
- export { buildGoalDirtyWorktreePauseRun, buildGoalDirtyWorktreeUserPrompt, buildGoalUserPauseRun, goalDirtyWorktreeInfoText, goalRunNeedsExplicitContinuationAfterWorker, shouldKeepGoalRunTrackedAfterDecision, shouldRunGoalTaskInMainCheckout, } from "./goal-run-helpers.js";
23
+ export { buildGoalUserPauseRun, goalRunNeedsExplicitContinuationAfterWorker, shouldKeepGoalRunTrackedAfterDecision, shouldRunGoalTaskInMainCheckout, } from "./goal-run-helpers.js";
24
24
  export interface AppProps {
25
25
  provider: Provider;
26
26
  model: string;
@@ -72,6 +72,14 @@ export interface AppProps {
72
72
  onExitPlan?: (planPath: string) => Promise<string>;
73
73
  };
74
74
  terminalHistoryPrinter?: TerminalHistoryPrinter;
75
+ /**
76
+ * When true, the UI runs in the alternate-screen fullscreen viewport: the
77
+ * transcript is rendered inside Ink as a bounded, app-scrolled region above a
78
+ * pinned controls region, and nothing is written to native scrollback. This
79
+ * is what keeps the footer a truly fixed bottom region. Defaults off (legacy
80
+ * scrollback path) for non-TTY / CI / print modes.
81
+ */
82
+ fullscreen?: boolean;
75
83
  /**
76
84
  * Wired by `renderApp`. Tears down the current Ink instance and renders
77
85
  * a fresh one. Patching Ink's internal frame tracking in place is
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"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"}
package/dist/ui/App.js CHANGED
@@ -52,6 +52,9 @@ import { getNextThinkingLevel, isThinkingLevelSupported } from "./thinking-level
52
52
  import { appendGoalProgressDraft, completedItemsWithDurableGoalTerminalProgress, } from "./goal-progress.js";
53
53
  import { getDoneFlushDecision, nextGoalModeAfterAgentDone, shouldTopSpaceAfterPrintedAgentBoundary, shouldTopSpaceStreamingAssistant, } from "./layout-decisions.js";
54
54
  import { isTranscriptSpacingItem } from "./transcript/spacing.js";
55
+ import { buildTranscriptLines } from "./transcript/transcript-lines.js";
56
+ import { useTranscriptScroll } from "./hooks/useTranscriptScroll.js";
57
+ import { scrollTranscriptByLines } from "./stores/transcript-scroll-store.js";
55
58
  import { renderTranscriptItem } from "./transcript/TranscriptRenderer.js";
56
59
  import { formatDuration } from "./duration-format.js";
57
60
  import { pickDurationVerb } from "./duration-summary.js";
@@ -63,7 +66,7 @@ export { getNextThinkingLevel } from "./thinking-level.js";
63
66
  export { appendGoalProgressDraft, completedItemsWithDurableGoalTerminalProgress, formatGoalTerminalProgress, getGoalContinuationChoiceKey, routeGoalSyntheticEvent, truncateGoalProgressText, } from "./goal-progress.js";
64
67
  export { getChatControlsLayoutDecision, getDoneFlushDecision, getGoalActivationPaneTransition, getGoalSetupFinishedPaneTransition, getGoalSetupPaneTransitionAfterRun, getScrollStabilizationDecision, getStaticHistoryKey, hasParagraphBreakLiveUserMessage, isTallLiveUserMessage, nextGoalModeAfterAgentDone, shouldHideHistoryForOverlayView, shouldHideStaticItemsForOverlayView, shouldResetUIForGoalSetupPaneTransition, shouldStabilizeOverlayPaneRerender, shouldTopSpaceAfterPrintedAgentBoundary, shouldTopSpaceAssistantAfterToolBoundary, shouldTopSpaceStreamingAssistant, } from "./layout-decisions.js";
65
68
  export { getNextGeneratedItemId, isActiveItem, partitionCompleted, pinStreamingTextBeforeToolBoundary, } from "./item-helpers.js";
66
- export { buildGoalDirtyWorktreePauseRun, buildGoalDirtyWorktreeUserPrompt, buildGoalUserPauseRun, goalDirtyWorktreeInfoText, goalRunNeedsExplicitContinuationAfterWorker, shouldKeepGoalRunTrackedAfterDecision, shouldRunGoalTaskInMainCheckout, } from "./goal-run-helpers.js";
69
+ export { buildGoalUserPauseRun, goalRunNeedsExplicitContinuationAfterWorker, shouldKeepGoalRunTrackedAfterDecision, shouldRunGoalTaskInMainCheckout, } from "./goal-run-helpers.js";
67
70
  /** Tools that get aggregated into a single compact group when possible. */
68
71
  const AGGREGATABLE_TOOLS = new Set([
69
72
  "read",
@@ -100,6 +103,9 @@ export function App(props) {
100
103
  const { columns, rows } = useTerminalSize();
101
104
  // Hoisted before terminal title hook so it can reference them
102
105
  const [lastUserMessage, setLastUserMessage] = useState("");
106
+ // Bumped on every prompt submit; the fullscreen transcript scroll controller
107
+ // watches this to snap back to the bottom so the newest output is visible.
108
+ const [scrollResetToken, setScrollResetToken] = useState(0);
103
109
  const [exitPending, setExitPending] = useState(false);
104
110
  const [quittingSummary, setQuittingSummary] = useState(null);
105
111
  // Terminal title — updated later after agentLoop is created
@@ -271,7 +277,12 @@ export function App(props) {
271
277
  queuedGoalSyntheticEventsRef,
272
278
  });
273
279
  const { pendingHistoryFlushRef, streamedAssistantFlushRef, queueFlush, finalizeSubmittedUserItem, clearPendingHistory, } = useTranscriptHistory({
274
- terminalHistoryPrinter: props.terminalHistoryPrinter,
280
+ // In fullscreen alt-screen mode the transcript renders inside Ink (the
281
+ // viewport), so we must NOT write completed rows to native scrollback —
282
+ // doing so would scroll the live frame. Dropping the printer keeps history
283
+ // accumulating in React state (still flushed + persisted) without any
284
+ // stdout writes. The legacy scrollback path keeps the printer.
285
+ terminalHistoryPrinter: props.fullscreen ? undefined : props.terminalHistoryPrinter,
275
286
  terminalHistoryContext: {
276
287
  theme,
277
288
  columns,
@@ -1155,15 +1166,14 @@ export function App(props) {
1155
1166
  setDoneStatus({ durationMs, toolsUsed, verb: pickDurationVerb(toolsUsed) });
1156
1167
  playNotificationSound();
1157
1168
  }
1158
- // Finalize rows. Do NOT clear the live area here — keep the items
1159
- // mounted and let the flush drain effect write them to scrollback
1160
- // FIRST and only then remove them from the live area. Clearing live
1161
- // up front (return []) erases the rows a frame before the sink writes
1162
- // them back into scrollback, which makes each finalized item blink
1163
- // out and the TUI jump as the agent finishes. Write-then-clear keeps
1164
- // every row continuously on screen (live → scrollback), matching how
1165
- // Ink's <Static> moves a finalized item in a single atomic frame.
1166
- if (doneDecision.flushLiveItems) {
1169
+ // Keep the final assistant response mounted in the live frame after a
1170
+ // normal chat turn finishes. Moving a large final response to terminal
1171
+ // history at this moment writes many scrollback rows while the footer is
1172
+ // still mounted, which visibly pushes the input/footer upward. The final
1173
+ // response is flushed on the next submit before the new prompt is shown.
1174
+ // Non-chat overlay transitions still flush so setup/plan/goal output
1175
+ // does not vanish during remounts.
1176
+ if (doneDecision.flushLiveItems && !doneDecision.showDoneStatus) {
1167
1177
  setLiveItems((prev) => {
1168
1178
  if (prev.length > 0)
1169
1179
  queueFlush(prev);
@@ -1684,6 +1694,7 @@ export function App(props) {
1684
1694
  id: getId(),
1685
1695
  };
1686
1696
  setLastUserMessage(input);
1697
+ setScrollResetToken((token) => token + 1);
1687
1698
  setDoneStatus(null);
1688
1699
  // Clear stale plan progress if there's no active approved plan
1689
1700
  // (avoids lingering progress from a completed or abandoned plan run)
@@ -1691,7 +1702,7 @@ export function App(props) {
1691
1702
  planStepsRef.current = [];
1692
1703
  setPlanSteps([]);
1693
1704
  }
1694
- finalizeSubmittedUserItem(userItem);
1705
+ finalizeSubmittedUserItem(userItem, liveItems);
1695
1706
  // Open a per-turn checkpoint capturing the conversation position right
1696
1707
  // before this exchange, so /rewind can restore pre-turn code/chat state.
1697
1708
  if (props.checkpointStore) {
@@ -1724,6 +1735,7 @@ export function App(props) {
1724
1735
  compactConversation,
1725
1736
  currentModel,
1726
1737
  finalizeSubmittedUserItem,
1738
+ liveItems,
1727
1739
  props.cwd,
1728
1740
  props.onSlashCommand,
1729
1741
  props.resetUI,
@@ -1941,8 +1953,8 @@ export function App(props) {
1941
1953
  item,
1942
1954
  index,
1943
1955
  items,
1944
- pendingHistoryFlushLastItem: pendingHistoryFlushRef.current.at(-1),
1945
- historyLastItem: history.at(-1),
1956
+ pendingHistoryFlushLastItem: index === 0 ? pendingHistoryFlushRef.current.at(-1) : undefined,
1957
+ historyLastItem: index === 0 ? history.at(-1) : undefined,
1946
1958
  version: props.version,
1947
1959
  currentModel,
1948
1960
  currentProvider,
@@ -2052,7 +2064,7 @@ export function App(props) {
2052
2064
  });
2053
2065
  const isSkillsView = overlay === "skills";
2054
2066
  const isPlanView = overlay === "plan";
2055
- const { footerStatusLayout, activityVisible, stallStatusVisible, statusSlotVisible, mainControlsRef, measuredLiveAreaRows, } = useChatLayoutMeasurements({
2067
+ const { footerStatusLayout, activityVisible, stallStatusVisible, statusSlotVisible, mainControlsRef, measuredLiveAreaRows, viewportRows, } = useChatLayoutMeasurements({
2056
2068
  rows,
2057
2069
  columns,
2058
2070
  backgroundTaskCount: bgTasks.length,
@@ -2129,6 +2141,54 @@ export function App(props) {
2129
2141
  // mid-stream, the live remainder is the next paragraph — re-insert the blank
2130
2142
  // line that separated them so the live tail lines up with the flushed history.
2131
2143
  const streamingContinuesFlushed = streamedAssistantFlushRef.current.flushedChars > 0;
2144
+ // ── Fullscreen alt-screen transcript ───────────────────
2145
+ // Flatten history + live items + in-flight streaming into the flat ANSI line
2146
+ // buffer the viewport renders. Reuses the same serializer the legacy
2147
+ // scrollback printer used, so the transcript looks identical. Only computed
2148
+ // when fullscreen is active (the legacy path renders items through Ink).
2149
+ const transcriptContext = useMemo(() => ({
2150
+ theme,
2151
+ columns,
2152
+ version: props.version,
2153
+ model: currentModel,
2154
+ provider: currentProvider,
2155
+ cwd: displayedCwd,
2156
+ }), [theme, columns, props.version, currentModel, currentProvider, displayedCwd]);
2157
+ const transcriptLines = useMemo(() => {
2158
+ if (!props.fullscreen)
2159
+ return [];
2160
+ const items = [...history, ...uniqueItemsById(liveItems)];
2161
+ const hasStreaming = visibleStreamingText.length > 0 || agentLoop.streamingThinking.length > 0;
2162
+ if (hasStreaming) {
2163
+ items.push({
2164
+ kind: "assistant",
2165
+ text: visibleStreamingText,
2166
+ thinking: agentLoop.streamingThinking,
2167
+ thinkingMs: agentLoop.thinkingMs,
2168
+ continuation: streamingContinuesFlushed,
2169
+ id: "__streaming__",
2170
+ });
2171
+ }
2172
+ return buildTranscriptLines(items, transcriptContext);
2173
+ }, [
2174
+ props.fullscreen,
2175
+ history,
2176
+ liveItems,
2177
+ visibleStreamingText,
2178
+ agentLoop.streamingThinking,
2179
+ agentLoop.thinkingMs,
2180
+ streamingContinuesFlushed,
2181
+ transcriptContext,
2182
+ ]);
2183
+ // Keyboard + bounds controller. The offset itself lives in the external
2184
+ // transcript-scroll store; the viewport subscribes to it directly so scroll
2185
+ // re-renders only the viewport, not this whole component.
2186
+ useTranscriptScroll({
2187
+ totalLines: transcriptLines.length,
2188
+ viewportRows,
2189
+ active: !!props.fullscreen && !overlay && !taskBarFocused,
2190
+ resetToken: scrollResetToken,
2191
+ });
2132
2192
  const visibleQueuedCount = liveItems.filter((item) => item.kind === "queued").length;
2133
2193
  const hiddenQueuedCount = Math.max(0, agentLoop.queuedCount - visibleQueuedCount);
2134
2194
  const shouldTopSpaceQueueIndicator = hiddenQueuedCount > 0 &&
@@ -2427,7 +2487,7 @@ export function App(props) {
2427
2487
  if (quittingSummary) {
2428
2488
  return (_jsx(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: _jsx(SessionSummaryDisplay, { summary: quittingSummary }) }));
2429
2489
  }
2430
- return (_jsx(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: rewindCheckpoints ? (_jsx(RewindOverlay, { checkpoints: rewindCheckpoints, onRestore: handleRewindRestore, onCancel: handleRewindCancel })) : fullScreenOverlay ? (_jsx(FullScreenOverlayRouter, { overlay: fullScreenOverlay, version: props.version, cwd: props.cwd, agentRunning: agentLoop.isRunning, planAutoExpand: planAutoExpand, onClosePixel: handleCloseRemountableOverlay, onPixelFixOne: handlePixelFixOne, onPixelFixAll: handlePixelFixAll, onCloseSkills: handleCloseRemountableOverlay, onClosePlan: handleClosePlanOverlay, onApprovePlan: handleApprovePlan, onRejectPlan: handleRejectPlan })) : (_jsx(ChatScreen, { columns: columns, liveItems: uniqueItemsById(liveItems), renderItem: renderItem, isRunning: agentLoop.isRunning, visibleStreamingText: visibleStreamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, reserveStreamingSpacing: shouldReserveStreamingSpacing, renderMarkdown: renderMarkdown, measuredLiveAreaRows: measuredLiveAreaRows, assistantMarginTop: shouldTopSpaceStreamingText || streamingContinuesFlushed ? 1 : 0, streamingContinuation: streamingContinuesFlushed, controlsRef: mainControlsRef, hiddenQueuedCount: hiddenQueuedCount, queueIndicatorMarginTop: shouldTopSpaceQueueIndicator ? 2 : 1, theme: theme, statusSlotVisible: statusSlotVisible, activityVisible: activityVisible, stallStatusVisible: stallStatusVisible, doneStatus: doneStatus, activityPhase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, isThinking: agentLoop.isThinking, thinkingLevel: thinkingLevel, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, lastUserMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length, formatDuration: formatDuration, inputControls: {
2490
+ return (_jsx(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: rewindCheckpoints ? (_jsx(RewindOverlay, { checkpoints: rewindCheckpoints, onRestore: handleRewindRestore, onCancel: handleRewindCancel })) : fullScreenOverlay ? (_jsx(FullScreenOverlayRouter, { overlay: fullScreenOverlay, version: props.version, cwd: props.cwd, agentRunning: agentLoop.isRunning, planAutoExpand: planAutoExpand, onClosePixel: handleCloseRemountableOverlay, onPixelFixOne: handlePixelFixOne, onPixelFixAll: handlePixelFixAll, onCloseSkills: handleCloseRemountableOverlay, onClosePlan: handleClosePlanOverlay, onApprovePlan: handleApprovePlan, onRejectPlan: handleRejectPlan })) : (_jsx(ChatScreen, { columns: columns, liveItems: uniqueItemsById(liveItems), renderItem: renderItem, isRunning: agentLoop.isRunning, visibleStreamingText: visibleStreamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, reserveStreamingSpacing: shouldReserveStreamingSpacing, renderMarkdown: renderMarkdown, measuredLiveAreaRows: measuredLiveAreaRows, fullscreen: props.fullscreen, rows: rows, transcriptLines: transcriptLines, viewportRows: viewportRows, assistantMarginTop: shouldTopSpaceStreamingText || streamingContinuesFlushed ? 1 : 0, streamingContinuation: streamingContinuesFlushed, controlsRef: mainControlsRef, hiddenQueuedCount: hiddenQueuedCount, queueIndicatorMarginTop: shouldTopSpaceQueueIndicator ? 2 : 1, theme: theme, statusSlotVisible: statusSlotVisible, activityVisible: activityVisible, stallStatusVisible: stallStatusVisible, doneStatus: doneStatus, activityPhase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, isThinking: agentLoop.isThinking, thinkingLevel: thinkingLevel, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, lastUserMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length, formatDuration: formatDuration, inputControls: {
2431
2491
  onSubmit: handleSubmit,
2432
2492
  onAbort: handleAbort,
2433
2493
  injectText: composerInject,
@@ -2441,6 +2501,8 @@ export function App(props) {
2441
2501
  onToggleMarkdown: () => setRenderMarkdown((prev) => !prev),
2442
2502
  cwd: props.cwd,
2443
2503
  commands: allCommands,
2504
+ mouseScroll: props.fullscreen,
2505
+ onScroll: scrollTranscriptByLines,
2444
2506
  }, taskPicker: {
2445
2507
  open: taskPicker.open,
2446
2508
  tasks: taskPicker.tasks,