@kenkaiiii/ggcoder 4.3.200 → 4.3.202

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 (94) hide show
  1. package/dist/core/compaction/compactor.d.ts +11 -0
  2. package/dist/core/compaction/compactor.d.ts.map +1 -1
  3. package/dist/core/compaction/compactor.js +14 -0
  4. package/dist/core/compaction/compactor.js.map +1 -1
  5. package/dist/core/compaction/compactor.test.js +12 -1
  6. package/dist/core/compaction/compactor.test.js.map +1 -1
  7. package/dist/system-prompt.d.ts.map +1 -1
  8. package/dist/system-prompt.js +4 -3
  9. package/dist/system-prompt.js.map +1 -1
  10. package/dist/system-prompt.test.js +7 -5
  11. package/dist/system-prompt.test.js.map +1 -1
  12. package/dist/tools/bash.d.ts.map +1 -1
  13. package/dist/tools/bash.js +1 -0
  14. package/dist/tools/bash.js.map +1 -1
  15. package/dist/tools/edit.d.ts.map +1 -1
  16. package/dist/tools/edit.js +1 -0
  17. package/dist/tools/edit.js.map +1 -1
  18. package/dist/tools/edit.test.js +4 -0
  19. package/dist/tools/edit.test.js.map +1 -1
  20. package/dist/tools/enter-plan.d.ts.map +1 -1
  21. package/dist/tools/enter-plan.js +1 -0
  22. package/dist/tools/enter-plan.js.map +1 -1
  23. package/dist/tools/exit-plan.d.ts.map +1 -1
  24. package/dist/tools/exit-plan.js +1 -0
  25. package/dist/tools/exit-plan.js.map +1 -1
  26. package/dist/tools/prompt-hints.d.ts.map +1 -1
  27. package/dist/tools/prompt-hints.js +4 -2
  28. package/dist/tools/prompt-hints.js.map +1 -1
  29. package/dist/tools/subagent.d.ts.map +1 -1
  30. package/dist/tools/subagent.js +2 -1
  31. package/dist/tools/subagent.js.map +1 -1
  32. package/dist/tools/tasks.d.ts.map +1 -1
  33. package/dist/tools/tasks.js +1 -0
  34. package/dist/tools/tasks.js.map +1 -1
  35. package/dist/tools/write.d.ts.map +1 -1
  36. package/dist/tools/write.js +1 -0
  37. package/dist/tools/write.js.map +1 -1
  38. package/dist/tools/write.test.js +4 -0
  39. package/dist/tools/write.test.js.map +1 -1
  40. package/dist/ui/App.d.ts +4 -0
  41. package/dist/ui/App.d.ts.map +1 -1
  42. package/dist/ui/App.js +22 -38
  43. package/dist/ui/App.js.map +1 -1
  44. package/dist/ui/components/ActivityIndicator.d.ts +9 -1
  45. package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
  46. package/dist/ui/components/ActivityIndicator.js +123 -35
  47. package/dist/ui/components/ActivityIndicator.js.map +1 -1
  48. package/dist/ui/components/AnimationContext.d.ts +8 -2
  49. package/dist/ui/components/AnimationContext.d.ts.map +1 -1
  50. package/dist/ui/components/AnimationContext.js +94 -16
  51. package/dist/ui/components/AnimationContext.js.map +1 -1
  52. package/dist/ui/components/CompactionNotice.d.ts +5 -1
  53. package/dist/ui/components/CompactionNotice.d.ts.map +1 -1
  54. package/dist/ui/components/CompactionNotice.js +4 -6
  55. package/dist/ui/components/CompactionNotice.js.map +1 -1
  56. package/dist/ui/components/Footer.d.ts.map +1 -1
  57. package/dist/ui/components/Footer.js +5 -6
  58. package/dist/ui/components/Footer.js.map +1 -1
  59. package/dist/ui/components/InputArea.d.ts.map +1 -1
  60. package/dist/ui/components/InputArea.js +29 -12
  61. package/dist/ui/components/InputArea.js.map +1 -1
  62. package/dist/ui/components/ServerToolExecution.d.ts +1 -0
  63. package/dist/ui/components/ServerToolExecution.d.ts.map +1 -1
  64. package/dist/ui/components/ServerToolExecution.js +21 -2
  65. package/dist/ui/components/ServerToolExecution.js.map +1 -1
  66. package/dist/ui/components/Spinner.d.ts +3 -1
  67. package/dist/ui/components/Spinner.d.ts.map +1 -1
  68. package/dist/ui/components/Spinner.js +10 -4
  69. package/dist/ui/components/Spinner.js.map +1 -1
  70. package/dist/ui/components/SubAgentPanel.d.ts.map +1 -1
  71. package/dist/ui/components/SubAgentPanel.js +3 -4
  72. package/dist/ui/components/SubAgentPanel.js.map +1 -1
  73. package/dist/ui/components/ToolExecution.d.ts +2 -0
  74. package/dist/ui/components/ToolExecution.d.ts.map +1 -1
  75. package/dist/ui/components/ToolExecution.js +24 -5
  76. package/dist/ui/components/ToolExecution.js.map +1 -1
  77. package/dist/ui/components/ToolGroupExecution.d.ts.map +1 -1
  78. package/dist/ui/components/ToolGroupExecution.js +23 -2
  79. package/dist/ui/components/ToolGroupExecution.js.map +1 -1
  80. package/dist/ui/components/ToolUseLoader.d.ts +4 -2
  81. package/dist/ui/components/ToolUseLoader.d.ts.map +1 -1
  82. package/dist/ui/components/ToolUseLoader.js +3 -3
  83. package/dist/ui/components/ToolUseLoader.js.map +1 -1
  84. package/dist/ui/components/index.d.ts +1 -1
  85. package/dist/ui/components/index.d.ts.map +1 -1
  86. package/dist/ui/components/index.js +1 -1
  87. package/dist/ui/components/index.js.map +1 -1
  88. package/dist/ui/hooks/useBlink.d.ts.map +1 -1
  89. package/dist/ui/hooks/useBlink.js +3 -4
  90. package/dist/ui/hooks/useBlink.js.map +1 -1
  91. package/dist/ui/render.d.ts.map +1 -1
  92. package/dist/ui/render.js +3 -2
  93. package/dist/ui/render.js.map +1 -1
  94. package/package.json +4 -4
package/dist/ui/App.js CHANGED
@@ -35,7 +35,6 @@ import { EyesOverlay } from "./components/EyesOverlay.js";
35
35
  import { ThemeSelector } from "./components/ThemeSelector.js";
36
36
  import { BackgroundTasksBar } from "./components/BackgroundTasksBar.js";
37
37
  import { useTheme, useSetTheme } from "./theme/theme.js";
38
- import { useAnimationTick, useAnimationActive, deriveFrame, } from "./components/AnimationContext.js";
39
38
  import { useTerminalTitle } from "./hooks/useTerminalTitle.js";
40
39
  import { getGitBranch } from "../utils/git.js";
41
40
  import { getModel, getContextWindow, getMaxThinkingLevel } from "../core/model-registry.js";
@@ -45,7 +44,7 @@ import { log } from "../core/logger.js";
45
44
  import { getPendingUpdate, startPeriodicUpdateCheck, stopPeriodicUpdateCheck, } from "../core/auto-update.js";
46
45
  import { generateSessionTitle } from "../utils/session-title.js";
47
46
  import { SettingsManager } from "../core/settings-manager.js";
48
- import { shouldCompact, compact } from "../core/compaction/compactor.js";
47
+ import { shouldCompact, compact, getCompactionReserveTokens, } from "../core/compaction/compactor.js";
49
48
  import { estimateConversationTokens } from "../core/compaction/token-estimator.js";
50
49
  import { PROMPT_COMMANDS, getPromptCommand } from "../core/prompt-commands.js";
51
50
  import { isFirstTimeSetup, markSetupAudited, getAnnouncedLanguages, markLanguagesAnnounced, } from "../core/setup-history.js";
@@ -93,6 +92,7 @@ function toErrorItem(err, id, contextPrefix) {
93
92
  }
94
93
  /** Tools that get aggregated into a single compact group when concurrent. */
95
94
  const AGGREGATABLE_TOOLS = new Set(["read", "grep", "find", "ls"]);
95
+ const RUNNING_INDICATOR_ANIMATION_MS = 1_200;
96
96
  /**
97
97
  * Cap memory by replacing old items with tiny tombstones. Ink's <Static>
98
98
  * tracks rendered items by array length — the array must never shrink, but
@@ -858,8 +858,7 @@ export function App(props) {
858
858
  return injectRepoMapContext(stripped);
859
859
  }
860
860
  const contextWindow = getContextWindow(currentModel, contextWindowOptions);
861
- const modelInfo = getModel(currentModel);
862
- const reserveTokens = (modelInfo?.maxOutputTokens ?? 0) + 5_000;
861
+ const reserveTokens = getCompactionReserveTokens(props.maxTokens);
863
862
  const tokensFresh = lastActualTokensTimestampRef.current > lastCompactionTimeRef.current;
864
863
  const actualTokens = lastActualTokensRef.current > 0 && tokensFresh ? lastActualTokensRef.current : undefined;
865
864
  if (shouldCompact(stripped, contextWindow, threshold, actualTokens, reserveTokens)) {
@@ -1058,6 +1057,8 @@ export function App(props) {
1058
1057
  }, []),
1059
1058
  onToolStart: useCallback((toolCallId, name, args) => {
1060
1059
  log("INFO", "tool", `Tool call started: ${name}`, { id: toolCallId });
1060
+ const startedAt = Date.now();
1061
+ const animateUntil = startedAt + RUNNING_INDICATOR_ANIMATION_MS;
1061
1062
  // Flush completed items (assistant text, finished tools) to Static
1062
1063
  // before adding tool UI. Keeping both in the live area makes it tall
1063
1064
  // and causes Ink's cursor math to clip the top.
@@ -1103,7 +1104,10 @@ export function App(props) {
1103
1104
  const next = [...prev];
1104
1105
  next[groupIdx] = {
1105
1106
  ...group,
1106
- tools: [...group.tools, { toolCallId, name, args, status: "running" }],
1107
+ tools: [
1108
+ ...group.tools,
1109
+ { toolCallId, name, args, status: "running", animateUntil },
1110
+ ],
1107
1111
  };
1108
1112
  return next;
1109
1113
  }
@@ -1111,7 +1115,7 @@ export function App(props) {
1111
1115
  ...prev,
1112
1116
  {
1113
1117
  kind: "tool_group",
1114
- tools: [{ toolCallId, name, args, status: "running" }],
1118
+ tools: [{ toolCallId, name, args, status: "running", animateUntil }],
1115
1119
  id: getId(),
1116
1120
  },
1117
1121
  ];
@@ -1120,7 +1124,7 @@ export function App(props) {
1120
1124
  else {
1121
1125
  setLiveItems((prev) => [
1122
1126
  ...prev,
1123
- { kind: "tool_start", toolCallId, name, args, id: getId() },
1127
+ { kind: "tool_start", toolCallId, name, args, id: getId(), startedAt, animateUntil },
1124
1128
  ]);
1125
1129
  }
1126
1130
  }, []),
@@ -1273,6 +1277,8 @@ export function App(props) {
1273
1277
  }, []),
1274
1278
  onServerToolCall: useCallback((id, name, input) => {
1275
1279
  log("INFO", "server_tool", `Server tool call: ${name}`, { id });
1280
+ const startedAt = Date.now();
1281
+ const animateUntil = startedAt + RUNNING_INDICATOR_ANIMATION_MS;
1276
1282
  // Flush completed items (including assistant text) to Static before
1277
1283
  // adding server tool UI — same rationale as onToolStart.
1278
1284
  setLiveItems((prev) => {
@@ -1287,7 +1293,8 @@ export function App(props) {
1287
1293
  serverToolCallId: id,
1288
1294
  name,
1289
1295
  input,
1290
- startedAt: Date.now(),
1296
+ startedAt,
1297
+ animateUntil,
1291
1298
  id: getId(),
1292
1299
  },
1293
1300
  ];
@@ -1660,12 +1667,6 @@ export function App(props) {
1660
1667
  setEyesCount(isEyesActive(props.cwd) ? journalCount({ status: "open" }, props.cwd) : undefined);
1661
1668
  }
1662
1669
  }, [agentLoop.isRunning, props.cwd]);
1663
- // Animated thinking border — derived from global animation tick
1664
- useAnimationActive();
1665
- const animTick = useAnimationTick();
1666
- const thinkingBorderFrame = agentLoop.activityPhase === "thinking"
1667
- ? deriveFrame(animTick, 1000, THINKING_BORDER_COLORS.length)
1668
- : 0;
1669
1670
  const handleSubmit = useCallback(async (input, inputImages = [], pasteInfo) => {
1670
1671
  const trimmed = input.trim();
1671
1672
  if (trimmed.startsWith("/")) {
@@ -2224,13 +2225,13 @@ export function App(props) {
2224
2225
  case "assistant":
2225
2226
  return (_jsx(AssistantMessage, { text: item.text, thinking: item.thinking, thinkingMs: item.thinkingMs, planMode: item.planMode }, item.id));
2226
2227
  case "tool_start":
2227
- return (_jsx(ToolExecution, { status: "running", name: item.name, args: item.args, progressOutput: item.progressOutput }, item.id));
2228
+ return (_jsx(ToolExecution, { status: "running", name: item.name, args: item.args, progressOutput: item.progressOutput, animateUntil: item.animateUntil }, item.id));
2228
2229
  case "tool_done":
2229
2230
  return (_jsx(ToolExecution, { status: "done", name: item.name, args: item.args, result: item.result, isError: item.isError, details: item.details }, item.id));
2230
2231
  case "tool_group":
2231
2232
  return _jsx(ToolGroupExecution, { tools: item.tools }, item.id);
2232
2233
  case "server_tool_start":
2233
- return (_jsx(ServerToolExecution, { status: "running", name: item.name, input: item.input, startedAt: item.startedAt }, item.id));
2234
+ return (_jsx(ServerToolExecution, { status: "running", name: item.name, input: item.input, startedAt: item.startedAt, animateUntil: item.animateUntil }, item.id));
2234
2235
  case "server_tool_done":
2235
2236
  return (_jsx(ServerToolExecution, { status: "done", name: item.name, input: item.input, durationMs: item.durationMs, resultType: item.resultType }, item.id));
2236
2237
  case "error": {
@@ -2244,30 +2245,15 @@ export function App(props) {
2244
2245
  case "plan_transition":
2245
2246
  return (_jsx(Box, { marginTop: 1, flexShrink: 1, children: _jsxs(Text, { color: theme.planPrimary, bold: true, wrap: "wrap", children: [item.active ? "● " : "● ", item.text] }) }, item.id));
2246
2247
  case "thinking_transition": {
2247
- // Borderless. While in liveItems the glyph color cycles through the
2248
- // shared TRANSITION_COLORS gradient (~500ms per color). Once the item
2249
- // flushes to <Static>, its last-rendered color sticks — re-renders
2250
- // don't propagate into scrollback. Cheap: the animation timer is
2251
- // already running for the activity indicator.
2252
- const glyphFrame = item.active
2253
- ? deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length)
2254
- : 0;
2255
- const glyphColor = item.active ? THINKING_BORDER_COLORS[glyphFrame] : theme.textDim;
2248
+ const glyphColor = item.active ? THINKING_BORDER_COLORS[0] : theme.textDim;
2256
2249
  return (_jsxs(Box, { marginTop: 1, flexShrink: 1, children: [_jsx(Text, { color: glyphColor, bold: true, children: "✻ " }), _jsx(Text, { color: item.active ? theme.accent : theme.textDim, bold: true, children: item.active ? "Thinking ON" : "Thinking OFF" })] }, item.id));
2257
2250
  }
2258
2251
  case "model_transition": {
2259
- // Same animated-gradient pattern as thinking_transition, distinct
2260
- // glyph (▸) and primary-blue model name so the two transitions read
2261
- // as related but different.
2262
- const glyphFrame = deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length);
2263
- const glyphColor = THINKING_BORDER_COLORS[glyphFrame];
2252
+ const glyphColor = THINKING_BORDER_COLORS[0];
2264
2253
  return (_jsxs(Box, { marginTop: 1, flexShrink: 1, children: [_jsx(Text, { color: glyphColor, bold: true, children: "▸ " }), _jsx(Text, { color: theme.textDim, children: "Switched to " }), _jsx(Text, { color: theme.primary, bold: true, children: item.modelName })] }, item.id));
2265
2254
  }
2266
2255
  case "theme_transition": {
2267
- // Same family as model/thinking transitions. The ◐ glyph (half-filled
2268
- // circle) reads as the light/dark dichotomy.
2269
- const glyphFrame = deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length);
2270
- const glyphColor = THINKING_BORDER_COLORS[glyphFrame];
2256
+ const glyphColor = THINKING_BORDER_COLORS[0];
2271
2257
  return (_jsxs(Box, { marginTop: 1, flexShrink: 1, children: [_jsx(Text, { color: glyphColor, bold: true, children: "◐ " }), _jsx(Text, { color: theme.textDim, children: "Theme switched to " }), _jsx(Text, { color: theme.primary, bold: true, children: item.themeName })] }, item.id));
2272
2258
  }
2273
2259
  case "plan_event": {
@@ -2293,7 +2279,7 @@ export function App(props) {
2293
2279
  ? ` (+${item.imageCount} image${item.imageCount > 1 ? "s" : ""})`
2294
2280
  : ""] })] }, item.id));
2295
2281
  case "compacting":
2296
- return _jsx(CompactionSpinner, {}, item.id);
2282
+ return _jsx(CompactionSpinner, { staticDisplay: true }, item.id);
2297
2283
  case "compacted":
2298
2284
  return (_jsx(CompactionDone, { originalCount: item.originalCount, newCount: item.newCount, tokensBefore: item.tokensBefore, tokensAfter: item.tokensAfter }, item.id));
2299
2285
  case "duration":
@@ -2694,9 +2680,7 @@ export function App(props) {
2694
2680
  log("ERROR", "error", errMsg);
2695
2681
  setLiveItems((prev) => [...prev, toErrorItem(err, getId())]);
2696
2682
  });
2697
- } })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, paddingRight: 1, children: [liveItems.map((item) => renderItem(item)), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: agentLoop.streamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, planMode: planMode })] }), agentLoop.isRunning && agentLoop.activityPhase !== "idle" ? (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: agentLoop.activityPhase === "thinking"
2698
- ? THINKING_BORDER_COLORS[thinkingBorderFrame]
2699
- : "transparent", paddingLeft: 1, paddingRight: 1, width: columns, children: _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), planMode: planMode, retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length }) })) : agentLoop.stallError ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: theme.warning, children: "⚠ API provider stream interrupted — retries exhausted." }), _jsx(Text, { color: theme.textDim, children: " Your conversation is preserved. Send a message to continue." })] })) : (doneStatus &&
2683
+ } })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, paddingRight: 1, children: [liveItems.map((item) => renderItem(item)), _jsx(StreamingArea, { isRunning: agentLoop.isRunning, streamingText: agentLoop.streamingText, streamingThinking: agentLoop.streamingThinking, thinkingMs: agentLoop.thinkingMs, planMode: planMode })] }), agentLoop.isRunning && agentLoop.activityPhase !== "idle" ? (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: agentLoop.activityPhase === "thinking" ? THINKING_BORDER_COLORS[0] : "transparent", paddingLeft: 1, paddingRight: 1, width: columns, children: _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), planMode: planMode, retryInfo: agentLoop.retryInfo, planDone: planSteps.filter((s) => s.completed).length, planTotal: planSteps.length, staticDisplay: true }) })) : agentLoop.stallError ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: theme.warning, children: "⚠ API provider stream interrupted — retries exhausted." }), _jsx(Text, { color: theme.textDim, children: " Your conversation is preserved. Send a message to continue." })] })) : (doneStatus &&
2700
2684
  !agentLoop.isRunning && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.success, children: ["✻ ", doneStatus.verb, " ", formatDuration(doneStatus.durationMs)] }) }))), agentLoop.queuedCount > 0 && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.accent, children: ["⏳ ", agentLoop.queuedCount, " message", agentLoop.queuedCount > 1 ? "s" : "", " queued"] }) })), _jsx(InputArea, { onSubmit: handleSubmit, onAbort: handleAbort, disabled: agentLoop.isRunning, isActive: !taskBarFocused && !overlay, onDownAtEnd: handleFocusTaskBar, onShiftTab: handleToggleThinking, onToggleTasks: () => {
2701
2685
  // While the agent is running, skip the screen-clear + staticKey
2702
2686
  // bump that would otherwise wipe the chat history from scrollback.