@deepseek-harness-tui/dsh-tui 0.8.8 → 0.9.0
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/README.md +27 -8
- package/bin/dsh-tui.js +1 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +4 -2
- package/lib/types/components/ActivityPicker.d.ts +4 -1
- package/lib/types/components/ActivityPicker.d.ts.map +1 -1
- package/lib/types/components/ActivityPicker.js +2 -2
- package/lib/types/components/BtwPanel.d.ts.map +1 -1
- package/lib/types/components/BtwPanel.js +1 -1
- package/lib/types/components/Chat/SubagentMessage.d.ts +2 -1
- package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -1
- package/lib/types/components/Chat/SubagentMessage.js +11 -3
- package/lib/types/components/CommandSuggestions.d.ts +21 -4
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/CommandSuggestions.js +41 -14
- package/lib/types/components/EffortSlider.d.ts +4 -1
- package/lib/types/components/EffortSlider.d.ts.map +1 -1
- package/lib/types/components/EffortSlider.js +4 -2
- package/lib/types/components/ExtensionDialog.js +6 -2
- package/lib/types/components/FileSuggestions.d.ts +24 -7
- package/lib/types/components/FileSuggestions.d.ts.map +1 -1
- package/lib/types/components/FileSuggestions.js +39 -12
- package/lib/types/components/GoalTodoPanel.d.ts +26 -2
- package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
- package/lib/types/components/GoalTodoPanel.js +86 -17
- package/lib/types/components/HelpMenu.d.ts +7 -1
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +12 -4
- package/lib/types/components/HistorySearchDialog.d.ts +4 -1
- package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
- package/lib/types/components/HistorySearchDialog.js +2 -2
- package/lib/types/components/LangPicker.d.ts +14 -0
- package/lib/types/components/LangPicker.d.ts.map +1 -0
- package/lib/types/components/LangPicker.js +17 -0
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LoadedContextPanel.js +3 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +12 -3
- package/lib/types/components/MessageList.d.ts +43 -2
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +553 -41
- package/lib/types/components/ModelPicker.d.ts +4 -1
- package/lib/types/components/ModelPicker.d.ts.map +1 -1
- package/lib/types/components/ModelPicker.js +2 -2
- package/lib/types/components/PermissionsPicker.d.ts +21 -0
- package/lib/types/components/PermissionsPicker.d.ts.map +1 -0
- package/lib/types/components/PermissionsPicker.js +27 -0
- package/lib/types/components/PlanPicker.d.ts +15 -0
- package/lib/types/components/PlanPicker.d.ts.map +1 -0
- package/lib/types/components/PlanPicker.js +18 -0
- package/lib/types/components/PresetPicker.d.ts +4 -1
- package/lib/types/components/PresetPicker.d.ts.map +1 -1
- package/lib/types/components/PresetPicker.js +2 -2
- package/lib/types/components/PromptInput.d.ts +4 -3
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +248 -29
- package/lib/types/components/RewindPicker.d.ts +12 -1
- package/lib/types/components/RewindPicker.d.ts.map +1 -1
- package/lib/types/components/RewindPicker.js +6 -4
- package/lib/types/components/ScrollbarGutter.d.ts +28 -0
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -0
- package/lib/types/components/ScrollbarGutter.js +68 -0
- package/lib/types/components/Select.d.ts +8 -1
- package/lib/types/components/Select.d.ts.map +1 -1
- package/lib/types/components/Select.js +4 -2
- package/lib/types/components/SkillsPicker.d.ts +4 -1
- package/lib/types/components/SkillsPicker.d.ts.map +1 -1
- package/lib/types/components/SkillsPicker.js +2 -2
- package/lib/types/components/SubagentCard.d.ts +2 -1
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +6 -1
- package/lib/types/components/SubagentDashboard.d.ts +4 -0
- package/lib/types/components/SubagentDashboard.d.ts.map +1 -1
- package/lib/types/components/SubagentDashboard.js +9 -1
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +5 -4
- package/lib/types/components/SuggestionCard.d.ts +63 -0
- package/lib/types/components/SuggestionCard.d.ts.map +1 -0
- package/lib/types/components/SuggestionCard.js +77 -0
- package/lib/types/components/ThemePicker.d.ts +4 -1
- package/lib/types/components/ThemePicker.d.ts.map +1 -1
- package/lib/types/components/ThemePicker.js +2 -2
- package/lib/types/components/ThinkingToggle.d.ts +4 -1
- package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
- package/lib/types/components/ThinkingToggle.js +2 -2
- package/lib/types/components/TimelineRail.d.ts +53 -0
- package/lib/types/components/TimelineRail.d.ts.map +1 -0
- package/lib/types/components/TimelineRail.js +190 -0
- package/lib/types/components/WorkspaceFlowPicker.d.ts +6 -1
- package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -1
- package/lib/types/components/WorkspaceFlowPicker.js +4 -2
- package/lib/types/components/WorkspaceMenuPicker.d.ts +19 -0
- package/lib/types/components/WorkspaceMenuPicker.d.ts.map +1 -0
- package/lib/types/components/WorkspaceMenuPicker.js +19 -0
- package/lib/types/components/WorkspacePicker.d.ts +4 -1
- package/lib/types/components/WorkspacePicker.d.ts.map +1 -1
- package/lib/types/components/WorkspacePicker.js +2 -2
- package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
- package/lib/types/components/approvals/ApprovalPanel.js +5 -1
- package/lib/types/components/design-system/ListItem.d.ts +8 -1
- package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
- package/lib/types/components/design-system/ListItem.js +8 -3
- package/lib/types/components/messages/AssistantTextMessage.d.ts +5 -2
- package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantTextMessage.js +6 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +10 -4
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +8 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +4 -2
- package/lib/types/components/messages/UserPromptMessage.d.ts +2 -1
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +34 -2
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +13 -2
- package/lib/types/components/sessions/SessionListRow.d.ts +4 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +4 -2
- package/lib/types/components/trajectory/HotspotView.d.ts +7 -1
- package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -1
- package/lib/types/components/trajectory/HotspotView.js +8 -2
- package/lib/types/components/trajectory/Ledger.d.ts +9 -1
- package/lib/types/components/trajectory/Ledger.d.ts.map +1 -1
- package/lib/types/components/trajectory/Ledger.js +23 -5
- package/lib/types/components/trajectory/WaveBand.d.ts +10 -1
- package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -1
- package/lib/types/components/trajectory/WaveBand.js +7 -2
- package/lib/types/dsh-adapter/channel.d.ts +16 -5
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +332 -29
- package/lib/types/dsh-adapter/index.d.ts +10 -2
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +4 -1
- package/lib/types/dsh-adapter/plugin.d.ts +0 -9
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +136 -6
- package/lib/types/i18n.d.ts +176 -15
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +51 -8
- package/lib/types/ink/components/AlternateScreen.d.ts.map +1 -1
- package/lib/types/ink/components/AlternateScreen.js +13 -1
- package/lib/types/ink/components/App.d.ts +12 -1
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +101 -4
- package/lib/types/ink/components/ClockContext.d.ts.map +1 -1
- package/lib/types/ink/components/ClockContext.js +2 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +170 -91
- package/lib/types/ink/constants.d.ts +9 -0
- package/lib/types/ink/constants.d.ts.map +1 -1
- package/lib/types/ink/constants.js +9 -0
- package/lib/types/ink/events/click-event.d.ts +7 -16
- package/lib/types/ink/events/click-event.d.ts.map +1 -1
- package/lib/types/ink/events/click-event.js +16 -19
- package/lib/types/ink/events/event-handlers.d.ts +11 -1
- package/lib/types/ink/events/event-handlers.d.ts.map +1 -1
- package/lib/types/ink/events/event-handlers.js +2 -0
- package/lib/types/ink/events/input-event.d.ts +9 -0
- package/lib/types/ink/events/input-event.d.ts.map +1 -1
- package/lib/types/ink/events/input-event.js +4 -0
- package/lib/types/ink/events/pointer-event.d.ts +61 -0
- package/lib/types/ink/events/pointer-event.d.ts.map +1 -0
- package/lib/types/ink/events/pointer-event.js +61 -0
- package/lib/types/ink/events/wheel-event.d.ts +17 -0
- package/lib/types/ink/events/wheel-event.d.ts.map +1 -0
- package/lib/types/ink/events/wheel-event.js +20 -0
- package/lib/types/ink/geometry-trace.d.ts +51 -0
- package/lib/types/ink/geometry-trace.d.ts.map +1 -0
- package/lib/types/ink/geometry-trace.js +83 -0
- package/lib/types/ink/hit-test.d.ts +56 -1
- package/lib/types/ink/hit-test.d.ts.map +1 -1
- package/lib/types/ink/hit-test.js +146 -8
- package/lib/types/ink/ink.d.ts +58 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +230 -29
- package/lib/types/ink/node-cache.d.ts +5 -0
- package/lib/types/ink/node-cache.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.d.ts +8 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +101 -12
- package/lib/types/ink/render-node-to-output.d.ts +10 -0
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +111 -18
- package/lib/types/ink/timeline-rail.d.ts +138 -0
- package/lib/types/ink/timeline-rail.d.ts.map +1 -0
- package/lib/types/ink/timeline-rail.js +179 -0
- package/lib/types/ink/wrap-text.d.ts.map +1 -1
- package/lib/types/ink/wrap-text.js +47 -5
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +819 -337
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +56 -29
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +64 -22
- package/lib/types/screens/StatusLine.d.ts +2 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +17 -1
- package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
- package/lib/types/screens/TrajectoryScene.js +81 -14
- package/lib/types/screens/chatOverlay.d.ts +221 -0
- package/lib/types/screens/chatOverlay.d.ts.map +1 -0
- package/lib/types/screens/chatOverlay.js +114 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +42 -6
- package/lib/types/tuiDisplayPrefs.d.ts +15 -0
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +9 -0
- package/lib/types/utils/debug.d.ts +10 -0
- package/lib/types/utils/debug.d.ts.map +1 -1
- package/lib/types/utils/debug.js +24 -0
- package/lib/types/utils/paths.d.ts.map +1 -1
- package/lib/types/utils/paths.js +1 -0
- package/package.json +4 -2
|
@@ -221,7 +221,7 @@ function HeaderTitle({ name, title, isTerminal, displayArgs, argsLanguage, nameC
|
|
|
221
221
|
* output, read content — instead of the raw result dump (mirroring Claude Code's `AssistantToolUseMessage.tsx` + the dsh-tools presentation views the
|
|
222
222
|
* channel captures per call).
|
|
223
223
|
*/
|
|
224
|
-
export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected = false, isExpanded = false, footnote, diffLayout = 'auto', toolBackground = 'none', }) {
|
|
224
|
+
export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected = false, isExpanded = false, onClick, footnote, diffLayout = 'auto', toolBackground = 'none', }) {
|
|
225
225
|
const isRunning = tool.status === 'running';
|
|
226
226
|
const isError = tool.status === 'error';
|
|
227
227
|
const displayArgs = verbose ? tool.argsFull ?? tool.argsText : tool.argsText;
|
|
@@ -286,9 +286,11 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
286
286
|
: ordinaryToolBackground === 'strong'
|
|
287
287
|
? 'toolCardBackground'
|
|
288
288
|
: undefined;
|
|
289
|
-
return (_jsx(Box, { ref: viewportRef, flexDirection: "row", justifyContent: "space-between", marginTop: addMargin ? 1 : 0, width: "100%",
|
|
289
|
+
return (_jsx(Box, { ref: viewportRef, flexDirection: "row", justifyContent: "space-between", marginTop: addMargin ? 1 : 0, width: "100%", onClick: onClick,
|
|
290
290
|
// Only selection paints a highlight; the configured treatment applies
|
|
291
291
|
// to an ordinary card. Diff line tints stay - they are content, not chrome.
|
|
292
|
+
// No hover tint: the card stays visually quiet until clicked (user
|
|
293
|
+
// feedback — row-hover color changes read as noise in the transcript).
|
|
292
294
|
backgroundColor: isSelected ? 'messageActionsBackground' : ordinaryBackground, children: _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { flexDirection: "row", flexWrap: "nowrap", minWidth: minWidth, children: [_jsx(ToolUseLoader, { shouldAnimate: isRunning, isUnresolved: isRunning, isError: isError, toolName: tool.name }), _jsx(HeaderTitle, { name: name, title: headerTitle, isTerminal: headerIsTerminal, displayArgs: displayArgs, argsLanguage: argsLanguage, nameColor: toolNameColor(tool.name) }), !isRunning && (_jsx(Box, { flexWrap: "nowrap", children: _jsx(Text, { dimColor: true, children: elapsedText }) }))] }), useSplitDiff && view?.card === 'diff' ? (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: GUTTER_FIRST }) }), _jsx(SplitDiffView, { diffs: view.diffs, width: columns - 4, maxRows: DIFF_BODY_MAX_LINES, verbose: verbose, toolBackground: ordinaryToolBackground })] })) : (rendered.map((line, index) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { color: line.tone === 'add'
|
|
293
295
|
? 'diffAddedWord'
|
|
294
296
|
: line.tone === 'del'
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
2
3
|
type Props = {
|
|
3
4
|
text: string;
|
|
4
5
|
/** Adds the top margin between turns (CC: addMargin). */
|
|
5
6
|
addMargin: boolean;
|
|
6
7
|
/** Message-selection mode highlight. */
|
|
7
8
|
isSelected?: boolean;
|
|
8
|
-
onClick?(): void;
|
|
9
|
+
onClick?(event: ClickEvent): void;
|
|
9
10
|
};
|
|
10
11
|
/**
|
|
11
12
|
* User prompt bubble: `❯ text` in bold briefLabelYou gold with no background
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserPromptMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/UserPromptMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"UserPromptMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/UserPromptMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAEjE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAA;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAClC,CAAA;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,SAAS,EACT,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA6BzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AskUserQuestionPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/AskUserQuestionPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AASvE,MAAM,MAAM,yBAAyB,GAAG;IACtC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;QAC9B;;oEAE4D;QAC5D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;QAClC;0EACkE;QAClE,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAC9B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"AskUserQuestionPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/AskUserQuestionPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AASvE,MAAM,MAAM,yBAAyB,GAAG;IACtC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;QAC9B;;oEAE4D;QAC5D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;QAClC;0EACkE;QAClE,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAC9B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,SAAS,CA+Y7C"}
|
|
@@ -241,7 +241,39 @@ export function AskUserQuestionPanel({ question, position, total, answered, onAn
|
|
|
241
241
|
const remaining = total - answered;
|
|
242
242
|
const headerTitle = ` ${t('question-header-progress', { position, total, remaining: remaining > 1 ? t('question-remaining-more', { n: remaining }) : '' })} `;
|
|
243
243
|
const cursorChar = customCursor < customText.length ? customText[customCursor] : ' ';
|
|
244
|
-
|
|
244
|
+
/** Mouse: click the input row to focus it (same as Tab). */
|
|
245
|
+
const focusInputRow = () => {
|
|
246
|
+
if (hideCustomInput)
|
|
247
|
+
return;
|
|
248
|
+
setFocusIndex(options.length);
|
|
249
|
+
setError(null);
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Mouse: click an option row. Multi-select toggles the checkmark (same as
|
|
253
|
+
* Space); single-select answers immediately with that option plus any
|
|
254
|
+
* typed text (same as focusing the row and pressing Enter) — one click =
|
|
255
|
+
* one answer, matching ApprovalPanel's click semantics.
|
|
256
|
+
*/
|
|
257
|
+
const clickOption = (index) => {
|
|
258
|
+
if (multiSelect) {
|
|
259
|
+
setChecked(previous => {
|
|
260
|
+
const next = new Set(previous);
|
|
261
|
+
if (next.has(index))
|
|
262
|
+
next.delete(index);
|
|
263
|
+
else
|
|
264
|
+
next.add(index);
|
|
265
|
+
return next;
|
|
266
|
+
});
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const label = options[index]?.label;
|
|
270
|
+
if (label === undefined)
|
|
271
|
+
return;
|
|
272
|
+
const text = customText.trim();
|
|
273
|
+
onAnswer({ selected: [label], ...(text !== '' ? { custom: text } : {}) });
|
|
274
|
+
};
|
|
275
|
+
const [hoverIndex, setHoverIndex] = React.useState(-1);
|
|
276
|
+
const renderInputRow = () => (_jsxs(Box, { flexDirection: "row", marginTop: inputFocused ? 1 : 0, onClick: focusInputRow, onMouseEnter: () => setHoverIndex(options.length), onMouseLeave: () => setHoverIndex(current => (current === options.length ? -1 : current)), backgroundColor: hoverIndex === options.length && !inputFocused ? 'userMessageBackgroundHover' : undefined, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : undefined, bold: inputFocused, children: inputFocused ? POINTER : ' ' }) }), _jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : 'suggestion', children: PENCIL }) }), _jsxs(Box, { flexDirection: "row", marginLeft: 1, children: [_jsx(Text, { bold: inputFocused, color: inputFocused ? 'claude' : 'suggestion', children: t('question-custom-tab') }), attached !== null && (_jsx(Text, { color: "suggestion", children: t('question-attached-label', { label: attached }) })), _jsx(Text, { dimColor: true, children: "\uFF1A" }), customText === '' && !inputFocused ? (_jsx(Text, { ref: caretRef, dimColor: true, children: t('question-direct-input') })) : (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: customText.slice(0, customCursor) }), inputFocused
|
|
245
277
|
? _jsx(Text, { ref: caretRef, inverse: true, children: cursorChar })
|
|
246
278
|
: _jsx(Text, { ref: caretRef, color: "suggestion", children: "\u258F" }), _jsx(Text, { wrap: "wrap", children: customText.slice(inputFocused ? customCursor + 1 : customCursor) })] }))] })] }));
|
|
247
279
|
const renderOptions = () => (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [options.slice(optionWindow.start, optionWindow.end).map((option, index) => {
|
|
@@ -259,7 +291,7 @@ export function AskUserQuestionPanel({ question, position, total, answered, onAn
|
|
|
259
291
|
const description = windowedOptions
|
|
260
292
|
? option.description?.replace(/\s+/gu, ' ').trim()
|
|
261
293
|
: option.description;
|
|
262
|
-
return (_jsxs(Box, { flexDirection: "row", marginTop: !windowedOptions && focused ? 1 : 0, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: focused, children: pointer }) }), _jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: selected, children: selected ? (multiSelect ? CHECKED : '●') : UNCHECKED }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [_jsx(Text, { bold: focused || selected, color: focused ? 'claude' : undefined, wrap: windowedOptions ? 'truncate' : 'wrap', children: label }), description !== undefined && (_jsx(Text, { dimColor: true, wrap: windowedOptions ? 'truncate' : 'wrap', children: description }))] })] }, `${absoluteIndex}:${option.label}`));
|
|
294
|
+
return (_jsxs(Box, { flexDirection: "row", marginTop: !windowedOptions && focused ? 1 : 0, onClick: () => clickOption(absoluteIndex), onMouseEnter: () => setHoverIndex(absoluteIndex), onMouseLeave: () => setHoverIndex(current => (current === absoluteIndex ? -1 : current)), backgroundColor: hoverIndex === absoluteIndex && !focused ? 'userMessageBackgroundHover' : undefined, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: focused, children: pointer }) }), _jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: selected, children: selected ? (multiSelect ? CHECKED : '●') : UNCHECKED }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [_jsx(Text, { bold: focused || selected, color: focused ? 'claude' : undefined, wrap: windowedOptions ? 'truncate' : 'wrap', children: label }), description !== undefined && (_jsx(Text, { dimColor: true, wrap: windowedOptions ? 'truncate' : 'wrap', children: description }))] })] }, `${absoluteIndex}:${option.label}`));
|
|
263
295
|
}), hideCustomInput ? null : renderInputRow()] }));
|
|
264
296
|
const hintParts = inputFocused
|
|
265
297
|
? [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlanReviewPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/PlanReviewPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAKvE,MAAM,MAAM,oBAAoB,GAAG;IACjC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAC9B,CAAA;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,oBAAoB,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"PlanReviewPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/PlanReviewPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAKvE,MAAM,MAAM,oBAAoB,GAAG;IACjC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAC9B,CAAA;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,oBAAoB,GAAG,KAAK,CAAC,SAAS,CAmQxC"}
|
|
@@ -168,11 +168,22 @@ export function PlanReviewPanel({ question, onAnswer, onCancel, }) {
|
|
|
168
168
|
}
|
|
169
169
|
}, { isActive: true });
|
|
170
170
|
const cursorChar = cursor < feedback.length ? feedback[cursor] : ' ';
|
|
171
|
+
/** Mouse: click a decision row = focus it + submit (same as Enter). */
|
|
172
|
+
const [hoverIndex, setHoverIndex] = React.useState(-1);
|
|
173
|
+
const clickOption = (index) => {
|
|
174
|
+
setFocusIndex(index);
|
|
175
|
+
submitOption(index);
|
|
176
|
+
};
|
|
177
|
+
/** Mouse: click the feedback row to focus it. */
|
|
178
|
+
const focusFeedbackRow = () => {
|
|
179
|
+
setFocusIndex(options.length);
|
|
180
|
+
setError(null);
|
|
181
|
+
};
|
|
171
182
|
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, paddingLeft: 2, paddingRight: 2, width: "100%", children: [_jsx(Divider, { color: "permission", title: ` ${question.header ?? t('plan-review-fallback-header')} `, padding: 4 }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, wrap: "wrap", children: question.question }), question.detail !== undefined && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(Markdown, { children: question.detail }) }))] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [options.map((option, index) => {
|
|
172
183
|
const focused = index === focusIndex;
|
|
173
184
|
const isApprove = option.label === approveLabel;
|
|
174
|
-
return (_jsxs(Box, { flexDirection: "row", marginTop: focused ? 1 : 0, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: focused, children: focused ? POINTER : ' ' }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [_jsxs(Text, { bold: focused, color: focused || isApprove ? 'claude' : undefined, wrap: "wrap", children: [index + 1, ". ", option.label] }), option.description !== undefined && (_jsx(Text, { dimColor: true, wrap: "wrap", children: option.description }))] })] }, option.label));
|
|
175
|
-
}), _jsxs(Box, { flexDirection: "row", marginTop: inputFocused ? 1 : 0, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : undefined, bold: inputFocused, children: inputFocused ? POINTER : ' ' }) }), _jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : 'suggestion', children: PENCIL }) }), _jsx(Box, { flexDirection: "row", marginLeft: 1, children: feedback === '' && !inputFocused ? (_jsx(Text, { ref: caretRef, dimColor: true, children: t('plan-review-feedback-placeholder') })) : (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: feedback.slice(0, cursor) }), inputFocused
|
|
185
|
+
return (_jsxs(Box, { flexDirection: "row", marginTop: focused ? 1 : 0, onClick: () => clickOption(index), onMouseEnter: () => setHoverIndex(index), onMouseLeave: () => setHoverIndex(current => (current === index ? -1 : current)), backgroundColor: hoverIndex === index && !focused ? 'userMessageBackgroundHover' : undefined, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: focused ? 'claude' : undefined, bold: focused, children: focused ? POINTER : ' ' }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 1, children: [_jsxs(Text, { bold: focused, color: focused || isApprove ? 'claude' : undefined, wrap: "wrap", children: [index + 1, ". ", option.label] }), option.description !== undefined && (_jsx(Text, { dimColor: true, wrap: "wrap", children: option.description }))] })] }, option.label));
|
|
186
|
+
}), _jsxs(Box, { flexDirection: "row", marginTop: inputFocused ? 1 : 0, onClick: focusFeedbackRow, onMouseEnter: () => setHoverIndex(options.length), onMouseLeave: () => setHoverIndex(current => (current === options.length ? -1 : current)), backgroundColor: hoverIndex === options.length && !inputFocused ? 'userMessageBackgroundHover' : undefined, children: [_jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : undefined, bold: inputFocused, children: inputFocused ? POINTER : ' ' }) }), _jsx(Box, { width: 1, flexShrink: 0, children: _jsx(Text, { color: inputFocused ? 'claude' : 'suggestion', children: PENCIL }) }), _jsx(Box, { flexDirection: "row", marginLeft: 1, children: feedback === '' && !inputFocused ? (_jsx(Text, { ref: caretRef, dimColor: true, children: t('plan-review-feedback-placeholder') })) : (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: feedback.slice(0, cursor) }), inputFocused
|
|
176
187
|
? _jsx(Text, { ref: caretRef, inverse: true, children: cursorChar })
|
|
177
188
|
: _jsx(Text, { ref: caretRef, color: "suggestion", children: "\u258F" }), _jsx(Text, { wrap: "wrap", children: feedback.slice(inputFocused ? cursor + 1 : cursor) })] })) })] })] }), error !== null && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "error", children: error }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t('plan-review-hint') }) })] }));
|
|
178
189
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
2
3
|
import type { SessionSummary } from '../../dsh-adapter/sessions/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* One session in the browser's list: a title line and a metadata line.
|
|
@@ -13,7 +14,7 @@ import type { SessionSummary } from '../../dsh-adapter/sessions/index.js';
|
|
|
13
14
|
* stay exactly two lines at every terminal width, and a row that wraps
|
|
14
15
|
* destroys the alignment that lets the eye scan a list at all.
|
|
15
16
|
*/
|
|
16
|
-
export declare function SessionListRow({ session, width, depth, focused, now, }: {
|
|
17
|
+
export declare function SessionListRow({ session, width, depth, focused, now, onClick, }: {
|
|
17
18
|
session: SessionSummary;
|
|
18
19
|
/** Columns available to the row, indentation included. */
|
|
19
20
|
width: number;
|
|
@@ -22,5 +23,7 @@ export declare function SessionListRow({ session, width, depth, focused, now, }:
|
|
|
22
23
|
focused: boolean;
|
|
23
24
|
/** Epoch ms used for every relative time in this render pass. */
|
|
24
25
|
now: number;
|
|
26
|
+
/** 鼠标点击行(fullscreen):恢复该会话(与 Enter 同路径)。 */
|
|
27
|
+
onClick?(event: ClickEvent): void;
|
|
25
28
|
}): React.ReactNode;
|
|
26
29
|
//# sourceMappingURL=SessionListRow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionListRow.d.ts","sourceRoot":"","sources":["../../../../src/components/sessions/SessionListRow.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SessionListRow.d.ts","sourceRoot":"","sources":["../../../../src/components/sessions/SessionListRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAQjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,GAAG,EACH,OAAO,GACR,EAAE;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,4CAA4C;IAC5C,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAClC,GAAG,KAAK,CAAC,SAAS,CA4ClB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { Box, Text } from '../../ui.js';
|
|
3
4
|
import { t } from '../../i18n.js';
|
|
4
5
|
import { formatBytes, formatWhen, kindMark, titleColor, truncateWidth, } from '../../sessions/format.js';
|
|
@@ -15,11 +16,12 @@ import { formatBytes, formatWhen, kindMark, titleColor, truncateWidth, } from '.
|
|
|
15
16
|
* stay exactly two lines at every terminal width, and a row that wraps
|
|
16
17
|
* destroys the alignment that lets the eye scan a list at all.
|
|
17
18
|
*/
|
|
18
|
-
export function SessionListRow({ session, width, depth, focused, now, }) {
|
|
19
|
+
export function SessionListRow({ session, width, depth, focused, now, onClick, }) {
|
|
19
20
|
const indent = depth * 2;
|
|
20
21
|
// Two cells for the focus marker, plus the indent for a nested run.
|
|
21
22
|
const body = Math.max(8, width - 2 - indent);
|
|
22
23
|
const mark = kindMark(session.kind);
|
|
24
|
+
const [hovered, setHovered] = useState(false);
|
|
23
25
|
const facts = [formatWhen(session.updatedAt, now)];
|
|
24
26
|
if (session.branch !== undefined)
|
|
25
27
|
facts.push(session.branch);
|
|
@@ -31,5 +33,5 @@ export function SessionListRow({ session, width, depth, focused, now, }) {
|
|
|
31
33
|
if (session.childCount > 0 && depth === 0) {
|
|
32
34
|
facts.push(t('session-children', { n: session.childCount }));
|
|
33
35
|
}
|
|
34
|
-
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsxs(Box, { children: [_jsx(Text, { color: focused ? 'suggestion' : 'subtle', children: `${' '.repeat(indent)}${focused ? '❯ ' : ' '}` }), mark !== undefined && _jsx(Text, { color: mark.color, children: `${mark.glyph} ` }), _jsx(Text, { color: titleColor(session.title.source, focused), bold: focused, children: truncateWidth(session.label ?? session.title.text, body - (mark === undefined ? 0 : 2)) })] }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: `${' '.repeat(indent + 2)}${truncateWidth(facts.join(' · '), body)}` }) })] }));
|
|
36
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, onClick: onClick, onMouseEnter: onClick !== undefined ? () => setHovered(true) : undefined, onMouseLeave: onClick !== undefined ? () => setHovered(false) : undefined, backgroundColor: hovered && !focused ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { children: [_jsx(Text, { color: focused ? 'suggestion' : 'subtle', children: `${' '.repeat(indent)}${focused ? '❯ ' : ' '}` }), mark !== undefined && _jsx(Text, { color: mark.color, children: `${mark.glyph} ` }), _jsx(Text, { color: titleColor(session.title.source, focused), bold: focused, children: truncateWidth(session.label ?? session.title.text, body - (mark === undefined ? 0 : 2)) })] }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: `${' '.repeat(indent + 2)}${truncateWidth(facts.join(' · '), body)}` }) })] }));
|
|
35
37
|
}
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { HotspotRow, HotspotSort, TrajAggregate } from '../../dsh-adapter/types.js';
|
|
3
3
|
/** Flatten the three sections into the single list the cursor walks. */
|
|
4
4
|
export declare function hotspotRows(agg: TrajAggregate): HotspotRow[];
|
|
5
|
-
export declare function HotspotView({ agg, sort, width, height, cursor, tick, switchTick, }: {
|
|
5
|
+
export declare function HotspotView({ agg, sort, width, height, cursor, tick, switchTick, onRowClick, }: {
|
|
6
6
|
agg: TrajAggregate;
|
|
7
7
|
sort: HotspotSort;
|
|
8
8
|
width: number;
|
|
@@ -10,5 +10,11 @@ export declare function HotspotView({ agg, sort, width, height, cursor, tick, sw
|
|
|
10
10
|
cursor: number;
|
|
11
11
|
tick: number;
|
|
12
12
|
switchTick: number;
|
|
13
|
+
/**
|
|
14
|
+
* Mouse pick (fullscreen): reports the clicked row's cursor index — the
|
|
15
|
+
* scene jumps back to the timeline positioned on the group's first member
|
|
16
|
+
* (same path as the keyboard Enter). Hover shows a dim `▸` pointer.
|
|
17
|
+
*/
|
|
18
|
+
onRowClick?: (cursorIndex: number) => void;
|
|
13
19
|
}): React.ReactNode;
|
|
14
20
|
//# sourceMappingURL=HotspotView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HotspotView.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/HotspotView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AA6CxF,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,EAAE,CAE5D;AAOD,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,UAAU,GACX,EAAE;IACD,GAAG,EAAE,aAAa,CAAA;IAClB,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"HotspotView.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/HotspotView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AA6CxF,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,EAAE,CAE5D;AAOD,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,UAAU,EACV,UAAU,GACX,EAAE;IACD,GAAG,EAAE,aAAa,CAAA;IAClB,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3C,GAAG,KAAK,CAAC,SAAS,CA6FlB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import { Box, Text, useTheme } from '../../ui.js';
|
|
3
4
|
import { getTheme } from '../../theme.js';
|
|
4
5
|
import { formatDuration, formatTokens, truncateWidth } from '../../trajectory/format.js';
|
|
@@ -40,9 +41,10 @@ export function hotspotRows(agg) {
|
|
|
40
41
|
function valueOf(row, sort) {
|
|
41
42
|
return sort === 'count' ? row.count : sort === 'tokens' ? row.tokens : row.totalMs;
|
|
42
43
|
}
|
|
43
|
-
export function HotspotView({ agg, sort, width, height, cursor, tick, switchTick, }) {
|
|
44
|
+
export function HotspotView({ agg, sort, width, height, cursor, tick, switchTick, onRowClick, }) {
|
|
44
45
|
const [themeName] = useTheme();
|
|
45
46
|
const theme = getTheme(themeName);
|
|
47
|
+
const [hoverIndex, setHoverIndex] = React.useState(-1);
|
|
46
48
|
const labelWidth = Math.min(18, Math.max(10, Math.floor(width * 0.16)));
|
|
47
49
|
const barWidth = Math.max(6, Math.min(30, width - labelWidth - 34));
|
|
48
50
|
// Build the flat list once, tagging each row with its section's scale.
|
|
@@ -72,12 +74,16 @@ export function HotspotView({ agg, sort, width, height, cursor, tick, switchTick
|
|
|
72
74
|
}
|
|
73
75
|
const { row, max, colorKey } = entry;
|
|
74
76
|
const focused = entry.cursorIndex === cursor;
|
|
77
|
+
// 鼠标:行点击跳回 timeline 定位;悬停轻指示(dim ▸,不刷背景)
|
|
78
|
+
const hovered = onRowClick !== undefined && hoverIndex === entry.cursorIndex;
|
|
75
79
|
// Stagger the settle by row so a section reads top-down on switch.
|
|
76
80
|
const dim = reproject(tick - offset, switchTick);
|
|
77
81
|
const base = row.error === true ? theme.error : theme[colorKey];
|
|
78
82
|
const stats = `${row.count}×` +
|
|
79
83
|
(row.tokens > 0 ? ` · ${formatTokens(row.tokens)}` : '') +
|
|
80
84
|
(row.count > 0 && row.totalMs > 0 ? ` · ⌀${formatDuration(row.totalMs / row.count)}` : '');
|
|
81
|
-
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1,
|
|
85
|
+
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, onClick: onRowClick === undefined ? undefined : () => onRowClick(entry.cursorIndex), onMouseEnter: onRowClick === undefined ? undefined : () => setHoverIndex(entry.cursorIndex), onMouseLeave: onRowClick === undefined
|
|
86
|
+
? undefined
|
|
87
|
+
: () => setHoverIndex(previous => (previous === entry.cursorIndex ? -1 : previous)), children: [_jsx(Box, { flexShrink: 0, width: 2, children: _jsx(Text, { color: focused ? 'suggestion' : 'inactive', children: focused || hovered ? '▸' : ' ' }) }), _jsx(Box, { flexShrink: 0, width: labelWidth, children: _jsx(Text, { color: focused ? 'suggestion' : row.error === true ? 'error' : undefined, children: truncateWidth(row.label, labelWidth) }) }), _jsx(Box, { flexShrink: 0, width: barWidth, children: _jsx(Text, { color: mix(base, theme.background, dim), children: bar(valueOf(row, sort), max, barWidth) }) }), _jsx(Box, { flexShrink: 0, width: 8, justifyContent: "flex-end", children: _jsx(Text, { bold: true, color: row.error === true ? 'error' : undefined, children: formatDuration(row.totalMs) }) }), _jsx(Box, { flexShrink: 1, overflow: "hidden", children: _jsx(Text, { color: "subtle", children: truncateWidth(stats, Math.max(4, width - labelWidth - barWidth - 16)) }) })] }, `r${entry.cursorIndex}`));
|
|
82
88
|
}) }));
|
|
83
89
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
2
3
|
import type { TrajNode } from '../../dsh-adapter/types.js';
|
|
3
|
-
export declare function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, }: {
|
|
4
|
+
export declare function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, onRowClick, }: {
|
|
4
5
|
/** The (possibly filtered) ledger. */
|
|
5
6
|
rows: readonly TrajNode[];
|
|
6
7
|
/** Index of the first visible row. */
|
|
@@ -16,5 +17,12 @@ export declare function Ledger({ rows, start, height, cursor, width, tick, arriv
|
|
|
16
17
|
arrivalTick: number;
|
|
17
18
|
/** Rows at or after this index are the ones that just arrived. */
|
|
18
19
|
arrivalFrom: number;
|
|
20
|
+
/**
|
|
21
|
+
* Mouse pick (fullscreen): reports the clicked row's absolute index — the
|
|
22
|
+
* scene jumps the cursor to it (same semantics as the keyboard jumps).
|
|
23
|
+
* Hover on a non-focused row shows a dim `▸` pointer — light indication,
|
|
24
|
+
* no background wash (the ledger is content, not a menu).
|
|
25
|
+
*/
|
|
26
|
+
onRowClick?: (index: number, event: ClickEvent) => void;
|
|
19
27
|
}): React.ReactNode;
|
|
20
28
|
//# sourceMappingURL=Ledger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Ledger.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/Ledger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Ledger.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/Ledger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAgBjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AA6C1D,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,IAAI,EACJ,WAAW,EACX,WAAW,EACX,UAAU,GACX,EAAE;IACD,sCAAsC;IACtC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;IACzB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CACxD,GAAG,KAAK,CAAC,SAAS,CAsKlB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import { Box, Text, useTheme } from '../../ui.js';
|
|
3
4
|
import { burstDurationMs, burstErrors, previewText } from '../../dsh-adapter/trajectory/index.js';
|
|
4
5
|
import { costGlyph, formatDuration, formatClock, heatColor, KIND_BADGE, KIND_BADGE_BG, KIND_FG, KIND_GLYPH, ledgerLayout, } from '../../trajectory/format.js';
|
|
@@ -46,9 +47,10 @@ function spineGlyph(rows, index) {
|
|
|
46
47
|
return SPINE.close;
|
|
47
48
|
return SPINE.mid;
|
|
48
49
|
}
|
|
49
|
-
export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, }) {
|
|
50
|
+
export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, onRowClick, }) {
|
|
50
51
|
const [themeName] = useTheme();
|
|
51
52
|
const theme = getTheme(themeName);
|
|
53
|
+
const [hoverIndex, setHoverIndex] = React.useState(-1);
|
|
52
54
|
const layout = ledgerLayout(width);
|
|
53
55
|
const visible = rows.slice(start, start + height);
|
|
54
56
|
const arriving = arrive(tick, arrivalTick);
|
|
@@ -65,6 +67,22 @@ export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick,
|
|
|
65
67
|
const running = node.status === 'running';
|
|
66
68
|
const isNew = index >= arrivalFrom && arriving > 0;
|
|
67
69
|
const duration = node.burst === undefined ? node.durationMs : burstDurationMs(node.burst);
|
|
70
|
+
// 鼠标:行点击跳光标;悬停在非焦点行亮出 dim ▸(轻指示,不刷背景)
|
|
71
|
+
const hovered = onRowClick !== undefined && hoverIndex === index;
|
|
72
|
+
const pointer = focused || hovered ? '▸' : ' ';
|
|
73
|
+
const rowEvents = onRowClick === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: {
|
|
76
|
+
onClick: (event) => {
|
|
77
|
+
onRowClick(index, event);
|
|
78
|
+
},
|
|
79
|
+
onMouseEnter: () => {
|
|
80
|
+
setHoverIndex(index);
|
|
81
|
+
},
|
|
82
|
+
onMouseLeave: () => {
|
|
83
|
+
setHoverIndex(previous => (previous === index ? -1 : previous));
|
|
84
|
+
},
|
|
85
|
+
};
|
|
68
86
|
// ── structural rows are RULES, not rows ────────────────────────────
|
|
69
87
|
//
|
|
70
88
|
// A ledger with five hundred entries needs chapters. Turn and step
|
|
@@ -82,7 +100,7 @@ export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick,
|
|
|
82
100
|
// attention than the work between them. Only the turn, which is the
|
|
83
101
|
// session's actual chapter break, gets a rule.
|
|
84
102
|
if (!isTurn) {
|
|
85
|
-
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: "subtle", children: `${
|
|
103
|
+
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, ...rowEvents, children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: "subtle", children: `${pointer}╵` }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { color: focused ? 'suggestion' : 'subtle', wrap: "truncate", children: node.label }) }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: heatColor(duration), children: costGlyph(duration) }) }), _jsx(Box, { flexShrink: 0, justifyContent: "flex-end", width: 7, children: _jsx(Text, { color: heatColor(duration), children: right }) })] }, `${node.seq}:step`));
|
|
86
104
|
}
|
|
87
105
|
const tone = failed ? 'error' : running ? 'success' : 'inactiveShimmer';
|
|
88
106
|
// Idle before a turn is wall-clock the session spent waiting on the
|
|
@@ -92,9 +110,9 @@ export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick,
|
|
|
92
110
|
const previous = rows[index - 1];
|
|
93
111
|
const idle = previous === undefined ? 0 : node.time - (previous.time + (previous.durationMs ?? 0));
|
|
94
112
|
const idleText = idle >= IDLE_FLOOR_MS ? ` ⋯ ${formatDuration(idle)}` : '';
|
|
95
|
-
const head = `${
|
|
113
|
+
const head = `${pointer}━━ ${node.label}${idleText} `;
|
|
96
114
|
const fill = Math.max(2, width - stringWidth(head) - stringWidth(right) - 2);
|
|
97
|
-
return (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { color: tone, bold: true, children: [`${
|
|
115
|
+
return (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, ...rowEvents, children: _jsxs(Text, { color: tone, bold: true, children: [`${pointer}━━ ${node.label}`, _jsx(Text, { color: "subtle", children: idleText }), _jsx(Text, { color: "inactive", children: ` ${'━'.repeat(fill)} ` }), _jsx(Text, { color: failed ? 'error' : heatColor(duration), children: right })] }) }, `${node.seq}:turn`));
|
|
98
116
|
}
|
|
99
117
|
const spineColor = failed ? 'error' : running ? 'success' : node.seed === true ? 'subtle' : 'inactive';
|
|
100
118
|
const badgeBg = KIND_BADGE_BG[node.kind];
|
|
@@ -107,6 +125,6 @@ export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick,
|
|
|
107
125
|
const outcome = layout.outcome && node.outcome !== undefined && node.outcome !== ''
|
|
108
126
|
? previewText(node.outcome, Math.max(8, Math.floor(layout.detail * 0.3)))
|
|
109
127
|
: '';
|
|
110
|
-
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, children: [_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { color: spineColor, children: [
|
|
128
|
+
return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, ...rowEvents, children: [_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { color: spineColor, children: [pointer, spineGlyph(rows, index)] }) }), layout.index && (_jsx(Box, { flexShrink: 0, width: 8, children: _jsx(Text, { color: "subtle", children: formatClock(node.time) }) })), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: isNew ? mix(theme[KIND_FG[node.kind]], theme.text, arriving) : KIND_FG[node.kind], backgroundColor: badgeBg, bold: true, children: badge }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsxs(Text, { wrap: "truncate", color: focused ? 'suggestion' : node.seed === true ? 'subtle' : undefined, children: [label, detail === '' ? '' : ' ', _jsx(Text, { color: focused ? 'suggestion' : 'inactive', children: detail }), outcome === '' ? '' : _jsx(Text, { color: "subtle", children: ` → ${outcome}` })] }) }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: running ? 'success' : heatColor(duration), children: costGlyph(duration) }) }), _jsx(Box, { flexShrink: 0, justifyContent: "flex-end", width: 7, children: _jsx(Text, { color: running ? 'success' : heatColor(duration), children: running ? '…' : duration === undefined ? '' : formatDuration(duration) }) })] }, `${node.seq}:${node.kind}`));
|
|
111
129
|
}) }));
|
|
112
130
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
2
3
|
import type { WaveBand as Band } from '../../dsh-adapter/types.js';
|
|
3
|
-
export declare function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, }: {
|
|
4
|
+
export declare function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, onColumnClick, }: {
|
|
4
5
|
band: Band;
|
|
5
6
|
/** Rendered width in cells; equals `band.buckets.length`. */
|
|
6
7
|
width: number;
|
|
@@ -19,6 +20,14 @@ export declare function WaveBand({ band, width, cursorColumn, viewportStart, vie
|
|
|
19
20
|
tick: number;
|
|
20
21
|
/** Tick the most recent alert was triggered on. */
|
|
21
22
|
alertTick: number;
|
|
23
|
+
/**
|
|
24
|
+
* Mouse pick (fullscreen): reports the clicked column (0-based within the
|
|
25
|
+
* band; the ruler row counts too — its ▐▌ bracket is the seek affordance).
|
|
26
|
+
* The scene jumps to that column's nearest event via bucket.firstIndex,
|
|
27
|
+
* which empty columns inherit from their predecessor for exactly this
|
|
28
|
+
* purpose. No hover: column density makes per-cell indication noise.
|
|
29
|
+
*/
|
|
30
|
+
onColumnClick?: (column: number, event: ClickEvent) => void;
|
|
22
31
|
}): React.ReactNode;
|
|
23
32
|
/**
|
|
24
33
|
* Convert a theme colour to the `#rrggbb` form chalk needs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WaveBand.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/WaveBand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"WaveBand.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/WaveBand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAIjE,OAAO,KAAK,EAAE,QAAQ,IAAI,IAAI,EAAe,MAAM,4BAA4B,CAAA;AAmD/E,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,aAAa,GACd,EAAE;IACD,IAAI,EAAE,IAAI,CAAA;IACV,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC7B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CAC5D,GAAG,KAAK,CAAC,SAAS,CA2GlB;AAED;;;;;;GAMG;AACH,iBAAS,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrC;AAED,6EAA6E;AAC7E,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAA"}
|
|
@@ -50,7 +50,7 @@ function channelColor(channel, theme) {
|
|
|
50
50
|
default: return theme.subtle;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
export function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, }) {
|
|
53
|
+
export function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, onColumnClick, }) {
|
|
54
54
|
const [themeName] = useTheme();
|
|
55
55
|
const theme = getTheme(themeName);
|
|
56
56
|
if (band.buckets.length === 0) {
|
|
@@ -123,7 +123,12 @@ export function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd
|
|
|
123
123
|
? chalk.hex(toHex(theme.permission))(glyph)
|
|
124
124
|
: chalk.hex(toHex(theme.subtle))(glyph);
|
|
125
125
|
}
|
|
126
|
-
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0,
|
|
126
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, onClick: onColumnClick === undefined
|
|
127
|
+
? undefined
|
|
128
|
+
: (event) => {
|
|
129
|
+
const column = Math.max(0, Math.min(band.buckets.length - 1, event.localCol));
|
|
130
|
+
onColumnClick(column, event);
|
|
131
|
+
}, children: [_jsx(Text, { children: wave }), _jsx(Text, { children: rulerText })] }));
|
|
127
132
|
}
|
|
128
133
|
/**
|
|
129
134
|
* Convert a theme colour to the `#rrggbb` form chalk needs.
|
|
@@ -8,7 +8,7 @@ import { type PreviewEntry, type SessionSummary } from './sessions/index.js';
|
|
|
8
8
|
import { type FileCandidate } from '../utils/fileSuggestions.js';
|
|
9
9
|
import type { ProviderSetupHost } from './providerWizard.js';
|
|
10
10
|
import { type SessionModeSpec } from '../sessionModes.js';
|
|
11
|
-
import { type StatusBarConfig, type ToolBackground } from '../tuiDisplayPrefs.js';
|
|
11
|
+
import { type ScrollGutterMode, type StatusBarConfig, type ToolBackground } from '../tuiDisplayPrefs.js';
|
|
12
12
|
import { type SubagentState } from './subagents.js';
|
|
13
13
|
export type { SubagentState } from './subagents.js';
|
|
14
14
|
import type { SpinnerMode } from '../components/Spinner/spinnerMode.js';
|
|
@@ -376,6 +376,10 @@ export interface Channel {
|
|
|
376
376
|
readonly thinkingFold: 'preview' | 'full';
|
|
377
377
|
/** Live tool-card background treatment. */
|
|
378
378
|
readonly toolBackground: ToolBackground;
|
|
379
|
+
/** What the fullscreen transcript's right gutter shows (settings
|
|
380
|
+
* `dsh-tui.scrollGutter`: turn timeline / proportional scrollbar /
|
|
381
|
+
* nothing). */
|
|
382
|
+
readonly scrollGutter: ScrollGutterMode;
|
|
379
383
|
/** Live status-footer visibility and compactness preferences. */
|
|
380
384
|
readonly statusBar: Readonly<StatusBarConfig>;
|
|
381
385
|
/** Whether the header's pixel whale art shows (settings `dsh-tui.whale`). */
|
|
@@ -390,10 +394,11 @@ export interface Channel {
|
|
|
390
394
|
readonly contextBarEnabled: boolean;
|
|
391
395
|
/**
|
|
392
396
|
* Current same-session goal projection, when a goal exists. Derived live
|
|
393
|
-
* from the durable
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
+
* from the durable goal events in the session log — top-level
|
|
398
|
+
* `goal/change` snapshots (every goal mutation appends one) plus the
|
|
399
|
+
* goal-sourced continuation rounds that advance the counter — so this
|
|
400
|
+
* snapshot tracks create/edit/pause/resume/complete/block/clear in real
|
|
401
|
+
* time and replays correctly on resume/rewind.
|
|
397
402
|
*/
|
|
398
403
|
readonly goal: ChannelGoal | undefined;
|
|
399
404
|
/**
|
|
@@ -740,6 +745,8 @@ export interface ChannelState {
|
|
|
740
745
|
thinkingFold: 'preview' | 'full';
|
|
741
746
|
/** Tool-card background treatment (see the public Channel type). */
|
|
742
747
|
toolBackground: ToolBackground;
|
|
748
|
+
/** Transcript gutter mode (see the public Channel type). */
|
|
749
|
+
scrollGutter: ScrollGutterMode;
|
|
743
750
|
/** Status-footer preferences (see the public Channel type). */
|
|
744
751
|
statusBar: StatusBarConfig;
|
|
745
752
|
/** Apply a diff-layout change (see the public Channel type). */
|
|
@@ -748,6 +755,8 @@ export interface ChannelState {
|
|
|
748
755
|
setThinkingFold(mode: 'preview' | 'full'): void;
|
|
749
756
|
/** Apply a tool-card background change. */
|
|
750
757
|
setToolBackground(background: ToolBackground): void;
|
|
758
|
+
/** Apply a transcript gutter mode change. */
|
|
759
|
+
setScrollGutter(mode: ScrollGutterMode): void;
|
|
751
760
|
/** Apply status-footer preference changes. */
|
|
752
761
|
setStatusBar(config: Partial<StatusBarConfig>): void;
|
|
753
762
|
/** Whale header art switch (see the public Channel type). */
|
|
@@ -942,6 +951,8 @@ export declare function createChannel(ctx: Context, initialAgent: Agent, options
|
|
|
942
951
|
thinkingFold?: 'preview' | 'full';
|
|
943
952
|
/** Tool-card background treatment; default `none`. */
|
|
944
953
|
toolBackground?: ToolBackground;
|
|
954
|
+
/** Transcript gutter mode; default `timeline` (settings `dsh-tui.scrollGutter`). */
|
|
955
|
+
scrollGutter?: ScrollGutterMode;
|
|
945
956
|
/** Status-footer field visibility and compactness. */
|
|
946
957
|
statusBar?: Partial<StatusBarConfig>;
|
|
947
958
|
/** Show the header's pixel whale art; default on. */
|