@kenkaiiii/ggcoder 4.3.162 → 4.3.164
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.
- package/dist/cli.js +37 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +20 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/prompt-commands.js +4 -4
- package/dist/core/settings-manager.d.ts +0 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +0 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -14
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/style-packs/index.d.ts.map +1 -1
- package/dist/core/style-packs/index.js +20 -0
- package/dist/core/style-packs/index.js.map +1 -1
- package/dist/core/style-packs/packs.d.ts.map +1 -1
- package/dist/core/style-packs/packs.js +6 -5
- package/dist/core/style-packs/packs.js.map +1 -1
- package/dist/ui/App.d.ts +40 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +180 -70
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/hooks/useTerminalSize.d.ts +12 -3
- package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
- package/dist/ui/hooks/useTerminalSize.js +16 -1
- package/dist/ui/hooks/useTerminalSize.js.map +1 -1
- package/dist/ui/render.d.ts +42 -0
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +12 -1
- package/dist/ui/render.js.map +1 -1
- package/dist/utils/error-handler.d.ts.map +1 -1
- package/dist/utils/error-handler.js +2 -0
- package/dist/utils/error-handler.js.map +1 -1
- package/package.json +4 -4
package/dist/ui/App.js
CHANGED
|
@@ -54,7 +54,6 @@ import { detectVerifyCommands } from "../core/verify-commands.js";
|
|
|
54
54
|
import { extractPlanSteps, findCompletedMarkers, markStepsCompleted, segmentDisplayText, stripDoneMarkers, } from "../utils/plan-steps.js";
|
|
55
55
|
import { getMCPServers } from "../core/mcp/index.js";
|
|
56
56
|
import { trimFlushedItems, flushOnTurnText, flushOnTurnEnd, flushOverflow, } from "./live-item-flush.js";
|
|
57
|
-
import { Buddy } from "./buddy/Buddy.js";
|
|
58
57
|
// ── Provider Error Hints ──────────────────────────────────
|
|
59
58
|
/** Detect provider-side errors and return a user-facing hint. */
|
|
60
59
|
function getProviderErrorHint(message) {
|
|
@@ -320,10 +319,12 @@ export function App(props) {
|
|
|
320
319
|
const [taskCount, setTaskCount] = useState(() => getTaskCount(props.cwd));
|
|
321
320
|
const [eyesCount, setEyesCount] = useState(() => isEyesActive(props.cwd) ? journalCount({ status: "open" }, props.cwd) : undefined);
|
|
322
321
|
const [updatePending, setUpdatePending] = useState(() => getPendingUpdate(props.version) !== null);
|
|
323
|
-
|
|
324
|
-
|
|
322
|
+
// Seed from sessionStore so "Run All" chaining survives the resetUI()
|
|
323
|
+
// remount that startTask() triggers between tasks.
|
|
324
|
+
const [runAllTasks, setRunAllTasks] = useState(props.sessionStore?.runAllTasks ?? false);
|
|
325
|
+
const runAllTasksRef = useRef(props.sessionStore?.runAllTasks ?? false);
|
|
325
326
|
const startTaskRef = useRef(() => { });
|
|
326
|
-
const runAllPixelRef = useRef(false);
|
|
327
|
+
const runAllPixelRef = useRef(props.sessionStore?.runAllPixel ?? false);
|
|
327
328
|
const currentPixelFixRef = useRef(null);
|
|
328
329
|
const startPixelFixRef = useRef(() => { });
|
|
329
330
|
const cwdRef = useRef(props.cwd);
|
|
@@ -342,7 +343,22 @@ export function App(props) {
|
|
|
342
343
|
const approvedPlanPathRef = useRef(props.sessionStore?.approvedPlanPath);
|
|
343
344
|
const planStepsRef = useRef(props.sessionStore?.planSteps ?? []);
|
|
344
345
|
const [planSteps, setPlanSteps] = useState(props.sessionStore?.planSteps ?? []);
|
|
345
|
-
|
|
346
|
+
// Seed the per-item ID counter so it doesn't collide with IDs already in
|
|
347
|
+
// sessionStore.history (which survives remount). Without this, a remount
|
|
348
|
+
// (resize, overlay toggle, etc.) starts the counter at 0 and new items
|
|
349
|
+
// generate ids "0", "1", "2"… that collide with the same ids from the
|
|
350
|
+
// previous mount, triggering React's duplicate-key warning and causing
|
|
351
|
+
// duplicate/omitted renders.
|
|
352
|
+
const nextIdRef = useRef((() => {
|
|
353
|
+
const hist = props.sessionStore?.history ?? props.initialHistory ?? [];
|
|
354
|
+
let max = -1;
|
|
355
|
+
for (const item of hist) {
|
|
356
|
+
const n = Number(item.id);
|
|
357
|
+
if (Number.isFinite(n) && n > max)
|
|
358
|
+
max = n;
|
|
359
|
+
}
|
|
360
|
+
return max + 1;
|
|
361
|
+
})());
|
|
346
362
|
const sessionManagerRef = useRef(props.sessionsDir ? new SessionManager(props.sessionsDir) : null);
|
|
347
363
|
const sessionPathRef = useRef(props.sessionStore?.sessionPath ?? props.sessionPath);
|
|
348
364
|
const persistedIndexRef = useRef(messagesRef.current.length);
|
|
@@ -648,15 +664,13 @@ export function App(props) {
|
|
|
648
664
|
await applyLanguageDetectionRef.current("tool");
|
|
649
665
|
};
|
|
650
666
|
// ── Compaction ─────────────────────────────────────────
|
|
651
|
-
// Load settings for auto-compaction
|
|
667
|
+
// Load settings for auto-compaction
|
|
652
668
|
const settingsRef = useRef(null);
|
|
653
|
-
const [buddyEnabled, setBuddyEnabled] = useState(false);
|
|
654
669
|
useEffect(() => {
|
|
655
670
|
if (props.settingsFile) {
|
|
656
671
|
const sm = new SettingsManager(props.settingsFile);
|
|
657
672
|
sm.load().then(() => {
|
|
658
673
|
settingsRef.current = sm;
|
|
659
|
-
setBuddyEnabled(sm.get("buddyEnabled") ?? false);
|
|
660
674
|
});
|
|
661
675
|
}
|
|
662
676
|
}, [props.settingsFile]);
|
|
@@ -1367,7 +1381,7 @@ export function App(props) {
|
|
|
1367
1381
|
}
|
|
1368
1382
|
return item;
|
|
1369
1383
|
});
|
|
1370
|
-
return [...next, { kind: "
|
|
1384
|
+
return [...next, { kind: "stopped", text: "Request was stopped.", id: getId() }];
|
|
1371
1385
|
});
|
|
1372
1386
|
}, []),
|
|
1373
1387
|
onQueuedStart: useCallback((content) => {
|
|
@@ -1431,7 +1445,7 @@ export function App(props) {
|
|
|
1431
1445
|
setLiveItems((prev) => [
|
|
1432
1446
|
...prev,
|
|
1433
1447
|
isAbort
|
|
1434
|
-
? { kind: "
|
|
1448
|
+
? { kind: "stopped", text: "Auto-setup cancelled.", id: getId() }
|
|
1435
1449
|
: { kind: "error", message: msg, id: getId() },
|
|
1436
1450
|
]);
|
|
1437
1451
|
}
|
|
@@ -1454,6 +1468,29 @@ export function App(props) {
|
|
|
1454
1468
|
useEffect(() => {
|
|
1455
1469
|
setTitleRunning(agentLoop.isRunning);
|
|
1456
1470
|
}, [agentLoop.isRunning]);
|
|
1471
|
+
// Mirror agent running state into sessionStore so renderApp's resize
|
|
1472
|
+
// handler and overlay toggles can skip their unmount/remount while the
|
|
1473
|
+
// agent is in flight (unmounting fires useAgentLoop's cleanup which
|
|
1474
|
+
// aborts the in-flight request). On the running→idle transition,
|
|
1475
|
+
// consume any pendingResetUI flag set during the run by scheduling a
|
|
1476
|
+
// deferred resetUI to clean up accumulated log-update drift. The 100ms
|
|
1477
|
+
// setTimeout lets onDone's two-phase flush commit to sessionStore.history
|
|
1478
|
+
// first, so the chat isn't lost. The cleanup also bails if the user
|
|
1479
|
+
// started a new run before the timer fires, to avoid aborting it.
|
|
1480
|
+
useEffect(() => {
|
|
1481
|
+
if (!sessionStore)
|
|
1482
|
+
return;
|
|
1483
|
+
sessionStore.isAgentRunning = agentLoop.isRunning;
|
|
1484
|
+
if (!agentLoop.isRunning && sessionStore.pendingResetUI) {
|
|
1485
|
+
sessionStore.pendingResetUI = false;
|
|
1486
|
+
const timer = setTimeout(() => {
|
|
1487
|
+
if (sessionStore.isAgentRunning)
|
|
1488
|
+
return;
|
|
1489
|
+
props.resetUI?.();
|
|
1490
|
+
}, 100);
|
|
1491
|
+
return () => clearTimeout(timer);
|
|
1492
|
+
}
|
|
1493
|
+
}, [agentLoop.isRunning, sessionStore, props.resetUI]);
|
|
1457
1494
|
// Consume sessionStore.pendingAction once on mount. Set by resetUI options
|
|
1458
1495
|
// for paths that remount AND immediately drive the agent (plan accept,
|
|
1459
1496
|
// plan reject, startTask, pixel fix). The action survives the unmount
|
|
@@ -1467,7 +1504,14 @@ export function App(props) {
|
|
|
1467
1504
|
pendingActionConsumedRef.current = true;
|
|
1468
1505
|
if (sessionStore)
|
|
1469
1506
|
sessionStore.pendingAction = undefined;
|
|
1470
|
-
if (action.
|
|
1507
|
+
if (action.planEvent) {
|
|
1508
|
+
const ev = action.planEvent;
|
|
1509
|
+
setLiveItems((prev) => [
|
|
1510
|
+
...prev,
|
|
1511
|
+
{ kind: "plan_event", event: ev.event, detail: ev.detail, id: getId() },
|
|
1512
|
+
]);
|
|
1513
|
+
}
|
|
1514
|
+
else if (action.infoText) {
|
|
1471
1515
|
setLiveItems((prev) => [
|
|
1472
1516
|
...prev,
|
|
1473
1517
|
{ kind: "info", text: action.infoText, id: getId() },
|
|
@@ -1626,37 +1670,23 @@ export function App(props) {
|
|
|
1626
1670
|
messagesRef.current[0] = { role: "system", content: newPrompt };
|
|
1627
1671
|
}
|
|
1628
1672
|
})();
|
|
1629
|
-
setLiveItems([{ kind: "
|
|
1630
|
-
return;
|
|
1631
|
-
}
|
|
1632
|
-
// Handle /buddy — toggle companion
|
|
1633
|
-
if (trimmed === "/buddy") {
|
|
1634
|
-
const next = !buddyEnabled;
|
|
1635
|
-
setBuddyEnabled(next);
|
|
1636
|
-
if (settingsRef.current) {
|
|
1637
|
-
settingsRef.current.set("buddyEnabled", next);
|
|
1638
|
-
}
|
|
1639
|
-
setLiveItems((items) => [
|
|
1640
|
-
...items,
|
|
1641
|
-
{
|
|
1642
|
-
kind: "info",
|
|
1643
|
-
text: next
|
|
1644
|
-
? "Buddy enabled! Your companion will appear near the prompt."
|
|
1645
|
-
: "Buddy disabled.",
|
|
1646
|
-
id: getId(),
|
|
1647
|
-
},
|
|
1648
|
-
]);
|
|
1673
|
+
setLiveItems([{ kind: "plan_event", event: "dismissed", id: getId() }]);
|
|
1649
1674
|
return;
|
|
1650
1675
|
}
|
|
1651
1676
|
// Handle /plans — open plan pane
|
|
1652
1677
|
if (trimmed === "/plans") {
|
|
1653
|
-
if (props.resetUI && props.sessionStore) {
|
|
1678
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
1654
1679
|
props.sessionStore.overlay = "plan";
|
|
1655
1680
|
props.sessionStore.planAutoExpand = false;
|
|
1656
1681
|
props.resetUI();
|
|
1657
1682
|
}
|
|
1658
1683
|
else {
|
|
1659
|
-
|
|
1684
|
+
if (props.sessionStore) {
|
|
1685
|
+
props.sessionStore.overlay = "plan";
|
|
1686
|
+
props.sessionStore.planAutoExpand = false;
|
|
1687
|
+
if (agentLoop.isRunning)
|
|
1688
|
+
props.sessionStore.pendingResetUI = true;
|
|
1689
|
+
}
|
|
1660
1690
|
setPlanAutoExpand(false);
|
|
1661
1691
|
setOverlay("plan");
|
|
1662
1692
|
}
|
|
@@ -1698,7 +1728,7 @@ export function App(props) {
|
|
|
1698
1728
|
setLiveItems((prev) => [
|
|
1699
1729
|
...prev,
|
|
1700
1730
|
isAbort
|
|
1701
|
-
? { kind: "
|
|
1731
|
+
? { kind: "stopped", text: "Request was stopped.", id: getId() }
|
|
1702
1732
|
: { kind: "error", message: msg, id: getId() },
|
|
1703
1733
|
]);
|
|
1704
1734
|
}
|
|
@@ -1822,7 +1852,7 @@ export function App(props) {
|
|
|
1822
1852
|
setLiveItems((prev) => [
|
|
1823
1853
|
...prev,
|
|
1824
1854
|
isAbort
|
|
1825
|
-
? { kind: "
|
|
1855
|
+
? { kind: "stopped", text: "Request was stopped.", id: getId() }
|
|
1826
1856
|
: { kind: "error", message: msg, id: getId() },
|
|
1827
1857
|
]);
|
|
1828
1858
|
}
|
|
@@ -1843,7 +1873,7 @@ export function App(props) {
|
|
|
1843
1873
|
log("INFO", "thinking", `Thinking ${next ? "enabled" : "disabled"}`);
|
|
1844
1874
|
setLiveItems((items) => [
|
|
1845
1875
|
...items,
|
|
1846
|
-
{ kind: "
|
|
1876
|
+
{ kind: "thinking_transition", active: next, id: getId() },
|
|
1847
1877
|
]);
|
|
1848
1878
|
if (props.settingsFile) {
|
|
1849
1879
|
const sm = new SettingsManager(props.settingsFile);
|
|
@@ -1919,7 +1949,7 @@ export function App(props) {
|
|
|
1919
1949
|
const displayName = modelInfo?.name ?? newModelId;
|
|
1920
1950
|
setLiveItems((prev) => [
|
|
1921
1951
|
...prev,
|
|
1922
|
-
{ kind: "
|
|
1952
|
+
{ kind: "model_transition", modelName: displayName, id: getId() },
|
|
1923
1953
|
]);
|
|
1924
1954
|
// Persist model selection for next CLI launch
|
|
1925
1955
|
if (props.settingsFile) {
|
|
@@ -1940,10 +1970,7 @@ export function App(props) {
|
|
|
1940
1970
|
const sm = new SettingsManager(props.settingsFile);
|
|
1941
1971
|
sm.load().then(() => sm.set("theme", name));
|
|
1942
1972
|
}
|
|
1943
|
-
setLiveItems((prev) => [
|
|
1944
|
-
...prev,
|
|
1945
|
-
{ kind: "info", text: `Theme switched to: ${name}`, id: getId() },
|
|
1946
|
-
]);
|
|
1973
|
+
setLiveItems((prev) => [...prev, { kind: "theme_transition", themeName: name, id: getId() }]);
|
|
1947
1974
|
}, [switchTheme, props.settingsFile]);
|
|
1948
1975
|
// All available slash commands for the command palette — ordered by how
|
|
1949
1976
|
// commonly they're used and grouped by purpose; /quit stays dead last.
|
|
@@ -2032,6 +2059,49 @@ export function App(props) {
|
|
|
2032
2059
|
return (_jsx(Box, { marginTop: 1, flexShrink: 1, borderStyle: "round", borderColor: theme.success, paddingX: 1, children: _jsxs(Text, { color: theme.success, bold: true, wrap: "wrap", children: ["✨ ", item.text] }) }, item.id));
|
|
2033
2060
|
case "plan_transition":
|
|
2034
2061
|
return (_jsx(Box, { marginTop: 1, flexShrink: 1, children: _jsxs(Text, { color: theme.planPrimary, bold: true, wrap: "wrap", children: [item.active ? "● " : "● ", item.text] }) }, item.id));
|
|
2062
|
+
case "thinking_transition": {
|
|
2063
|
+
// Borderless. While in liveItems the glyph color cycles through the
|
|
2064
|
+
// shared TRANSITION_COLORS gradient (~500ms per color). Once the item
|
|
2065
|
+
// flushes to <Static>, its last-rendered color sticks — re-renders
|
|
2066
|
+
// don't propagate into scrollback. Cheap: the animation timer is
|
|
2067
|
+
// already running for the activity indicator.
|
|
2068
|
+
const glyphFrame = item.active
|
|
2069
|
+
? deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length)
|
|
2070
|
+
: 0;
|
|
2071
|
+
const glyphColor = item.active ? THINKING_BORDER_COLORS[glyphFrame] : theme.textDim;
|
|
2072
|
+
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));
|
|
2073
|
+
}
|
|
2074
|
+
case "model_transition": {
|
|
2075
|
+
// Same animated-gradient pattern as thinking_transition, distinct
|
|
2076
|
+
// glyph (▸) and primary-blue model name so the two transitions read
|
|
2077
|
+
// as related but different.
|
|
2078
|
+
const glyphFrame = deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length);
|
|
2079
|
+
const glyphColor = THINKING_BORDER_COLORS[glyphFrame];
|
|
2080
|
+
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));
|
|
2081
|
+
}
|
|
2082
|
+
case "theme_transition": {
|
|
2083
|
+
// Same family as model/thinking transitions. The ◐ glyph (half-filled
|
|
2084
|
+
// circle) reads as the light/dark dichotomy.
|
|
2085
|
+
const glyphFrame = deriveFrame(animTick, 500, THINKING_BORDER_COLORS.length);
|
|
2086
|
+
const glyphColor = THINKING_BORDER_COLORS[glyphFrame];
|
|
2087
|
+
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));
|
|
2088
|
+
}
|
|
2089
|
+
case "plan_event": {
|
|
2090
|
+
// Plan-domain status changes (approve / reject / dismiss). Uses
|
|
2091
|
+
// theme.planPrimary to match the existing plan_transition family,
|
|
2092
|
+
// distinct from the model/thinking gradient.
|
|
2093
|
+
const label = item.event === "approved"
|
|
2094
|
+
? "Plan approved"
|
|
2095
|
+
: item.event === "rejected"
|
|
2096
|
+
? "Plan rejected"
|
|
2097
|
+
: "Plan dismissed";
|
|
2098
|
+
return (_jsxs(Box, { marginTop: 1, flexShrink: 1, children: [_jsxs(Text, { color: theme.planPrimary, bold: true, children: ["○ ", label] }), item.detail ? _jsx(Text, { color: theme.textDim, children: ` — "${item.detail}"` }) : null] }, item.id));
|
|
2099
|
+
}
|
|
2100
|
+
case "stopped":
|
|
2101
|
+
// Cancellation / abort acknowledgement (ESC, auto-setup cancel, etc.).
|
|
2102
|
+
// Muted dim treatment — this is an ack, not a state change worth a
|
|
2103
|
+
// gradient. Glyph `⊘` reads as "stop" without being alarming.
|
|
2104
|
+
return (_jsx(Box, { marginTop: 1, flexShrink: 1, children: _jsxs(Text, { color: theme.textDim, bold: true, children: ["⊘ ", item.text] }) }, item.id));
|
|
2035
2105
|
case "step_done":
|
|
2036
2106
|
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));
|
|
2037
2107
|
case "queued":
|
|
@@ -2115,7 +2185,7 @@ export function App(props) {
|
|
|
2115
2185
|
setLiveItems((prev) => [
|
|
2116
2186
|
...prev,
|
|
2117
2187
|
isAbort
|
|
2118
|
-
? { kind: "
|
|
2188
|
+
? { kind: "stopped", text: "Request was stopped.", id: getId() }
|
|
2119
2189
|
: { kind: "error", message: msg, id: getId() },
|
|
2120
2190
|
]);
|
|
2121
2191
|
setRunAllTasks(false);
|
|
@@ -2134,7 +2204,9 @@ export function App(props) {
|
|
|
2134
2204
|
startTaskRef.current = startTask;
|
|
2135
2205
|
useEffect(() => {
|
|
2136
2206
|
runAllTasksRef.current = runAllTasks;
|
|
2137
|
-
|
|
2207
|
+
if (props.sessionStore)
|
|
2208
|
+
props.sessionStore.runAllTasks = runAllTasks;
|
|
2209
|
+
}, [runAllTasks, props.sessionStore]);
|
|
2138
2210
|
const startPixelFix = useCallback((errorId) => {
|
|
2139
2211
|
void (async () => {
|
|
2140
2212
|
try {
|
|
@@ -2210,25 +2282,32 @@ export function App(props) {
|
|
|
2210
2282
|
})();
|
|
2211
2283
|
}, [props.cwd, stdout, agentLoop, currentProvider, currentModel]);
|
|
2212
2284
|
startPixelFixRef.current = startPixelFix;
|
|
2213
|
-
|
|
2285
|
+
// Seed from sessionStore so "Fix All" chaining survives a deferred
|
|
2286
|
+
// resetUI() if it fires between pixel fixes (e.g. user toggled a pane).
|
|
2287
|
+
const [runAllPixel, setRunAllPixel] = useState(props.sessionStore?.runAllPixel ?? false);
|
|
2214
2288
|
useEffect(() => {
|
|
2215
2289
|
runAllPixelRef.current = runAllPixel;
|
|
2216
|
-
|
|
2290
|
+
if (props.sessionStore)
|
|
2291
|
+
props.sessionStore.runAllPixel = runAllPixel;
|
|
2292
|
+
}, [runAllPixel, props.sessionStore]);
|
|
2217
2293
|
const isTaskView = overlay === "tasks";
|
|
2218
2294
|
const isSkillsView = overlay === "skills";
|
|
2219
2295
|
const isPlanView = overlay === "plan";
|
|
2220
2296
|
const isEyesView = overlay === "eyes";
|
|
2221
2297
|
const isPixelView = overlay === "pixel";
|
|
2222
2298
|
const isOverlayView = isTaskView || isSkillsView || isPlanView || isEyesView || isPixelView;
|
|
2223
|
-
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Static, { items: isOverlayView ? [] : history, style: { width: "100%" }, children: (item) => (_jsx(Box, { flexDirection: "column", paddingRight: 1, children: renderItem(item) }, item.id)) }, `${resizeKey}-${staticKey}`), isTaskView ? (_jsx(TaskOverlay, { cwd: props.cwd, agentRunning: agentLoop.isRunning, onClose: () => {
|
|
2224
|
-
if (props.resetUI && props.sessionStore) {
|
|
2299
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Static, { items: isOverlayView && !agentLoop.isRunning ? [] : history, style: { width: "100%" }, children: (item) => (_jsx(Box, { flexDirection: "column", paddingRight: 1, children: renderItem(item) }, item.id)) }, `${resizeKey}-${staticKey}`), isTaskView ? (_jsx(TaskOverlay, { cwd: props.cwd, agentRunning: agentLoop.isRunning, onClose: () => {
|
|
2300
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2225
2301
|
props.sessionStore.overlay = null;
|
|
2226
2302
|
props.resetUI();
|
|
2227
2303
|
}
|
|
2228
2304
|
else {
|
|
2229
|
-
|
|
2305
|
+
if (props.sessionStore) {
|
|
2306
|
+
props.sessionStore.overlay = null;
|
|
2307
|
+
if (agentLoop.isRunning)
|
|
2308
|
+
props.sessionStore.pendingResetUI = true;
|
|
2309
|
+
}
|
|
2230
2310
|
setTaskCount(getTaskCount(props.cwd));
|
|
2231
|
-
setStaticKey((k) => k + 1);
|
|
2232
2311
|
setOverlay(null);
|
|
2233
2312
|
}
|
|
2234
2313
|
}, onWorkOnTask: (title, prompt, taskId) => {
|
|
@@ -2243,13 +2322,16 @@ export function App(props) {
|
|
|
2243
2322
|
startTask(next.title, next.prompt, next.id);
|
|
2244
2323
|
}
|
|
2245
2324
|
} })) : isPixelView ? (_jsx(PixelOverlay, { version: props.version, agentRunning: agentLoop.isRunning, onClose: () => {
|
|
2246
|
-
if (props.resetUI && props.sessionStore) {
|
|
2325
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2247
2326
|
props.sessionStore.overlay = null;
|
|
2248
2327
|
props.resetUI();
|
|
2249
2328
|
}
|
|
2250
2329
|
else {
|
|
2251
|
-
|
|
2252
|
-
|
|
2330
|
+
if (props.sessionStore) {
|
|
2331
|
+
props.sessionStore.overlay = null;
|
|
2332
|
+
if (agentLoop.isRunning)
|
|
2333
|
+
props.sessionStore.pendingResetUI = true;
|
|
2334
|
+
}
|
|
2253
2335
|
setOverlay(null);
|
|
2254
2336
|
}
|
|
2255
2337
|
}, onFixOne: (entry) => {
|
|
@@ -2263,38 +2345,48 @@ export function App(props) {
|
|
|
2263
2345
|
setRunAllPixel(true);
|
|
2264
2346
|
startPixelFix(first.errorId);
|
|
2265
2347
|
} })) : isSkillsView ? (_jsx(SkillsOverlay, { cwd: props.cwd, onClose: () => {
|
|
2266
|
-
if (props.resetUI && props.sessionStore) {
|
|
2348
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2267
2349
|
props.sessionStore.overlay = null;
|
|
2268
2350
|
props.resetUI();
|
|
2269
2351
|
}
|
|
2270
2352
|
else {
|
|
2271
|
-
|
|
2272
|
-
|
|
2353
|
+
if (props.sessionStore) {
|
|
2354
|
+
props.sessionStore.overlay = null;
|
|
2355
|
+
if (agentLoop.isRunning)
|
|
2356
|
+
props.sessionStore.pendingResetUI = true;
|
|
2357
|
+
}
|
|
2273
2358
|
setOverlay(null);
|
|
2274
2359
|
}
|
|
2275
2360
|
} })) : isEyesView ? (_jsx(EyesOverlay, { cwd: props.cwd, onClose: () => {
|
|
2276
|
-
if (props.resetUI && props.sessionStore) {
|
|
2361
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2277
2362
|
props.sessionStore.overlay = null;
|
|
2278
2363
|
props.resetUI();
|
|
2279
2364
|
}
|
|
2280
2365
|
else {
|
|
2281
|
-
|
|
2366
|
+
if (props.sessionStore) {
|
|
2367
|
+
props.sessionStore.overlay = null;
|
|
2368
|
+
if (agentLoop.isRunning)
|
|
2369
|
+
props.sessionStore.pendingResetUI = true;
|
|
2370
|
+
}
|
|
2282
2371
|
setEyesCount(isEyesActive(props.cwd) ? journalCount({ status: "open" }, props.cwd) : undefined);
|
|
2283
|
-
setStaticKey((k) => k + 1);
|
|
2284
2372
|
setOverlay(null);
|
|
2285
2373
|
}
|
|
2286
2374
|
}, onQueueMessage: (msg) => {
|
|
2287
2375
|
agentLoop.queueMessage(msg);
|
|
2288
2376
|
} })) : isPlanView ? (_jsx(PlanOverlay, { cwd: props.cwd, autoExpandNewest: planAutoExpand, onClose: () => {
|
|
2289
2377
|
planOverlayPendingRef.current = false;
|
|
2290
|
-
if (props.resetUI && props.sessionStore) {
|
|
2378
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2291
2379
|
props.sessionStore.overlay = null;
|
|
2292
2380
|
props.sessionStore.planAutoExpand = false;
|
|
2293
2381
|
props.resetUI();
|
|
2294
2382
|
}
|
|
2295
2383
|
else {
|
|
2296
|
-
|
|
2297
|
-
|
|
2384
|
+
if (props.sessionStore) {
|
|
2385
|
+
props.sessionStore.overlay = null;
|
|
2386
|
+
props.sessionStore.planAutoExpand = false;
|
|
2387
|
+
if (agentLoop.isRunning)
|
|
2388
|
+
props.sessionStore.pendingResetUI = true;
|
|
2389
|
+
}
|
|
2298
2390
|
setPlanAutoExpand(false);
|
|
2299
2391
|
setOverlay(null);
|
|
2300
2392
|
}
|
|
@@ -2332,7 +2424,7 @@ export function App(props) {
|
|
|
2332
2424
|
sessionPath: newSessionPath,
|
|
2333
2425
|
pendingAction: {
|
|
2334
2426
|
prompt: "The plan has been approved. Implement it now, following each step in order.",
|
|
2335
|
-
|
|
2427
|
+
planEvent: { event: "approved" },
|
|
2336
2428
|
},
|
|
2337
2429
|
});
|
|
2338
2430
|
return;
|
|
@@ -2380,7 +2472,7 @@ export function App(props) {
|
|
|
2380
2472
|
props.resetUI({
|
|
2381
2473
|
pendingAction: {
|
|
2382
2474
|
prompt: rejectionMsg,
|
|
2383
|
-
|
|
2475
|
+
planEvent: { event: "rejected", detail: feedback },
|
|
2384
2476
|
},
|
|
2385
2477
|
});
|
|
2386
2478
|
return;
|
|
@@ -2403,30 +2495,48 @@ export function App(props) {
|
|
|
2403
2495
|
? THINKING_BORDER_COLORS[thinkingBorderFrame]
|
|
2404
2496
|
: "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, 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 &&
|
|
2405
2497
|
!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: () => {
|
|
2406
|
-
|
|
2498
|
+
// While the agent is running, skip the screen-clear + staticKey
|
|
2499
|
+
// bump that would otherwise wipe the chat history from scrollback.
|
|
2500
|
+
// Just flip the overlay state — Ink's log-update handles the
|
|
2501
|
+
// live-area transition (chat input → TaskOverlay) natively, and
|
|
2502
|
+
// the chat history above stays in scrollback. When the overlay
|
|
2503
|
+
// closes, the history is still there (banner included).
|
|
2504
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2407
2505
|
props.sessionStore.overlay = "tasks";
|
|
2408
2506
|
props.resetUI();
|
|
2409
2507
|
}
|
|
2410
2508
|
else {
|
|
2411
|
-
|
|
2509
|
+
if (props.sessionStore) {
|
|
2510
|
+
props.sessionStore.overlay = "tasks";
|
|
2511
|
+
if (agentLoop.isRunning)
|
|
2512
|
+
props.sessionStore.pendingResetUI = true;
|
|
2513
|
+
}
|
|
2412
2514
|
setOverlay("tasks");
|
|
2413
2515
|
}
|
|
2414
2516
|
}, onToggleSkills: () => {
|
|
2415
|
-
if (props.resetUI && props.sessionStore) {
|
|
2517
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2416
2518
|
props.sessionStore.overlay = "skills";
|
|
2417
2519
|
props.resetUI();
|
|
2418
2520
|
}
|
|
2419
2521
|
else {
|
|
2420
|
-
|
|
2522
|
+
if (props.sessionStore) {
|
|
2523
|
+
props.sessionStore.overlay = "skills";
|
|
2524
|
+
if (agentLoop.isRunning)
|
|
2525
|
+
props.sessionStore.pendingResetUI = true;
|
|
2526
|
+
}
|
|
2421
2527
|
setOverlay("skills");
|
|
2422
2528
|
}
|
|
2423
2529
|
}, onTogglePixel: () => {
|
|
2424
|
-
if (props.resetUI && props.sessionStore) {
|
|
2530
|
+
if (props.resetUI && props.sessionStore && !agentLoop.isRunning) {
|
|
2425
2531
|
props.sessionStore.overlay = "pixel";
|
|
2426
2532
|
props.resetUI();
|
|
2427
2533
|
}
|
|
2428
2534
|
else {
|
|
2429
|
-
|
|
2535
|
+
if (props.sessionStore) {
|
|
2536
|
+
props.sessionStore.overlay = "pixel";
|
|
2537
|
+
if (agentLoop.isRunning)
|
|
2538
|
+
props.sessionStore.pendingResetUI = true;
|
|
2539
|
+
}
|
|
2430
2540
|
setOverlay("pixel");
|
|
2431
2541
|
}
|
|
2432
2542
|
}, onTogglePlanMode: () => {
|
|
@@ -2442,6 +2552,6 @@ export function App(props) {
|
|
|
2442
2552
|
id: getId(),
|
|
2443
2553
|
},
|
|
2444
2554
|
]);
|
|
2445
|
-
}, cwd: props.cwd, commands: allCommands, eyesCount: eyesCount }), 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 })) : (_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, cwd: displayedCwd, gitBranch: gitBranch, thinkingEnabled: thinkingEnabled, planMode: planMode, exitPending: exitPending })),
|
|
2555
|
+
}, cwd: props.cwd, commands: allCommands, eyesCount: eyesCount }), 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 })) : (_jsx(Footer, { model: currentModel, tokensIn: agentLoop.contextUsed, cwd: displayedCwd, gitBranch: gitBranch, thinkingEnabled: thinkingEnabled, planMode: planMode, exitPending: exitPending })), (bgTasks.length > 0 || (eyesCount !== undefined && eyesCount > 0) || updatePending) && (_jsxs(Box, { children: [bgTasks.length > 0 && (_jsx(BackgroundTasksBar, { tasks: bgTasks, focused: taskBarFocused, expanded: taskBarExpanded, selectedIndex: selectedTaskIndex, onExpand: handleTaskBarExpand, onCollapse: handleTaskBarCollapse, onKill: handleTaskKill, onExit: handleTaskBarExit, onNavigate: handleTaskNavigate })), eyesCount !== undefined && eyesCount > 0 && (_jsx(Box, { paddingLeft: bgTasks.length > 0 ? 2 : 1, paddingRight: 1, children: _jsx(Text, { color: theme.accent, bold: true, children: `${eyesCount} eyes signal${eyesCount === 1 ? "" : "s"} · Run /eyes-improve to enhance GG Coder` }) })), updatePending && (_jsx(Box, { paddingLeft: bgTasks.length > 0 || (eyesCount !== undefined && eyesCount > 0) ? 2 : 1, paddingRight: 1, children: _jsx(Text, { color: theme.success, bold: true, children: "\u2728 Update ready \u00B7 restart to apply" }) }))] }))] }))] }));
|
|
2446
2556
|
}
|
|
2447
2557
|
//# sourceMappingURL=App.js.map
|