@kenkaiiii/ggcoder 4.3.215 → 4.3.217

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 (103) hide show
  1. package/dist/cli.d.ts +2 -1
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +17 -5
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +2 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +6 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/core/goal-controller.d.ts.map +1 -1
  10. package/dist/core/goal-controller.js +46 -1
  11. package/dist/core/goal-controller.js.map +1 -1
  12. package/dist/core/goal-controller.test.js +39 -0
  13. package/dist/core/goal-controller.test.js.map +1 -1
  14. package/dist/core/goal-store.d.ts +9 -0
  15. package/dist/core/goal-store.d.ts.map +1 -1
  16. package/dist/core/goal-store.js +24 -0
  17. package/dist/core/goal-store.js.map +1 -1
  18. package/dist/core/goal-store.test.js +10 -0
  19. package/dist/core/goal-store.test.js.map +1 -1
  20. package/dist/core/goal-worker.d.ts +2 -1
  21. package/dist/core/goal-worker.d.ts.map +1 -1
  22. package/dist/core/goal-worker.js +5 -0
  23. package/dist/core/goal-worker.js.map +1 -1
  24. package/dist/core/goal-worker.test.js +29 -0
  25. package/dist/core/goal-worker.test.js.map +1 -1
  26. package/dist/system-prompt.d.ts.map +1 -1
  27. package/dist/system-prompt.js +4 -0
  28. package/dist/system-prompt.js.map +1 -1
  29. package/dist/system-prompt.test.js +18 -0
  30. package/dist/system-prompt.test.js.map +1 -1
  31. package/dist/tools/goals.d.ts +9 -0
  32. package/dist/tools/goals.d.ts.map +1 -1
  33. package/dist/tools/goals.js +49 -1
  34. package/dist/tools/goals.js.map +1 -1
  35. package/dist/tools/goals.test.js +44 -21
  36. package/dist/tools/goals.test.js.map +1 -1
  37. package/dist/ui/App.d.ts +2 -6
  38. package/dist/ui/App.d.ts.map +1 -1
  39. package/dist/ui/App.js +89 -38
  40. package/dist/ui/App.js.map +1 -1
  41. package/dist/ui/chat-layout-pinning.test.js +19 -2
  42. package/dist/ui/chat-layout-pinning.test.js.map +1 -1
  43. package/dist/ui/components/AnimationContext.d.ts.map +1 -1
  44. package/dist/ui/components/AnimationContext.js +3 -5
  45. package/dist/ui/components/AnimationContext.js.map +1 -1
  46. package/dist/ui/components/AssistantMessage.test.js +12 -12
  47. package/dist/ui/components/AssistantMessage.test.js.map +1 -1
  48. package/dist/ui/components/CompactionNotice.js +2 -2
  49. package/dist/ui/components/CompactionNotice.js.map +1 -1
  50. package/dist/ui/components/Footer.d.ts +1 -0
  51. package/dist/ui/components/Footer.d.ts.map +1 -1
  52. package/dist/ui/components/Footer.js +5 -2
  53. package/dist/ui/components/Footer.js.map +1 -1
  54. package/dist/ui/components/ModelSelector.d.ts.map +1 -1
  55. package/dist/ui/components/ModelSelector.js +18 -18
  56. package/dist/ui/components/ModelSelector.js.map +1 -1
  57. package/dist/ui/components/ServerToolExecution.d.ts.map +1 -1
  58. package/dist/ui/components/ServerToolExecution.js +5 -23
  59. package/dist/ui/components/ServerToolExecution.js.map +1 -1
  60. package/dist/ui/components/SlashStyledSelectList.d.ts +15 -0
  61. package/dist/ui/components/SlashStyledSelectList.d.ts.map +1 -0
  62. package/dist/ui/components/SlashStyledSelectList.js +66 -0
  63. package/dist/ui/components/SlashStyledSelectList.js.map +1 -0
  64. package/dist/ui/components/SubAgentPanel.d.ts.map +1 -1
  65. package/dist/ui/components/SubAgentPanel.js +3 -2
  66. package/dist/ui/components/SubAgentPanel.js.map +1 -1
  67. package/dist/ui/components/ThemeSelector.js +2 -2
  68. package/dist/ui/components/ThemeSelector.js.map +1 -1
  69. package/dist/ui/components/ToolExecution.d.ts.map +1 -1
  70. package/dist/ui/components/ToolExecution.js +12 -30
  71. package/dist/ui/components/ToolExecution.js.map +1 -1
  72. package/dist/ui/components/ToolGroupExecution.d.ts.map +1 -1
  73. package/dist/ui/components/ToolGroupExecution.js +5 -24
  74. package/dist/ui/components/ToolGroupExecution.js.map +1 -1
  75. package/dist/ui/footer-status-layout.test.js +9 -1
  76. package/dist/ui/footer-status-layout.test.js.map +1 -1
  77. package/dist/ui/goal-events.d.ts +4 -0
  78. package/dist/ui/goal-events.d.ts.map +1 -1
  79. package/dist/ui/goal-events.js +19 -1
  80. package/dist/ui/goal-events.js.map +1 -1
  81. package/dist/ui/goal-events.test.js +13 -0
  82. package/dist/ui/goal-events.test.js.map +1 -1
  83. package/dist/ui/queued-message.test.js +18 -0
  84. package/dist/ui/queued-message.test.js.map +1 -1
  85. package/dist/ui/terminal-history.d.ts.map +1 -1
  86. package/dist/ui/terminal-history.js +80 -40
  87. package/dist/ui/terminal-history.js.map +1 -1
  88. package/dist/ui/terminal-history.test.js +53 -5
  89. package/dist/ui/terminal-history.test.js.map +1 -1
  90. package/dist/ui/thinking-level-cycle.test.d.ts +2 -0
  91. package/dist/ui/thinking-level-cycle.test.d.ts.map +1 -0
  92. package/dist/ui/thinking-level-cycle.test.js +19 -0
  93. package/dist/ui/thinking-level-cycle.test.js.map +1 -0
  94. package/dist/ui/tool-group-summary.d.ts.map +1 -1
  95. package/dist/ui/tool-group-summary.js +117 -8
  96. package/dist/ui/tool-group-summary.js.map +1 -1
  97. package/dist/ui/tool-group-summary.test.d.ts +2 -0
  98. package/dist/ui/tool-group-summary.test.d.ts.map +1 -0
  99. package/dist/ui/tool-group-summary.test.js +79 -0
  100. package/dist/ui/tool-group-summary.test.js.map +1 -0
  101. package/dist/ui/tui-history-parity.test.js +153 -40
  102. package/dist/ui/tui-history-parity.test.js.map +1 -1
  103. package/package.json +3 -3
package/dist/ui/App.js CHANGED
@@ -206,7 +206,30 @@ export function buildUserContentWithAttachments(text, inputImages, modelSupports
206
206
  return parts.length === 1 && parts[0].type === "text" ? parts[0].text : parts;
207
207
  }
208
208
  /** Tools that get aggregated into a single compact group when possible. */
209
- const AGGREGATABLE_TOOLS = new Set(["read", "grep", "find", "ls"]);
209
+ const AGGREGATABLE_TOOLS = new Set([
210
+ "read",
211
+ "grep",
212
+ "find",
213
+ "ls",
214
+ "mcp__kencode-search__searchCode",
215
+ "mcp__kencode-search__referenceSources",
216
+ "mcp__kencode-search__discoverRepos",
217
+ ]);
218
+ const OPENAI_GPT_THINKING_LEVELS = ["medium", "high", "xhigh"];
219
+ function isOpenAIGptModel(provider, model) {
220
+ return provider === "openai" && model.startsWith("gpt-");
221
+ }
222
+ export function getNextThinkingLevel(provider, model, current) {
223
+ if (!isOpenAIGptModel(provider, model)) {
224
+ return current ? undefined : getMaxThinkingLevel(model);
225
+ }
226
+ if (!current)
227
+ return "medium";
228
+ const index = OPENAI_GPT_THINKING_LEVELS.indexOf(current);
229
+ if (index === -1)
230
+ return "medium";
231
+ return OPENAI_GPT_THINKING_LEVELS[index + 1];
232
+ }
210
233
  const RUNNING_INDICATOR_ANIMATION_MS = 1_200;
211
234
  /**
212
235
  * Cap memory by replacing old finalized rows with tiny tombstones. The full
@@ -494,6 +517,19 @@ function isAgentSpacingKind(kind) {
494
517
  "server_tool_start",
495
518
  "server_tool_done",
496
519
  "subagent_group",
520
+ "info",
521
+ "error",
522
+ "stopped",
523
+ "plan_transition",
524
+ "goal_agent_transition",
525
+ "model_transition",
526
+ "theme_transition",
527
+ "plan_event",
528
+ "update_notice",
529
+ "compacting",
530
+ "compacted",
531
+ "style_pack",
532
+ "setup_hint",
497
533
  ].includes(kind);
498
534
  }
499
535
  function isToolBoundaryKind(kind) {
@@ -511,13 +547,7 @@ function isAgentSpacingItem(item) {
511
547
  return isAgentSpacingKind(item.kind);
512
548
  }
513
549
  export function shouldTopSpaceAfterPrintedAgentBoundary({ currentKind, previousLiveItem, lastPendingHistoryItem, lastHistoryItem, }) {
514
- const needsExternalSpacing = [
515
- "goal_progress",
516
- "tool_start",
517
- "tool_group",
518
- "assistant",
519
- "queued",
520
- ].includes(currentKind);
550
+ const needsExternalSpacing = isAgentSpacingKind(currentKind);
521
551
  if (!needsExternalSpacing)
522
552
  return false;
523
553
  if (previousLiveItem !== undefined)
@@ -611,12 +641,15 @@ export function partitionCompleted(items) {
611
641
  function normalizeAssistantText(text) {
612
642
  return stripDoneMarkers(text).trim();
613
643
  }
644
+ function isReasoningMarkerText(text) {
645
+ return /^(?:currentItem\?\.type\s*=+\s*)?["']?reasoning["']?$/u.test(text.trim());
646
+ }
614
647
  function isSameAssistantText(item, text) {
615
648
  return item.kind === "assistant" && normalizeAssistantText(item.text) === text;
616
649
  }
617
650
  export function pinStreamingTextBeforeToolBoundary({ items, visibleStreamingText, thinking, thinkingMs, makeId, }) {
618
651
  const text = normalizeAssistantText(visibleStreamingText);
619
- if (text.length === 0)
652
+ if (text.length === 0 || isReasoningMarkerText(text))
620
653
  return items;
621
654
  if (items.some((item) => item.kind === "assistant"))
622
655
  return items;
@@ -769,7 +802,7 @@ export function App(props) {
769
802
  const [currentProvider, setCurrentProvider] = useState(props.provider);
770
803
  const [currentTools, setCurrentTools] = useState(props.tools);
771
804
  const currentToolsRef = useRef(props.tools);
772
- const [thinkingEnabled, setThinkingEnabled] = useState(!!props.thinking);
805
+ const [thinkingLevel, setThinkingLevel] = useState(props.thinking);
773
806
  const [renderMarkdown, setRenderMarkdown] = useState(true);
774
807
  const messagesRef = useRef(props.sessionStore?.messages ?? props.messages);
775
808
  const repoMapInjectionEnabledRef = useRef(true);
@@ -915,11 +948,19 @@ export function App(props) {
915
948
  useEffect(() => {
916
949
  onRuntimeStateChange?.({ provider: currentProvider });
917
950
  }, [currentProvider, onRuntimeStateChange]);
951
+ useEffect(() => {
952
+ if (thinkingLevel && !isOpenAIGptModel(currentProvider, currentModel)) {
953
+ const maxLevel = getMaxThinkingLevel(currentModel);
954
+ if (thinkingLevel !== maxLevel) {
955
+ setThinkingLevel(maxLevel);
956
+ }
957
+ }
958
+ }, [currentProvider, currentModel, thinkingLevel]);
918
959
  useEffect(() => {
919
960
  onRuntimeStateChange?.({
920
- thinking: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined,
961
+ thinking: thinkingLevel,
921
962
  });
922
- }, [thinkingEnabled, currentModel, onRuntimeStateChange]);
963
+ }, [thinkingLevel, onRuntimeStateChange]);
923
964
  useEffect(() => {
924
965
  printHistoryItems(history);
925
966
  }, [history, printHistoryItems]);
@@ -1463,7 +1504,7 @@ export function App(props) {
1463
1504
  tools: currentTools,
1464
1505
  webSearch: props.webSearch,
1465
1506
  maxTokens: props.maxTokens,
1466
- thinking: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined,
1507
+ thinking: thinkingLevel,
1467
1508
  apiKey: activeApiKey,
1468
1509
  baseUrl: activeBaseUrl,
1469
1510
  accountId: activeAccountId,
@@ -2628,20 +2669,20 @@ export function App(props) {
2628
2669
  }
2629
2670
  }, [agentLoop, handleDoubleExit]);
2630
2671
  const handleToggleThinking = useCallback(() => {
2631
- setThinkingEnabled((prev) => {
2632
- const next = !prev;
2633
- log("INFO", "thinking", `Thinking ${next ? "enabled" : "disabled"}`);
2634
- setLiveItems((items) => [
2635
- ...items,
2636
- { kind: "thinking_transition", active: next, id: getId() },
2637
- ]);
2672
+ setThinkingLevel((prev) => {
2673
+ const next = getNextThinkingLevel(currentProvider, currentModel, prev);
2674
+ log("INFO", "thinking", next ? `Thinking ${next}` : "Thinking disabled");
2638
2675
  if (props.settingsFile) {
2639
2676
  const sm = new SettingsManager(props.settingsFile);
2640
- sm.load().then(() => sm.set("thinkingEnabled", next));
2677
+ void sm.load().then(async () => {
2678
+ await sm.set("thinkingEnabled", !!next);
2679
+ if (next)
2680
+ await sm.set("thinkingLevel", next);
2681
+ });
2641
2682
  }
2642
2683
  return next;
2643
2684
  });
2644
- }, [props.settingsFile]);
2685
+ }, [currentProvider, currentModel, props.settingsFile]);
2645
2686
  const handleModelSelect = useCallback((value) => {
2646
2687
  setOverlay(null);
2647
2688
  const colonIdx = value.indexOf(":");
@@ -2830,7 +2871,7 @@ export function App(props) {
2830
2871
  case "user":
2831
2872
  return (_jsx(UserMessage, { text: item.text, imageCount: item.imageCount, pasteInfo: item.pasteInfo }, item.id));
2832
2873
  case "goal":
2833
- return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.success, bold: true, children: "▶ " }), _jsx(Text, { color: theme.textDim, children: "Goal: " }), _jsx(Text, { color: theme.success, children: truncateGoalProgressText(item.title) }), item.workerId ? _jsxs(Text, { color: theme.textDim, children: [" \u00B7 worker ", item.workerId] }) : null] }) }, item.id));
2874
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.success, bold: true, children: "▶ " }), _jsx(Text, { color: theme.textDim, children: "Goal: " }), _jsx(Text, { color: theme.success, children: truncateGoalProgressText(item.title) }), item.workerId ? _jsxs(Text, { color: theme.textDim, children: [" \u00B7 worker ", item.workerId] }) : null] }) }, item.id));
2834
2875
  case "goal_progress": {
2835
2876
  const color = goalProgressColor(item, theme);
2836
2877
  const loaderStatus = goalProgressLoaderStatus(item);
@@ -2843,10 +2884,10 @@ export function App(props) {
2843
2884
  case "style_pack": {
2844
2885
  const names = item.added.map((id) => LANGUAGE_DISPLAY_NAMES[id]);
2845
2886
  const headerLabel = item.added.length > 1 ? "STYLE PACKS ACTIVE" : "STYLE PACK ACTIVE";
2846
- return (_jsxs(Box, { marginTop: 1, flexShrink: 1, flexDirection: "column", borderStyle: "round", borderColor: theme.language, paddingX: 1, children: [_jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.language, bold: true, children: "◆ " }), _jsx(Text, { color: theme.language, bold: true, children: headerLabel })] }), _jsx(Text, { color: theme.text, bold: true, wrap: "wrap", children: names.join(", ") }), item.showSetupHint && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.textMuted, children: "Tip: run " }), _jsx(Text, { color: theme.language, bold: true, children: "/setup" }), _jsx(Text, { color: theme.textMuted, children: " to audit this project against the active pack(s)" })] }) }))] }, item.id));
2887
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, flexShrink: 1, children: _jsxs(Box, { flexShrink: 1, flexDirection: "column", borderStyle: "round", borderColor: theme.language, paddingX: 1, children: [_jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.language, bold: true, children: "◆ " }), _jsx(Text, { color: theme.language, bold: true, children: headerLabel })] }), _jsx(Text, { color: theme.text, bold: true, wrap: "wrap", children: names.join(", ") }), item.showSetupHint && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.textMuted, children: "Tip: run " }), _jsx(Text, { color: theme.language, bold: true, children: "/setup" }), _jsx(Text, { color: theme.textMuted, children: " to audit this project against the active pack(s)" })] }) }))] }) }, item.id));
2847
2888
  }
2848
2889
  case "setup_hint":
2849
- return (_jsxs(Box, { marginTop: 1, flexShrink: 1, flexDirection: "column", borderStyle: "round", borderColor: theme.language, paddingX: 1, children: [_jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.language, bold: true, children: "◆ " }), _jsx(Text, { color: theme.language, bold: true, children: "NO STYLE PACKS DETECTED" })] }), _jsx(Text, { color: theme.textMuted, wrap: "wrap", children: "This directory has no recognized language manifest at its root." }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.textMuted, children: "Tip: run " }), _jsx(Text, { color: theme.language, bold: true, children: "/setup" }), _jsx(Text, { color: theme.textMuted, children: " to audit project hygiene or bootstrap a new project from scratch" })] }) })] }, item.id));
2890
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, flexShrink: 1, children: _jsxs(Box, { flexShrink: 1, flexDirection: "column", borderStyle: "round", borderColor: theme.language, paddingX: 1, children: [_jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.language, bold: true, children: "◆ " }), _jsx(Text, { color: theme.language, bold: true, children: "NO STYLE PACKS DETECTED" })] }), _jsx(Text, { color: theme.textMuted, wrap: "wrap", children: "This directory has no recognized language manifest at its root." }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.textMuted, children: "Tip: run " }), _jsx(Text, { color: theme.language, bold: true, children: "/setup" }), _jsx(Text, { color: theme.textMuted, children: " to audit project hygiene or bootstrap a new project from scratch" })] }) })] }) }, item.id));
2850
2891
  case "assistant":
2851
2892
  return (_jsx(AssistantMessage, { text: item.text, thinking: item.thinking, thinkingMs: item.thinkingMs, renderMarkdown: renderMarkdown, availableTerminalHeight: measuredLiveAreaRows, marginTop: assistantMarginTop }, item.id));
2852
2893
  case "tool_start":
@@ -2866,15 +2907,11 @@ export function App(props) {
2866
2907
  case "info":
2867
2908
  return renderStatusMessage(item.id, "○ ", item.text, theme.commandColor, { muted: true });
2868
2909
  case "update_notice":
2869
- return (_jsx(Box, { marginTop: 1, flexShrink: 1, borderStyle: "round", borderColor: theme.commandColor, paddingX: 1, children: _jsxs(Text, { color: theme.commandColor, bold: true, wrap: "wrap", children: ["✨ ", item.text] }) }, item.id));
2910
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, flexShrink: 1, children: _jsx(Box, { flexShrink: 1, borderStyle: "round", borderColor: theme.commandColor, paddingX: 1, children: _jsxs(Text, { color: theme.commandColor, bold: true, wrap: "wrap", children: ["✨ ", item.text] }) }) }, item.id));
2870
2911
  case "plan_transition":
2871
2912
  return renderStatusMessage(item.id, "● ", normalizeStatusText(item.text), theme.commandColor, { bold: true });
2872
2913
  case "goal_agent_transition":
2873
2914
  return renderStatusMessage(item.id, "● ", normalizeStatusText(item.text), theme.commandColor, { bold: true });
2874
- case "thinking_transition": {
2875
- const glyphColor = item.active ? theme.commandColor : theme.textDim;
2876
- return renderStatusMessage(item.id, "✻ ", item.active ? "Thinking ON" : "Thinking OFF", glyphColor, { bold: true, muted: !item.active });
2877
- }
2878
2915
  case "model_transition":
2879
2916
  return renderStatusMessage(item.id, "▸ ", _jsxs(_Fragment, { children: [_jsx(Text, { color: theme.textDim, children: "Switched to " }), _jsx(Text, { color: theme.commandColor, bold: true, children: item.modelName })] }), theme.commandColor, { bold: true });
2880
2917
  case "theme_transition":
@@ -2895,7 +2932,7 @@ export function App(props) {
2895
2932
  // gradient. Glyph `⊘` reads as "stop" without being alarming.
2896
2933
  return renderStatusMessage(item.id, "⊘ ", normalizeStatusText(item.text), theme.commandColor, { bold: true });
2897
2934
  case "step_done":
2898
- return (_jsx(Box, { marginTop: 1, flexShrink: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.success, bold: true, children: "✓ " }), _jsx(Text, { color: theme.success, bold: true, children: `Step ${item.stepNum} done` }), item.description ? (_jsx(Text, { color: theme.textDim, children: ` — ${item.description}` })) : null] }) }, item.id));
2935
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, flexShrink: 1, children: _jsxs(Text, { wrap: "wrap", children: [_jsx(Text, { color: theme.success, bold: true, children: "✓ " }), _jsx(Text, { color: theme.success, bold: true, children: `Step ${item.stepNum} done` }), item.description ? (_jsx(Text, { color: theme.textDim, children: ` — ${item.description}` })) : null] }) }, item.id));
2899
2936
  case "queued": {
2900
2937
  const suffix = item.imageCount
2901
2938
  ? ` (+${item.imageCount} image${item.imageCount > 1 ? "s" : ""})`
@@ -2907,7 +2944,7 @@ export function App(props) {
2907
2944
  case "compacted":
2908
2945
  return (_jsx(CompactionDone, { originalCount: item.originalCount, newCount: item.newCount, tokensBefore: item.tokensBefore, tokensAfter: item.tokensAfter }, item.id));
2909
2946
  case "duration":
2910
- return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.textDim, children: ["✻ ", item.verb, " ", formatDuration(item.durationMs)] }) }, item.id));
2947
+ return (_jsx(Box, { paddingLeft: 1, marginTop: 1, children: _jsxs(Text, { color: theme.textDim, children: ["✻ ", item.verb, " ", formatDuration(item.durationMs)] }) }, item.id));
2911
2948
  case "subagent_group":
2912
2949
  return withPrintedBoundarySpacing(_jsx(SubAgentPanel, { agents: item.agents, aborted: item.aborted }, item.id));
2913
2950
  }
@@ -3307,6 +3344,7 @@ export function App(props) {
3307
3344
  cwd: props.cwd,
3308
3345
  provider: currentProvider,
3309
3346
  model: currentModel,
3347
+ thinkingLevel,
3310
3348
  goalRunId: checkedRun.id,
3311
3349
  goalTaskId: decision.task.id,
3312
3350
  taskTitle: decision.task.title,
@@ -3350,6 +3388,7 @@ export function App(props) {
3350
3388
  props.cwd,
3351
3389
  currentProvider,
3352
3390
  currentModel,
3391
+ thinkingLevel,
3353
3392
  appendGoalProgress,
3354
3393
  clearGoalModeIfIdle,
3355
3394
  clearGoalStatusEntry,
@@ -3659,7 +3698,7 @@ export function App(props) {
3659
3698
  contextWindowOptions,
3660
3699
  cwd: displayedCwd,
3661
3700
  gitBranch,
3662
- thinkingLevel: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined,
3701
+ thinkingLevel,
3663
3702
  goalMode,
3664
3703
  });
3665
3704
  const chatControlsLayout = getChatControlsLayoutDecision({
@@ -3714,12 +3753,24 @@ export function App(props) {
3714
3753
  const shouldReserveStreamingSpacing = agentLoop.isRunning &&
3715
3754
  !hasLiveAssistantItem &&
3716
3755
  (visibleStreamingText.trim().length > 0 || liveItems.some(isAgentSpacingItem));
3756
+ const lastLiveItem = liveItems.at(-1);
3757
+ const lastPendingHistoryItem = pendingHistoryFlushRef.current.at(-1);
3758
+ const lastHistoryItem = history.at(-1);
3717
3759
  const shouldTopSpaceStreamingText = shouldTopSpaceStreamingAssistant({
3718
3760
  visibleStreamingText,
3719
- lastLiveItem: liveItems.at(-1),
3720
- lastPendingHistoryItem: pendingHistoryFlushRef.current.at(-1),
3721
- lastHistoryItem: history.at(-1),
3761
+ lastLiveItem,
3762
+ lastPendingHistoryItem,
3763
+ lastHistoryItem,
3722
3764
  });
3765
+ const visibleQueuedCount = liveItems.filter((item) => item.kind === "queued").length;
3766
+ const hiddenQueuedCount = Math.max(0, agentLoop.queuedCount - visibleQueuedCount);
3767
+ const shouldTopSpaceQueueIndicator = hiddenQueuedCount > 0 &&
3768
+ shouldTopSpaceAfterPrintedAgentBoundary({
3769
+ currentKind: "queued",
3770
+ previousLiveItem: lastLiveItem,
3771
+ lastPendingHistoryItem,
3772
+ lastHistoryItem,
3773
+ });
3723
3774
  return (_jsx(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: isGoalView ? (_jsx(GoalOverlay, { cwd: props.cwd, agentRunning: agentLoop.isRunning, autoExpandNewest: goalAutoExpand, onClose: () => {
3724
3775
  goalAutoExpandRef.current = false;
3725
3776
  setGoalAutoExpand(false);
@@ -3938,7 +3989,7 @@ export function App(props) {
3938
3989
  log("ERROR", "error", errMsg);
3939
3990
  setLiveItems((prev) => [...prev, toErrorItem(err, getId())]);
3940
3991
  });
3941
- } })) : (_jsxs(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: [_jsxs(Box, { flexDirection: "column", flexGrow: 0, flexShrink: 1, overflowY: "hidden", children: [liveItems.map((item, index, items) => renderItem(item, index, items)), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: visibleStreamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, reserveSpacing: shouldReserveStreamingSpacing, renderMarkdown: renderMarkdown, availableTerminalHeight: measuredLiveAreaRows, assistantMarginTop: shouldTopSpaceStreamingText ? 1 : 0, continuation: streamedAssistantFlushRef.current.flushedChars > 0 })] }), _jsxs(Box, { ref: mainControlsRef, flexDirection: "column", flexShrink: 0, flexGrow: 0, children: [agentLoop.queuedCount > 0 && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.warning, bold: true, children: "• " }), _jsxs(Text, { color: theme.textDim, children: [agentLoop.queuedCount, " message", agentLoop.queuedCount > 1 ? "s" : "", " queued"] })] })), _jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Box, { borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, borderColor: theme.textDim, width: columns, height: 0 }), _jsx(Box, { paddingLeft: 1, paddingRight: 1, width: columns, children: statusSlotVisible ? (activityVisible ? (_jsx(ActivityIndicator, { phase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, thinkingMs: agentLoop.thinkingMs, isThinking: agentLoop.isThinking, thinkingEnabled: thinkingEnabled, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, userMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length, staticDisplay: true })) : stallStatusVisible ? (_jsx(Text, { color: theme.warning, wrap: "truncate", children: "⚠ API provider stream interrupted — retries exhausted. Your conversation is preserved." })) : doneStatus ? (_jsxs(Text, { color: theme.success, children: ["✻ ", doneStatus.verb, " ", formatDuration(doneStatus.durationMs)] })) : (_jsxs(Text, { children: [_jsx(Text, { color: theme.commandColor, children: "⠿ " }), _jsx(Text, { color: theme.textDim, children: "Ready to go.." }), !renderMarkdown && (_jsx(Text, { color: theme.warning, children: " · raw markdown mode" }))] }))) : (_jsxs(Text, { children: [_jsx(Text, { color: theme.commandColor, children: "⠿ " }), _jsx(Text, { color: theme.textDim, children: "Ready to go.." })] })) })] }), _jsx(InputArea, { onSubmit: handleSubmit, onAbort: handleAbort, disabled: agentLoop.isRunning, isActive: !taskBarFocused && !overlay, onDownAtEnd: handleFocusTaskBar, onShiftTab: handleToggleThinking, onToggleGoal: () => {
3992
+ } })) : (_jsxs(Box, { flexDirection: "column", width: columns, flexShrink: 0, flexGrow: 0, children: [_jsxs(Box, { flexDirection: "column", flexGrow: 0, flexShrink: 1, overflowY: "hidden", children: [liveItems.map((item, index, items) => renderItem(item, index, items)), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: visibleStreamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, reserveSpacing: shouldReserveStreamingSpacing, renderMarkdown: renderMarkdown, availableTerminalHeight: measuredLiveAreaRows, assistantMarginTop: shouldTopSpaceStreamingText ? 1 : 0, continuation: streamedAssistantFlushRef.current.flushedChars > 0 })] }), _jsxs(Box, { ref: mainControlsRef, flexDirection: "column", flexShrink: 0, flexGrow: 0, children: [hiddenQueuedCount > 0 && (_jsxs(Box, { flexDirection: "row", paddingLeft: 1, marginTop: shouldTopSpaceQueueIndicator ? 2 : 1, flexShrink: 0, children: [_jsx(Box, { width: 2, flexShrink: 0, children: _jsx(Text, { color: theme.warning, bold: true, children: "• " }) }), _jsxs(Text, { color: theme.textDim, children: [hiddenQueuedCount, " message", hiddenQueuedCount > 1 ? "s" : "", " queued"] })] })), _jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Box, { borderStyle: "single", borderTop: true, borderBottom: false, borderLeft: false, borderRight: false, borderColor: theme.textDim, width: columns, height: 0 }), _jsx(Box, { paddingLeft: 1, paddingRight: 1, width: columns, children: statusSlotVisible ? (activityVisible ? (_jsx(ActivityIndicator, { phase: agentLoop.activityPhase, elapsedMs: agentLoop.elapsedMs, runStartRef: agentLoop.runStartRef, thinkingMs: agentLoop.thinkingMs, isThinking: agentLoop.isThinking, thinkingEnabled: !!thinkingLevel, tokenEstimate: agentLoop.streamedTokenEstimate, charCountRef: agentLoop.charCountRef, realTokensAccumRef: agentLoop.realTokensAccumRef, userMessage: lastUserMessage, activeToolNames: agentLoop.activeToolCalls.map((tc) => tc.name), retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length, staticDisplay: true })) : stallStatusVisible ? (_jsx(Text, { color: theme.warning, wrap: "truncate", children: "⚠ API provider stream interrupted — retries exhausted. Your conversation is preserved." })) : doneStatus ? (_jsxs(Text, { color: theme.success, children: ["✻ ", doneStatus.verb, " ", formatDuration(doneStatus.durationMs)] })) : (_jsxs(Text, { children: [_jsx(Text, { color: theme.commandColor, children: "⠿ " }), _jsx(Text, { color: theme.textDim, children: "Ready to go.." }), !renderMarkdown && (_jsx(Text, { color: theme.warning, children: " · raw markdown mode" }))] }))) : (_jsxs(Text, { children: [_jsx(Text, { color: theme.commandColor, children: "⠿ " }), _jsx(Text, { color: theme.textDim, children: "Ready to go.." })] })) })] }), _jsx(InputArea, { onSubmit: handleSubmit, onAbort: handleAbort, disabled: agentLoop.isRunning, isActive: !taskBarFocused && !overlay, onDownAtEnd: handleFocusTaskBar, onShiftTab: handleToggleThinking, onToggleGoal: () => {
3942
3993
  openOverlay("goal");
3943
3994
  }, onToggleSkills: () => {
3944
3995
  openOverlay("skills");
@@ -3946,7 +3997,7 @@ export function App(props) {
3946
3997
  openOverlay("pixel");
3947
3998
  }, onToggleMarkdown: () => {
3948
3999
  setRenderMarkdown((prev) => !prev);
3949
- }, cwd: props.cwd, commands: allCommands }), overlay === "model" ? (_jsx(ModelSelector, { onSelect: handleModelSelect, onCancel: () => setOverlay(null), loggedInProviders: props.loggedInProviders ?? [currentProvider], currentModel: currentModel, currentProvider: currentProvider })) : overlay === "theme" ? (_jsx(ThemeSelector, { onSelect: handleThemeSelect, onCancel: () => setOverlay(null), currentTheme: theme.name })) : (_jsxs(_Fragment, { children: [_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, contextWindowOptions: contextWindowOptions, cwd: displayedCwd, gitBranch: gitBranch, thinkingLevel: thinkingEnabled ? getMaxThinkingLevel(currentModel) : undefined, goalMode: goalMode, exitPending: exitPending, renderMarkdown: renderMarkdown }), !exitPending && _jsx(GoalStatusBar, { entries: goalStatusEntries })] })), (footerStatusLayout.hasBackgroundTasks || footerStatusLayout.hasUpdateNotice) && (_jsxs(Box, { flexDirection: footerStatusLayout.stack ? "column" : "row", width: columns, children: [footerStatusLayout.hasBackgroundTasks && (_jsx(BackgroundTasksBar, { tasks: bgTasks, focused: taskBarFocused, expanded: taskBarExpanded, selectedIndex: selectedTaskIndex, onExpand: handleTaskBarExpand, onCollapse: handleTaskBarCollapse, onKill: handleTaskKill, onExit: handleTaskBarExit, onNavigate: handleTaskNavigate, compact: footerStatusLayout.compactBackgroundTasks })), footerStatusLayout.hasUpdateNotice && (_jsx(Box, { paddingLeft: footerStatusLayout.stack || !footerStatusLayout.hasBackgroundTasks ? 1 : 2, paddingRight: 1, children: _jsx(Text, { color: theme.success, bold: true, wrap: "truncate", children: "\u2728 Update ready \u00B7 restart to apply" }) }))] }))] })] })) }));
4000
+ }, cwd: props.cwd, commands: allCommands }), overlay === "model" ? (_jsx(ModelSelector, { onSelect: handleModelSelect, onCancel: () => setOverlay(null), loggedInProviders: props.loggedInProviders ?? [currentProvider], currentModel: currentModel, currentProvider: currentProvider })) : overlay === "theme" ? (_jsx(ThemeSelector, { onSelect: handleThemeSelect, onCancel: () => setOverlay(null), currentTheme: theme.name })) : (_jsxs(_Fragment, { children: [_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, contextWindowOptions: contextWindowOptions, cwd: displayedCwd, gitBranch: gitBranch, thinkingLevel: thinkingLevel, goalMode: goalMode, exitPending: exitPending, renderMarkdown: renderMarkdown }), !exitPending && _jsx(GoalStatusBar, { entries: goalStatusEntries })] })), (footerStatusLayout.hasBackgroundTasks || footerStatusLayout.hasUpdateNotice) && (_jsxs(Box, { flexDirection: footerStatusLayout.stack ? "column" : "row", width: columns, children: [footerStatusLayout.hasBackgroundTasks && (_jsx(BackgroundTasksBar, { tasks: bgTasks, focused: taskBarFocused, expanded: taskBarExpanded, selectedIndex: selectedTaskIndex, onExpand: handleTaskBarExpand, onCollapse: handleTaskBarCollapse, onKill: handleTaskKill, onExit: handleTaskBarExit, onNavigate: handleTaskNavigate, compact: footerStatusLayout.compactBackgroundTasks })), footerStatusLayout.hasUpdateNotice && (_jsx(Box, { paddingLeft: footerStatusLayout.stack || !footerStatusLayout.hasBackgroundTasks ? 1 : 2, paddingRight: 1, children: _jsx(Text, { color: theme.success, bold: true, wrap: "truncate", children: "\u2728 Update ready \u00B7 restart to apply" }) }))] }))] })] })) }));
3950
4001
  }
3951
4002
  function formatRepoMapCommandOutput(enabled, markdown, refreshed) {
3952
4003
  const status = enabled ? "on" : "off";