zidane 5.3.0 → 5.3.1
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/{agent-CYpPKn5Z.d.ts → agent-bKs7MRT2.d.ts} +430 -5
- package/dist/agent-bKs7MRT2.d.ts.map +1 -0
- package/dist/chat.d.ts +310 -6
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/{errors-COmsomd5.js → errors-Byb0F8B9.js} +44 -2
- package/dist/errors-Byb0F8B9.js.map +1 -0
- package/dist/{index-D-cTScN3.d.ts → index-BlMvPh9X.d.ts} +57 -10
- package/dist/index-BlMvPh9X.d.ts.map +1 -0
- package/dist/{index-Cc-q1hLT.d.ts → index-CTmNaIDb.d.ts} +2 -2
- package/dist/{index-Cc-q1hLT.d.ts.map → index-CTmNaIDb.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +10 -10
- package/dist/{interpolate-BhmHKD6x.js → interpolate-ERgZUxgg.js} +2 -2
- package/dist/{interpolate-BhmHKD6x.js.map → interpolate-ERgZUxgg.js.map} +1 -1
- package/dist/{login-BXVt5wuA.js → login-CNS9_8Ue.js} +3 -3
- package/dist/{login-BXVt5wuA.js.map → login-CNS9_8Ue.js.map} +1 -1
- package/dist/{mcp-B1psg7jf.js → mcp-ZsSFo4Dp.js} +2 -2
- package/dist/{mcp-B1psg7jf.js.map → mcp-ZsSFo4Dp.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-DsbMYNmt.js → messages-D0xT979U.js} +631 -68
- package/dist/messages-D0xT979U.js.map +1 -0
- package/dist/{presets-tvD28pCu.js → presets-h5i3kpOP.js} +29 -10
- package/dist/presets-h5i3kpOP.js.map +1 -0
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-v1Rn2rqG.js → providers-x3LZByR5.js} +38 -6
- package/dist/providers-x3LZByR5.js.map +1 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -3
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.js +1 -1
- package/dist/{session-DOJgRXvF.js → session-BHZwxmfr.js} +2 -2
- package/dist/{session-DOJgRXvF.js.map → session-BHZwxmfr.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tools-CMVruxF0.js → tools-CWEDS2ZT.js} +380 -48
- package/dist/tools-CWEDS2ZT.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-eyhlGeBI.d.ts → transcript-anchors-DOUqyvXR.d.ts} +28 -4
- package/dist/transcript-anchors-DOUqyvXR.d.ts.map +1 -0
- package/dist/tui.d.ts +29 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +365 -80
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-Y7e15gJf.js → turn-operations-D9HvatsR.js} +678 -33
- package/dist/turn-operations-D9HvatsR.js.map +1 -0
- package/dist/types-IcokUOyC.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/dist/agent-CYpPKn5Z.d.ts.map +0 -1
- package/dist/errors-COmsomd5.js.map +0 -1
- package/dist/index-D-cTScN3.d.ts.map +0 -1
- package/dist/messages-DsbMYNmt.js.map +0 -1
- package/dist/presets-tvD28pCu.js.map +0 -1
- package/dist/providers-v1Rn2rqG.js.map +0 -1
- package/dist/tools-CMVruxF0.js.map +0 -1
- package/dist/transcript-anchors-eyhlGeBI.d.ts.map +0 -1
- package/dist/turn-operations-Y7e15gJf.js.map +0 -1
package/dist/tui.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { s as McpOAuthProvider, t as connectMcpServers } from "./mcp-
|
|
4
|
-
import { C as summaryToTurn, a as selectFilesFromSession, r as buildPostCompactAttachments, s as compactConversation, t as loginMcpServer } from "./login-
|
|
1
|
+
import { D as resolvePersistDir, T as cleanupPersistedSession, p as createAgent } from "./tools-CWEDS2ZT.js";
|
|
2
|
+
import { s as errorMessage } from "./errors-Byb0F8B9.js";
|
|
3
|
+
import { s as McpOAuthProvider, t as connectMcpServers } from "./mcp-ZsSFo4Dp.js";
|
|
4
|
+
import { C as summaryToTurn, a as selectFilesFromSession, r as buildPostCompactAttachments, s as compactConversation, t as loginMcpServer } from "./login-CNS9_8Ue.js";
|
|
5
5
|
import { n as formatTokenUsage } from "./stats-DgOvY7wd.js";
|
|
6
|
-
import { n as loadSession, t as createSession } from "./session-
|
|
6
|
+
import { n as loadSession, t as createSession } from "./session-BHZwxmfr.js";
|
|
7
7
|
import { createTuiStore } from "./session/sqlite.js";
|
|
8
|
-
import { $ as useMcpAuthDispatch, $n as bootTick, $t as isVisible, A as getSafelist, At as clampFps, B as supportsOAuth, Bn as uniqueSkillNamesFromReferences,
|
|
8
|
+
import { $ as useMcpAuthDispatch, $n as bootTick, $t as isVisible, A as getSafelist, At as clampFps, B as supportsOAuth, Bn as uniqueSkillNamesFromReferences, Ct as shortId, D as useSafeModeQueue, Dn as findGitRoot, Dr as accentColor, Dt as SETTINGS_CHOICES, E as useSafeModeActions, En as summarizeOutcomes, Et as DEFAULT_SETTINGS, F as suggestSafelistEntry, Ft as resolveTheme, Gt as ConfigProvider, H as filterModelCatalog, Hn as createFilesCompletionProvider, Ht as DiscoveryProvider, Jn as useCompletion, K as discoverProjectMcps, Kt as useConfig, L as splitPromptSegments, Nn as matchesBinding, Nr as TODO_STATUS_GLYPHS, Ot as SETTINGS_TOGGLES, Pt as resolveChipColor, Q as McpAuthProvider, Qt as isTurnHighlighted, R as formatPathForCwd, Sn as buildEditOutcomesAnnotation, St as fmtTokens, T as SafeModeProvider, Tn as resolveApprovalForPayload, Tt as useEnabledToggleSet, U as indexOfEntry, Ur as useActiveTodos, Ut as useDiscovery, V as buildModelCatalog, Vt as createDiscoverySlot, W as buildMcpServers, Wt as useDiscoveryOptional, Xn as buildLinearRamp, Xt as eventsFromTurns, Y as createFileMcpCredentialStore, Yn as blendHsl, Yt as deriveSessionTitle, Zn as tryOpenBrowser, Zt as isEditErrorResult, _ as turnContextSize, _n as extractEditPayload, _r as modelSupportsReasoning, _t as truncateTrailing, a as computeTurnAnchors, an as selectableTurnIds, at as InteractionsProvider, b as defaultSkillScanPaths, bt as ageString, c as formatToolCall, ct as createInteractionTools, d as useSelectStyle, dn as turnSelectionOwnership, dt as pendingInteractionsFromTurns, ei as buildBuildSystem, en as lastContextSizeFromTurns, er as shouldAutoCompact, et as useMcpAuthState, f as useSurfaces, g as finalizeStreamingMarkdownForOwner, gt as hintsLength, h as finalizeStreamingMarkdown, hr as getContextWindow, ht as clipHintsToWidth, i as turnAsText, j as isOnSafelist, jn as ensureKeybindingsFile, jt as useSettings, k as addToSafelist, kt as SettingsProvider, l as ThemeProvider, ln as toolCallPreview, m as useTheme, mn as buildUnifiedDiff, mt as useInteractionsQueue, n as deleteTurnSafely, o as TOOL_DISPLAY, on as stripSpawnTokensLine, pt as useInteractionsActions, qt as resolveConfig, r as truncateTurnsAt, rn as marginTopFor, rt as splitMarkdownCodeBlocks, s as displayNameFor, sn as sumRunCosts, sr as setProviderCredential, st as buildResumedToolResultsTurn, ti as buildPlanSystem, tn as listSessionMeta, tr as detectAuth, tt as getMcpAuthStatus, u as useColors, un as toolResultText, ut as makeRequestInteraction, v as useStreamBuffer, vn as filetypeFromPath, w as writeSessionExport, wt as listProjectFiles, x as discoverProjectSkills, xr as piIdOf, xt as compactPath, y as buildSkillsConfig, yn as previewEditPayload, yt as generateSessionTitle, z as runOAuthLogin, zn as createSkillsCompletionProvider } from "./turn-operations-D9HvatsR.js";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { Buffer } from "node:buffer";
|
|
11
11
|
import * as fs from "node:fs";
|
|
@@ -80,7 +80,7 @@ function useModalAwareFocus(preferred = true) {
|
|
|
80
80
|
*
|
|
81
81
|
* Uses `useTerminalDimensions()` so it reflows on `SIGWINCH` without remount.
|
|
82
82
|
*/
|
|
83
|
-
function Modal({ title, bottomTitle, onClose, disableEscape = false, children, maxWidth = 92, minWidth = 44, maxHeight, horizontalMargin = 4, verticalMargin = 2 }) {
|
|
83
|
+
function Modal({ title, bottomTitle, rightTitle, onClose, disableEscape = false, children, maxWidth = 92, minWidth = 44, maxHeight, horizontalMargin = 4, verticalMargin = 2 }) {
|
|
84
84
|
const ctx = useContext(ModalContext);
|
|
85
85
|
const dismiss = onClose ?? ctx?.close;
|
|
86
86
|
const COLOR = useColors();
|
|
@@ -91,7 +91,7 @@ function Modal({ title, bottomTitle, onClose, disableEscape = false, children, m
|
|
|
91
91
|
const { width: termWidth, height: termHeight } = useTerminalDimensions();
|
|
92
92
|
const width = Math.max(minWidth, Math.min(maxWidth, termWidth - horizontalMargin * 2));
|
|
93
93
|
const height = maxHeight === void 0 ? void 0 : Math.min(maxHeight, Math.max(0, termHeight - verticalMargin * 2));
|
|
94
|
-
|
|
94
|
+
const panel = /* @__PURE__ */ jsx("box", {
|
|
95
95
|
title: title ? ` ${title} ` : void 0,
|
|
96
96
|
bottomTitle: bottomTitle ? ` ${bottomTitle} ` : void 0,
|
|
97
97
|
bottomTitleAlignment: "right",
|
|
@@ -110,6 +110,21 @@ function Modal({ title, bottomTitle, onClose, disableEscape = false, children, m
|
|
|
110
110
|
},
|
|
111
111
|
children
|
|
112
112
|
});
|
|
113
|
+
if (rightTitle == null) return panel;
|
|
114
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
115
|
+
style: {
|
|
116
|
+
width,
|
|
117
|
+
flexDirection: "column"
|
|
118
|
+
},
|
|
119
|
+
children: [panel, /* @__PURE__ */ jsx("box", {
|
|
120
|
+
style: {
|
|
121
|
+
position: "absolute",
|
|
122
|
+
top: 0,
|
|
123
|
+
right: 1
|
|
124
|
+
},
|
|
125
|
+
children: rightTitle
|
|
126
|
+
})]
|
|
127
|
+
});
|
|
113
128
|
}
|
|
114
129
|
//#endregion
|
|
115
130
|
//#region src/tui/agent-picker.tsx
|
|
@@ -923,7 +938,7 @@ function StatusSpinner({ color }) {
|
|
|
923
938
|
function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
|
|
924
939
|
const COLOR = useColors();
|
|
925
940
|
const items = useMemo(() => partitionTranscript(events, settings), [events, settings]);
|
|
926
|
-
const showThrobber = busy;
|
|
941
|
+
const showThrobber = busy && settings.showThrobber;
|
|
927
942
|
const throbberLabel = events.length > 0 && events[events.length - 1].kind === "thinking" ? "Thinking" : void 0;
|
|
928
943
|
const ownership = useMemo(() => turnSelectionOwnership(events), [events]);
|
|
929
944
|
const scrollboxRef = useRef(null);
|
|
@@ -1145,13 +1160,16 @@ function EventLineImpl({ event, depthOffset = 0 }) {
|
|
|
1145
1160
|
dim: child
|
|
1146
1161
|
})
|
|
1147
1162
|
});
|
|
1148
|
-
return /* @__PURE__ */
|
|
1163
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
1149
1164
|
style: row,
|
|
1150
|
-
children: /* @__PURE__ */ jsx(ToolCallBlock, {
|
|
1165
|
+
children: [/* @__PURE__ */ jsx(ToolCallBlock, {
|
|
1151
1166
|
event,
|
|
1152
1167
|
display: settings.toolCallDisplay === "full" ? "full" : "formatted",
|
|
1153
1168
|
dim: child
|
|
1154
|
-
})
|
|
1169
|
+
}), event.tool === "todowrite" && /* @__PURE__ */ jsx(TodoInProgressList, {
|
|
1170
|
+
input: event.input,
|
|
1171
|
+
dim: child
|
|
1172
|
+
})]
|
|
1155
1173
|
});
|
|
1156
1174
|
case "tool-result": return /* @__PURE__ */ jsx(ToolResultBlock, {
|
|
1157
1175
|
text: event.text,
|
|
@@ -1644,6 +1662,7 @@ const MarkdownBlock = memo(({ text, dim }) => {
|
|
|
1644
1662
|
const SURFACE = useSurfaces();
|
|
1645
1663
|
const mdStyle = useMdStyle();
|
|
1646
1664
|
const renderer = useRenderer();
|
|
1665
|
+
const content = text.replace(/^\n+|\n+$/g, "");
|
|
1647
1666
|
const bag = useRef({
|
|
1648
1667
|
ctx: renderer,
|
|
1649
1668
|
colors: COLOR,
|
|
@@ -1658,7 +1677,7 @@ const MarkdownBlock = memo(({ text, dim }) => {
|
|
|
1658
1677
|
}, [COLOR, SURFACE]);
|
|
1659
1678
|
const renderNode = useMemo(() => makeMarkdownRenderNode(bag), []);
|
|
1660
1679
|
return /* @__PURE__ */ jsx("markdown", {
|
|
1661
|
-
content
|
|
1680
|
+
content,
|
|
1662
1681
|
syntaxStyle: mdStyle,
|
|
1663
1682
|
streaming: true,
|
|
1664
1683
|
internalBlockMode: "coalesced",
|
|
@@ -1966,6 +1985,43 @@ function ToolCallBlock({ event, display, dim }) {
|
|
|
1966
1985
|
]
|
|
1967
1986
|
});
|
|
1968
1987
|
}
|
|
1988
|
+
function TodoInProgressList({ input, dim }) {
|
|
1989
|
+
const COLOR = useColors();
|
|
1990
|
+
const items = useMemo(() => {
|
|
1991
|
+
const raw = input?.todos;
|
|
1992
|
+
if (!Array.isArray(raw)) return [];
|
|
1993
|
+
return raw.flatMap((t) => {
|
|
1994
|
+
if (t == null || typeof t !== "object") return [];
|
|
1995
|
+
const rec = t;
|
|
1996
|
+
if (rec.status !== "in_progress") return [];
|
|
1997
|
+
const id = typeof rec.id === "string" ? rec.id : "";
|
|
1998
|
+
const content = typeof rec.content === "string" ? rec.content : "";
|
|
1999
|
+
if (!id || !content) return [];
|
|
2000
|
+
return [{
|
|
2001
|
+
id,
|
|
2002
|
+
content
|
|
2003
|
+
}];
|
|
2004
|
+
});
|
|
2005
|
+
}, [input]);
|
|
2006
|
+
if (items.length === 0) return null;
|
|
2007
|
+
const glyph = TODO_STATUS_GLYPHS.in_progress;
|
|
2008
|
+
return /* @__PURE__ */ jsx("box", {
|
|
2009
|
+
style: {
|
|
2010
|
+
flexDirection: "column",
|
|
2011
|
+
marginLeft: 2
|
|
2012
|
+
},
|
|
2013
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("text", {
|
|
2014
|
+
wrapMode: "none",
|
|
2015
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2016
|
+
fg: COLOR.mute,
|
|
2017
|
+
children: `${glyph} `
|
|
2018
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2019
|
+
fg: dim ? COLOR.dim : COLOR.warn,
|
|
2020
|
+
children: item.content
|
|
2021
|
+
})]
|
|
2022
|
+
}, item.id))
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
1969
2025
|
//#endregion
|
|
1970
2026
|
//#region src/tui/discovery-shell.tsx
|
|
1971
2027
|
/**
|
|
@@ -2740,26 +2796,6 @@ const FILE_EDIT_TOOLS = new Set([
|
|
|
2740
2796
|
function isFileEditTool(tool) {
|
|
2741
2797
|
return FILE_EDIT_TOOLS.has(tool);
|
|
2742
2798
|
}
|
|
2743
|
-
/** Page jump = viewport height minus 1 row of carry-over context. */
|
|
2744
|
-
function diffPageStep(viewportHeight) {
|
|
2745
|
-
return Math.max(1, viewportHeight - 1);
|
|
2746
|
-
}
|
|
2747
|
-
/** Clamp a candidate `scrollTop` into `[0, max]`, tolerating bad inputs. */
|
|
2748
|
-
function clampScrollTop(next, max) {
|
|
2749
|
-
if (!Number.isFinite(next)) return 0;
|
|
2750
|
-
if (!Number.isFinite(max) || max < 0) return Math.max(0, next);
|
|
2751
|
-
return Math.max(0, Math.min(max, next));
|
|
2752
|
-
}
|
|
2753
|
-
/**
|
|
2754
|
-
* Apply a signed scroll delta to a scrollbox, clamping against its own
|
|
2755
|
-
* scrollHeight/viewport. Mouse-wheel events still route through OpenTUI's
|
|
2756
|
-
* own hit-tester regardless of focus; this only services keyboard scroll.
|
|
2757
|
-
*/
|
|
2758
|
-
function applyDiffScroll(scrollbox, delta) {
|
|
2759
|
-
if (!scrollbox) return;
|
|
2760
|
-
const max = Math.max(0, scrollbox.scrollHeight - scrollbox.viewport.height);
|
|
2761
|
-
scrollbox.scrollTop = clampScrollTop(scrollbox.scrollTop + delta, max);
|
|
2762
|
-
}
|
|
2763
2799
|
function useEditPayloadFromRequest(request) {
|
|
2764
2800
|
const targetPath = String(request.input.path ?? "");
|
|
2765
2801
|
const [priorContent, priorError] = useMemo(() => {
|
|
@@ -2891,7 +2927,6 @@ function SingleEditApprovalModal({ request, payload, priorContent, priorError, t
|
|
|
2891
2927
|
const mdStyle = useMdStyle();
|
|
2892
2928
|
const { width: termWidth } = useTerminalDimensions();
|
|
2893
2929
|
const modal = useModal();
|
|
2894
|
-
const diffScrollRef = useRef(null);
|
|
2895
2930
|
const preview = useMemo(() => payload ? previewEditPayload(payload, priorContent, 6) : null, [payload, priorContent]);
|
|
2896
2931
|
const diffText = preview?.diffText ?? "";
|
|
2897
2932
|
const focusedResolved = preview?.resolution[0]?.resolved ?? true;
|
|
@@ -2908,20 +2943,6 @@ function SingleEditApprovalModal({ request, payload, priorContent, priorError, t
|
|
|
2908
2943
|
modal.close();
|
|
2909
2944
|
}, [onDecide, modal]);
|
|
2910
2945
|
useKeyboard((key) => {
|
|
2911
|
-
if (key.name === "pageup") {
|
|
2912
|
-
const sb = diffScrollRef.current;
|
|
2913
|
-
if (sb) applyDiffScroll(sb, -diffPageStep(sb.viewport.height));
|
|
2914
|
-
return;
|
|
2915
|
-
}
|
|
2916
|
-
if (key.name === "pagedown") {
|
|
2917
|
-
const sb = diffScrollRef.current;
|
|
2918
|
-
if (sb) applyDiffScroll(sb, diffPageStep(sb.viewport.height));
|
|
2919
|
-
return;
|
|
2920
|
-
}
|
|
2921
|
-
if ((key.name === "up" || key.name === "down") && key.shift) {
|
|
2922
|
-
applyDiffScroll(diffScrollRef.current, key.name === "up" ? -1 : 1);
|
|
2923
|
-
return;
|
|
2924
|
-
}
|
|
2925
2946
|
if (key.name === "left") {
|
|
2926
2947
|
setSelected((i) => (i - 1 + BULK_ACTIONS.length) % BULK_ACTIONS.length);
|
|
2927
2948
|
return;
|
|
@@ -2954,7 +2975,7 @@ function SingleEditApprovalModal({ request, payload, priorContent, priorError, t
|
|
|
2954
2975
|
children: [/* @__PURE__ */ jsxs("box", {
|
|
2955
2976
|
title: SINGLE_EDIT_TITLE,
|
|
2956
2977
|
titleAlignment: "left",
|
|
2957
|
-
bottomTitle: " ←→ navigate · ↵ confirm · esc deny · a/s/p/d shortcuts
|
|
2978
|
+
bottomTitle: " ←→ navigate · ↵ confirm · esc deny · a/s/p/d shortcuts ",
|
|
2958
2979
|
style: {
|
|
2959
2980
|
flexGrow: 1,
|
|
2960
2981
|
flexShrink: 1,
|
|
@@ -2991,7 +3012,6 @@ function SingleEditApprovalModal({ request, payload, priorContent, priorError, t
|
|
|
2991
3012
|
marginBottom: 1
|
|
2992
3013
|
},
|
|
2993
3014
|
children: /* @__PURE__ */ jsx("scrollbox", {
|
|
2994
|
-
ref: diffScrollRef,
|
|
2995
3015
|
focusable: false,
|
|
2996
3016
|
stickyScroll: false,
|
|
2997
3017
|
style: {
|
|
@@ -3119,20 +3139,6 @@ function MultiEditApprovalModal({ request, payload, priorContent, priorError, ta
|
|
|
3119
3139
|
decide("deny");
|
|
3120
3140
|
return;
|
|
3121
3141
|
}
|
|
3122
|
-
if (key.name === "pageup") {
|
|
3123
|
-
const sb = diffScrollRef.current;
|
|
3124
|
-
if (sb) applyDiffScroll(sb, -diffPageStep(sb.viewport.height));
|
|
3125
|
-
return;
|
|
3126
|
-
}
|
|
3127
|
-
if (key.name === "pagedown") {
|
|
3128
|
-
const sb = diffScrollRef.current;
|
|
3129
|
-
if (sb) applyDiffScroll(sb, diffPageStep(sb.viewport.height));
|
|
3130
|
-
return;
|
|
3131
|
-
}
|
|
3132
|
-
if ((key.name === "up" || key.name === "down") && key.shift) {
|
|
3133
|
-
applyDiffScroll(diffScrollRef.current, key.name === "up" ? -1 : 1);
|
|
3134
|
-
return;
|
|
3135
|
-
}
|
|
3136
3142
|
if (key.name === "tab") {
|
|
3137
3143
|
setZone((z) => z === "list" ? "actions" : "list");
|
|
3138
3144
|
return;
|
|
@@ -3220,7 +3226,7 @@ function MultiEditApprovalModal({ request, payload, priorContent, priorError, ta
|
|
|
3220
3226
|
children: [/* @__PURE__ */ jsxs("box", {
|
|
3221
3227
|
title: MULTI_EDIT_TITLE,
|
|
3222
3228
|
titleAlignment: "left",
|
|
3223
|
-
bottomTitle: " ↑↓ select · space toggle · y/n all/none · tab focus · a/s/p/d shortcuts · ↵ confirm · esc deny
|
|
3229
|
+
bottomTitle: " ↑↓ select · space toggle · y/n all/none · tab focus · a/s/p/d shortcuts · ↵ confirm · esc deny ",
|
|
3224
3230
|
style: {
|
|
3225
3231
|
flexGrow: 1,
|
|
3226
3232
|
flexShrink: 1,
|
|
@@ -4210,6 +4216,72 @@ function OptionList({ items, initialCursor, onPick }) {
|
|
|
4210
4216
|
});
|
|
4211
4217
|
}
|
|
4212
4218
|
//#endregion
|
|
4219
|
+
//#region src/tui/todo-indicator.tsx
|
|
4220
|
+
/**
|
|
4221
|
+
* Layout budget when truncating the content. The bar never wraps —
|
|
4222
|
+
* single-line by contract — so we subtract every column consumed by
|
|
4223
|
+
* surrounding chrome before measuring how much room is left for the
|
|
4224
|
+
* todo's `content` text.
|
|
4225
|
+
*
|
|
4226
|
+
* - 2 cols ⇒ `<ChatScreen>`'s `border: true` (1 cell each side).
|
|
4227
|
+
* - 2 cols ⇒ this indicator's own `paddingLeft: 1 + paddingRight: 1`
|
|
4228
|
+
* (mirrors the queue block's outer padding so the bar
|
|
4229
|
+
* and queue read as aligned siblings).
|
|
4230
|
+
* - 4 cols ⇒ the indicator's own visible chrome: glyph "◐" (1) +
|
|
4231
|
+
* two spaces (2) + 1 col of trailing breathing room.
|
|
4232
|
+
*
|
|
4233
|
+
* That's 8 cols total of non-content overhead. Below `MIN_VISIBLE_TAIL`
|
|
4234
|
+
* the bar bails — a one-or-two-char tail isn't worth painting.
|
|
4235
|
+
*/
|
|
4236
|
+
const SCREEN_BORDER_COLS = 2;
|
|
4237
|
+
const INDICATOR_PADDING_COLS = 2;
|
|
4238
|
+
const CHROME_COLS = 4;
|
|
4239
|
+
const MIN_VISIBLE_TAIL = 8;
|
|
4240
|
+
function truncateForWidth(text, max) {
|
|
4241
|
+
if (max <= 0) return "";
|
|
4242
|
+
if (text.length <= max) return text;
|
|
4243
|
+
if (max <= 1) return "…";
|
|
4244
|
+
return `${text.slice(0, max - 1)}…`;
|
|
4245
|
+
}
|
|
4246
|
+
function TodoIndicator({ session }) {
|
|
4247
|
+
const { settings } = useSettings();
|
|
4248
|
+
const COLOR = useColors();
|
|
4249
|
+
const { width: termWidth } = useTerminalDimensions();
|
|
4250
|
+
const state = useActiveTodos(session);
|
|
4251
|
+
if (!settings.showTodoIndicator) return null;
|
|
4252
|
+
const item = state.inProgress;
|
|
4253
|
+
if (!item) return null;
|
|
4254
|
+
const usable = Math.max(0, termWidth - SCREEN_BORDER_COLS - INDICATOR_PADDING_COLS - CHROME_COLS);
|
|
4255
|
+
if (usable < MIN_VISIBLE_TAIL) return null;
|
|
4256
|
+
const display = truncateForWidth(item.content.replace(/\s+/g, " ").trim(), usable);
|
|
4257
|
+
return /* @__PURE__ */ jsx("box", {
|
|
4258
|
+
style: {
|
|
4259
|
+
marginTop: 1,
|
|
4260
|
+
flexShrink: 0,
|
|
4261
|
+
flexDirection: "row",
|
|
4262
|
+
paddingLeft: 1,
|
|
4263
|
+
paddingRight: 1
|
|
4264
|
+
},
|
|
4265
|
+
children: /* @__PURE__ */ jsxs("text", {
|
|
4266
|
+
wrapMode: "none",
|
|
4267
|
+
children: [
|
|
4268
|
+
/* @__PURE__ */ jsx("span", {
|
|
4269
|
+
fg: COLOR.warn,
|
|
4270
|
+
children: TODO_STATUS_GLYPHS.in_progress
|
|
4271
|
+
}),
|
|
4272
|
+
/* @__PURE__ */ jsx("span", {
|
|
4273
|
+
fg: COLOR.mute,
|
|
4274
|
+
children: " "
|
|
4275
|
+
}),
|
|
4276
|
+
/* @__PURE__ */ jsx("span", {
|
|
4277
|
+
fg: COLOR.dim,
|
|
4278
|
+
children: display
|
|
4279
|
+
})
|
|
4280
|
+
]
|
|
4281
|
+
})
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
4284
|
+
//#endregion
|
|
4213
4285
|
//#region src/tui/screens.tsx
|
|
4214
4286
|
/**
|
|
4215
4287
|
* Build a key-binding set for the prompt textarea / API-key input. Strips the
|
|
@@ -5028,7 +5100,7 @@ const CWD_DISPLAY = compactPath(process.cwd());
|
|
|
5028
5100
|
* default-value reference at the prop destructure.
|
|
5029
5101
|
*/
|
|
5030
5102
|
const EMPTY_QUEUED_MESSAGES = [];
|
|
5031
|
-
function ChatScreen({ events, busy, compacting = false, queuedMessages = EMPTY_QUEUED_MESSAGES, queueSelectionIndex = null, queueShortcuts, onEnterQueueFromEmptyPrompt, settings, onSubmit, session, pending, onApproval, pendingInteraction, onInteraction, completionProviders, onPopupOpenChange, selectedTurnId, promptTriggerHints }) {
|
|
5103
|
+
function ChatScreen({ events, busy, compacting = false, queuedMessages = EMPTY_QUEUED_MESSAGES, queueSelectionIndex = null, queueShortcuts, onEnterQueueFromEmptyPrompt, settings, onSubmit, session, pending, onApproval, pendingInteraction, onInteraction, completionProviders, onPopupOpenChange, selectedTurnId, promptTriggerHints, liveSession = null }) {
|
|
5032
5104
|
const COLOR = useColors();
|
|
5033
5105
|
const titleText = session?.title ?? "untitled";
|
|
5034
5106
|
const showSessionShortcut = !!session && !busy && !pending && !pendingInteraction;
|
|
@@ -5127,20 +5199,24 @@ function ChatScreen({ events, busy, compacting = false, queuedMessages = EMPTY_Q
|
|
|
5127
5199
|
}) : pendingInteraction ? /* @__PURE__ */ jsx(InteractionBlock, {
|
|
5128
5200
|
request: pendingInteraction,
|
|
5129
5201
|
onResolve: onInteraction
|
|
5130
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5202
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5203
|
+
queuedMessages.length > 0 && !completionPopupOpen && /* @__PURE__ */ jsx(QueuedMessagesBlock, {
|
|
5204
|
+
messages: queuedMessages,
|
|
5205
|
+
selectionIndex: queueSelectionIndex,
|
|
5206
|
+
shortcuts: queueShortcuts
|
|
5207
|
+
}),
|
|
5208
|
+
/* @__PURE__ */ jsx(TodoIndicator, { session: liveSession }),
|
|
5209
|
+
/* @__PURE__ */ jsx(PromptBlock, {
|
|
5210
|
+
userPrompts,
|
|
5211
|
+
onSubmit,
|
|
5212
|
+
completionProviders,
|
|
5213
|
+
onPopupOpenChange: handlePopupOpenChange,
|
|
5214
|
+
selectMode: queueSelectionIndex != null ? "queue" : selectedTurnId != null ? "turn" : null,
|
|
5215
|
+
triggerHints: promptTriggerHints,
|
|
5216
|
+
busy,
|
|
5217
|
+
onEnterQueueFromEmpty: onEnterQueueFromEmptyPrompt
|
|
5218
|
+
})
|
|
5219
|
+
] }),
|
|
5144
5220
|
/* @__PURE__ */ jsx(TitleOverlay, {
|
|
5145
5221
|
title: titleText,
|
|
5146
5222
|
meta: metaSegments
|
|
@@ -7326,6 +7402,207 @@ function displayPath$1(path, home) {
|
|
|
7326
7402
|
return path;
|
|
7327
7403
|
}
|
|
7328
7404
|
//#endregion
|
|
7405
|
+
//#region src/tui/todos-modal.tsx
|
|
7406
|
+
/** Floor on the modal height — keeps the header + at least a few rows visible on tiny terminals. */
|
|
7407
|
+
const MIN_MODAL_HEIGHT = 12;
|
|
7408
|
+
/** Ceiling on the modal height — prevents a giant list from blanket-filling a tall window. */
|
|
7409
|
+
const MAX_MODAL_HEIGHT$1 = 36;
|
|
7410
|
+
/**
|
|
7411
|
+
* Per-status palette for a row — the glyph and the content text pick
|
|
7412
|
+
* different tones so a quick scan reads the status from the glyph color
|
|
7413
|
+
* while the row content stays in a calm reading tone:
|
|
7414
|
+
*
|
|
7415
|
+
* pending glyph `mute` · text `dim` — queued / not yet started
|
|
7416
|
+
* in_progress glyph `warn` · text `brand` — currently working (loudest)
|
|
7417
|
+
* completed glyph `accent` · text `dim` — done (success glyph, calm text)
|
|
7418
|
+
* cancelled glyph `error` · text `mute` — explicitly dropped
|
|
7419
|
+
*
|
|
7420
|
+
* All tokens come from the active theme — a runtime theme switch
|
|
7421
|
+
* repaints without touching this component.
|
|
7422
|
+
*/
|
|
7423
|
+
function statusColors(status, COLOR) {
|
|
7424
|
+
switch (status) {
|
|
7425
|
+
case "in_progress": return {
|
|
7426
|
+
glyph: COLOR.warn,
|
|
7427
|
+
text: COLOR.brand
|
|
7428
|
+
};
|
|
7429
|
+
case "completed": return {
|
|
7430
|
+
glyph: COLOR.accent,
|
|
7431
|
+
text: COLOR.dim
|
|
7432
|
+
};
|
|
7433
|
+
case "cancelled": return {
|
|
7434
|
+
glyph: COLOR.error,
|
|
7435
|
+
text: COLOR.mute
|
|
7436
|
+
};
|
|
7437
|
+
default: return {
|
|
7438
|
+
glyph: COLOR.mute,
|
|
7439
|
+
text: COLOR.dim
|
|
7440
|
+
};
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
function TodoRow({ item, rowId }) {
|
|
7444
|
+
const COLOR = useColors();
|
|
7445
|
+
const colors = statusColors(item.status, COLOR);
|
|
7446
|
+
return /* @__PURE__ */ jsx("box", {
|
|
7447
|
+
id: rowId,
|
|
7448
|
+
style: {
|
|
7449
|
+
flexShrink: 0,
|
|
7450
|
+
flexDirection: "row"
|
|
7451
|
+
},
|
|
7452
|
+
children: /* @__PURE__ */ jsxs("text", {
|
|
7453
|
+
wrapMode: "word",
|
|
7454
|
+
children: [
|
|
7455
|
+
/* @__PURE__ */ jsx("span", {
|
|
7456
|
+
fg: colors.glyph,
|
|
7457
|
+
children: TODO_STATUS_GLYPHS[item.status]
|
|
7458
|
+
}),
|
|
7459
|
+
/* @__PURE__ */ jsx("span", {
|
|
7460
|
+
fg: COLOR.mute,
|
|
7461
|
+
children: " "
|
|
7462
|
+
}),
|
|
7463
|
+
/* @__PURE__ */ jsx("span", {
|
|
7464
|
+
fg: colors.text,
|
|
7465
|
+
children: item.content
|
|
7466
|
+
})
|
|
7467
|
+
]
|
|
7468
|
+
})
|
|
7469
|
+
});
|
|
7470
|
+
}
|
|
7471
|
+
function TodosModal({ session, agent }) {
|
|
7472
|
+
const COLOR = useColors();
|
|
7473
|
+
const { height: termHeight } = useTerminalDimensions();
|
|
7474
|
+
const [, setTick] = useState(0);
|
|
7475
|
+
useEffect(() => {
|
|
7476
|
+
if (!agent) return;
|
|
7477
|
+
return agent.hooks.hook("tool:after", (ctx) => {
|
|
7478
|
+
if (ctx.name === "todowrite") setTick((t) => t + 1);
|
|
7479
|
+
});
|
|
7480
|
+
}, [agent]);
|
|
7481
|
+
const state = useActiveTodos(session);
|
|
7482
|
+
const scrollRef = useRef(null);
|
|
7483
|
+
const inProgressId = state.inProgress?.id ?? null;
|
|
7484
|
+
useEffect(() => {
|
|
7485
|
+
if (!inProgressId) return;
|
|
7486
|
+
const sb = scrollRef.current;
|
|
7487
|
+
if (!sb) return;
|
|
7488
|
+
const handle = requestAnimationFrame(() => {
|
|
7489
|
+
sb.scrollChildIntoView(`todo-row-${inProgressId}`);
|
|
7490
|
+
});
|
|
7491
|
+
return () => cancelAnimationFrame(handle);
|
|
7492
|
+
}, [inProgressId]);
|
|
7493
|
+
const idealHeight = Math.floor((termHeight - 4) * .66);
|
|
7494
|
+
const maxHeight = Math.max(MIN_MODAL_HEIGHT, Math.min(MAX_MODAL_HEIGHT$1, idealHeight));
|
|
7495
|
+
const display = state.todos.length > 0 ? state.todos : state.archive;
|
|
7496
|
+
const total = display.length;
|
|
7497
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
7498
|
+
title: "todos",
|
|
7499
|
+
bottomTitle: total > 0 ? `${total} item${total === 1 ? "" : "s"} · esc close` : "esc close",
|
|
7500
|
+
rightTitle: display.length > 0 ? /* @__PURE__ */ jsx(CountsBadge, { items: display }) : null,
|
|
7501
|
+
maxWidth: 100,
|
|
7502
|
+
maxHeight,
|
|
7503
|
+
children: total === 0 ? /* @__PURE__ */ jsxs("text", { children: [
|
|
7504
|
+
/* @__PURE__ */ jsx("span", {
|
|
7505
|
+
fg: COLOR.mute,
|
|
7506
|
+
children: "(no todos yet — the agent hasn't called "
|
|
7507
|
+
}),
|
|
7508
|
+
/* @__PURE__ */ jsx("span", {
|
|
7509
|
+
fg: COLOR.warn,
|
|
7510
|
+
children: "todowrite"
|
|
7511
|
+
}),
|
|
7512
|
+
/* @__PURE__ */ jsx("span", {
|
|
7513
|
+
fg: COLOR.mute,
|
|
7514
|
+
children: ")"
|
|
7515
|
+
})
|
|
7516
|
+
] }) : /* @__PURE__ */ jsx("box", {
|
|
7517
|
+
style: {
|
|
7518
|
+
flexDirection: "column",
|
|
7519
|
+
flexGrow: 1,
|
|
7520
|
+
flexShrink: 1,
|
|
7521
|
+
overflow: "hidden"
|
|
7522
|
+
},
|
|
7523
|
+
children: /* @__PURE__ */ jsx("scrollbox", {
|
|
7524
|
+
ref: scrollRef,
|
|
7525
|
+
focusable: false,
|
|
7526
|
+
stickyScroll: false,
|
|
7527
|
+
style: {
|
|
7528
|
+
flexGrow: 1,
|
|
7529
|
+
flexShrink: 1
|
|
7530
|
+
},
|
|
7531
|
+
children: display.map((item) => /* @__PURE__ */ jsx(TodoRow, {
|
|
7532
|
+
item,
|
|
7533
|
+
rowId: `todo-row-${item.id}`
|
|
7534
|
+
}, item.id))
|
|
7535
|
+
})
|
|
7536
|
+
})
|
|
7537
|
+
});
|
|
7538
|
+
}
|
|
7539
|
+
/**
|
|
7540
|
+
* Right-aligned top-border badge — "{in-progress} in progress ·
|
|
7541
|
+
* {completed} completed". Empty buckets are dropped so a homogeneous
|
|
7542
|
+
* list reads cleanly. Status order is fixed (in-progress first, then
|
|
7543
|
+
* completed) regardless of which buckets are populated — the badge's
|
|
7544
|
+
* shape stays predictable so the eye lands on the live count instantly.
|
|
7545
|
+
*/
|
|
7546
|
+
function CountsBadge({ items }) {
|
|
7547
|
+
const COLOR = useColors();
|
|
7548
|
+
const counts = {
|
|
7549
|
+
pending: 0,
|
|
7550
|
+
in_progress: 0,
|
|
7551
|
+
completed: 0,
|
|
7552
|
+
cancelled: 0
|
|
7553
|
+
};
|
|
7554
|
+
for (const item of items) counts[item.status] += 1;
|
|
7555
|
+
const parts = [];
|
|
7556
|
+
if (counts.in_progress) parts.push({
|
|
7557
|
+
count: counts.in_progress,
|
|
7558
|
+
label: "in progress",
|
|
7559
|
+
color: COLOR.warn
|
|
7560
|
+
});
|
|
7561
|
+
if (counts.completed) parts.push({
|
|
7562
|
+
count: counts.completed,
|
|
7563
|
+
label: "completed",
|
|
7564
|
+
color: COLOR.accent
|
|
7565
|
+
});
|
|
7566
|
+
if (counts.pending) parts.push({
|
|
7567
|
+
count: counts.pending,
|
|
7568
|
+
label: "pending",
|
|
7569
|
+
color: COLOR.dim
|
|
7570
|
+
});
|
|
7571
|
+
if (counts.cancelled) parts.push({
|
|
7572
|
+
count: counts.cancelled,
|
|
7573
|
+
label: "cancelled",
|
|
7574
|
+
color: COLOR.error
|
|
7575
|
+
});
|
|
7576
|
+
if (parts.length === 0) return null;
|
|
7577
|
+
return /* @__PURE__ */ jsxs("text", {
|
|
7578
|
+
wrapMode: "none",
|
|
7579
|
+
children: [
|
|
7580
|
+
/* @__PURE__ */ jsx("span", {
|
|
7581
|
+
fg: COLOR.mute,
|
|
7582
|
+
children: " "
|
|
7583
|
+
}),
|
|
7584
|
+
parts.map((p, i) => /* @__PURE__ */ jsxs("span", { children: [
|
|
7585
|
+
i > 0 && /* @__PURE__ */ jsx("span", {
|
|
7586
|
+
fg: COLOR.mute,
|
|
7587
|
+
children: " · "
|
|
7588
|
+
}),
|
|
7589
|
+
/* @__PURE__ */ jsx("span", {
|
|
7590
|
+
fg: p.color,
|
|
7591
|
+
children: String(p.count)
|
|
7592
|
+
}),
|
|
7593
|
+
/* @__PURE__ */ jsx("span", {
|
|
7594
|
+
fg: COLOR.mute,
|
|
7595
|
+
children: ` ${p.label}`
|
|
7596
|
+
})
|
|
7597
|
+
] }, p.label)),
|
|
7598
|
+
/* @__PURE__ */ jsx("span", {
|
|
7599
|
+
fg: COLOR.mute,
|
|
7600
|
+
children: " "
|
|
7601
|
+
})
|
|
7602
|
+
]
|
|
7603
|
+
});
|
|
7604
|
+
}
|
|
7605
|
+
//#endregion
|
|
7329
7606
|
//#region src/tui/turn-details-modal.tsx
|
|
7330
7607
|
/** Max chars surfaced in the scrollable preview pane. Long enough that almost everything fits without truncation. */
|
|
7331
7608
|
const PREVIEW_CHAR_MAX = 8e3;
|
|
@@ -9425,6 +9702,13 @@ function AppShell() {
|
|
|
9425
9702
|
}));
|
|
9426
9703
|
return;
|
|
9427
9704
|
}
|
|
9705
|
+
if (matchesBinding(key, keybindings.openTodos) && screen === "chat" && currentSession) {
|
|
9706
|
+
modal.open(/* @__PURE__ */ jsx(TodosModal, {
|
|
9707
|
+
session: sessionRef.current,
|
|
9708
|
+
agent: agentRef.current
|
|
9709
|
+
}));
|
|
9710
|
+
return;
|
|
9711
|
+
}
|
|
9428
9712
|
if (matchesBinding(key, keybindings.enterSelectTurnMode) && screen === "chat" && !busy && !pendingApproval && !pendingInteraction) {
|
|
9429
9713
|
enterSelectMode();
|
|
9430
9714
|
return;
|
|
@@ -9558,6 +9842,7 @@ function AppShell() {
|
|
|
9558
9842
|
settings,
|
|
9559
9843
|
onSubmit: onSubmitPrompt,
|
|
9560
9844
|
session: currentSession,
|
|
9845
|
+
liveSession: sessionRef.current,
|
|
9561
9846
|
pending: pendingApproval,
|
|
9562
9847
|
onApproval: resolveHead,
|
|
9563
9848
|
pendingInteraction,
|