@deepseek-harness-tui/dsh-tui 0.9.3 → 0.10.0-beta.2
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 +24 -6
- package/cordis.patch.yml +117 -39
- package/cordis.yml +13 -10
- package/lib/types/api.d.ts +7 -0
- package/lib/types/api.d.ts.map +1 -0
- package/lib/types/api.js +1 -0
- package/lib/types/cc/hyperlink.d.ts.map +1 -1
- package/lib/types/cc/hyperlink.js +42 -4
- package/lib/types/cc/markdown.d.ts.map +1 -1
- package/lib/types/cc/markdown.js +15 -5
- package/lib/types/commands.d.ts +6 -0
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +12 -8
- package/lib/types/components/MessageList.d.ts +8 -4
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +94 -32
- package/lib/types/components/PermissionsPicker.d.ts +6 -7
- package/lib/types/components/PermissionsPicker.d.ts.map +1 -1
- package/lib/types/components/PermissionsPicker.js +20 -14
- package/lib/types/components/PromptEditor.d.ts +46 -0
- package/lib/types/components/PromptEditor.d.ts.map +1 -0
- package/lib/types/components/PromptEditor.js +60 -0
- package/lib/types/components/PromptInput.d.ts +12 -0
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +1240 -205
- package/lib/types/components/RewindPicker.js +1 -1
- package/lib/types/components/SplitDiffView.d.ts +11 -1
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +9 -2
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +140 -3
- package/lib/types/components/SubagentDashboard.d.ts.map +1 -1
- package/lib/types/components/SubagentDashboard.js +2 -2
- package/lib/types/components/SubagentDetailScene.js +1 -1
- package/lib/types/components/ThemePicker.d.ts +13 -15
- package/lib/types/components/ThemePicker.d.ts.map +1 -1
- package/lib/types/components/ThemePicker.js +24 -26
- package/lib/types/components/Tooltip.d.ts +67 -0
- package/lib/types/components/Tooltip.d.ts.map +1 -0
- package/lib/types/components/Tooltip.js +220 -0
- package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
- package/lib/types/components/approvals/ApprovalPanel.js +1 -1
- package/lib/types/components/design-system/Divider.d.ts +14 -1
- package/lib/types/components/design-system/Divider.d.ts.map +1 -1
- package/lib/types/components/design-system/Divider.js +86 -8
- package/lib/types/components/design-system/ThemeProvider.d.ts +5 -2
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +52 -16
- package/lib/types/components/design-system/ThemedBox.d.ts +23 -2
- package/lib/types/components/design-system/ThemedBox.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +11 -6
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +10 -6
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +13 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +37 -6
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +7 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +1 -1
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +29 -3
- package/lib/types/components/sessions/SessionListRow.d.ts +8 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +9 -2
- package/lib/types/components/sessions/SessionPreview.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionPreview.js +5 -3
- package/lib/types/components/sessions/WorkspaceListRow.d.ts +17 -0
- package/lib/types/components/sessions/WorkspaceListRow.d.ts.map +1 -0
- package/lib/types/components/sessions/WorkspaceListRow.js +27 -0
- package/lib/types/components/smoothReveal.d.ts +97 -0
- package/lib/types/components/smoothReveal.d.ts.map +1 -0
- package/lib/types/components/smoothReveal.js +279 -0
- package/lib/types/customTheme.d.ts +4 -0
- package/lib/types/customTheme.d.ts.map +1 -1
- package/lib/types/customTheme.js +9 -5
- package/lib/types/dsh-adapter/approvals.d.ts +114 -2
- package/lib/types/dsh-adapter/approvals.d.ts.map +1 -1
- package/lib/types/dsh-adapter/approvals.js +241 -3
- package/lib/types/dsh-adapter/channel.d.ts +59 -2
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +499 -80
- package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
- package/lib/types/dsh-adapter/childStderr.js +9 -0
- package/lib/types/dsh-adapter/contract.d.ts +17 -13
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +36 -27
- package/lib/types/dsh-adapter/credentialRefGuard.d.ts +40 -0
- package/lib/types/dsh-adapter/credentialRefGuard.d.ts.map +1 -0
- package/lib/types/dsh-adapter/credentialRefGuard.js +43 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts +1 -1
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -1
- package/lib/types/dsh-adapter/effect-ledger.js +1 -0
- package/lib/types/dsh-adapter/extensions.d.ts +4 -1
- package/lib/types/dsh-adapter/extensions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/extensions.js +8 -1
- package/lib/types/dsh-adapter/index.d.ts +11 -1
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +2 -0
- package/lib/types/dsh-adapter/plugin-test-utils.d.ts +62 -0
- package/lib/types/dsh-adapter/plugin-test-utils.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-test-utils.js +61 -0
- package/lib/types/dsh-adapter/plugin.d.ts +20 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +174 -39
- package/lib/types/dsh-adapter/plugins-info.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugins-info.js +12 -0
- package/lib/types/dsh-adapter/preset-resolution.d.ts +49 -0
- package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -0
- package/lib/types/dsh-adapter/preset-resolution.js +42 -0
- package/lib/types/dsh-adapter/presets.d.ts +0 -26
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +4 -14
- package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
- package/lib/types/dsh-adapter/promptDebug.js +4 -1
- package/lib/types/dsh-adapter/providerGuard.d.ts +75 -0
- package/lib/types/dsh-adapter/providerGuard.d.ts.map +1 -0
- package/lib/types/dsh-adapter/providerGuard.js +104 -0
- package/lib/types/dsh-adapter/questions-answerer.d.ts +49 -0
- package/lib/types/dsh-adapter/questions-answerer.d.ts.map +1 -0
- package/lib/types/dsh-adapter/questions-answerer.js +61 -0
- package/lib/types/dsh-adapter/recap.d.ts.map +1 -1
- package/lib/types/dsh-adapter/recap.js +12 -6
- package/lib/types/dsh-adapter/sanitize.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sanitize.js +6 -1
- package/lib/types/dsh-adapter/sessions/digest.d.ts +21 -1
- package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/digest.js +229 -3
- package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -0
- package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/frames.js +34 -19
- package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/list.js +148 -31
- package/lib/types/dsh-adapter/sessions/store.d.ts +8 -0
- package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/store.js +24 -4
- package/lib/types/dsh-adapter/sessions/types.d.ts +3 -0
- package/lib/types/dsh-adapter/sessions/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +13 -1
- package/lib/types/dsh-adapter/settingsEditor.d.ts +6 -0
- package/lib/types/dsh-adapter/settingsEditor.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settingsEditor.js +15 -3
- package/lib/types/dsh-adapter/subagents.d.ts +4 -0
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +8 -0
- package/lib/types/dsh-adapter/themes.d.ts +51 -0
- package/lib/types/dsh-adapter/themes.d.ts.map +1 -0
- package/lib/types/dsh-adapter/themes.js +272 -0
- package/lib/types/dsh-adapter/toast.d.ts +67 -0
- package/lib/types/dsh-adapter/toast.d.ts.map +1 -0
- package/lib/types/dsh-adapter/toast.js +141 -0
- package/lib/types/dsh-adapter/types.d.ts +1 -1
- package/lib/types/extensions.d.ts +4 -0
- package/lib/types/extensions.d.ts.map +1 -1
- package/lib/types/extensions.js +5 -1
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +7 -2
- package/lib/types/hooks/useRuntimeThemeSnapshot.d.ts +10 -0
- package/lib/types/hooks/useRuntimeThemeSnapshot.d.ts.map +1 -0
- package/lib/types/hooks/useRuntimeThemeSnapshot.js +32 -0
- package/lib/types/i18n.d.ts +199 -41
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +82 -20
- package/lib/types/ink/components/App.d.ts +20 -0
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +142 -13
- package/lib/types/ink/components/Box.d.ts +39 -2
- package/lib/types/ink/components/Box.d.ts.map +1 -1
- package/lib/types/ink/components/Box.js +61 -37
- package/lib/types/ink/events/context-menu-event.d.ts +19 -0
- package/lib/types/ink/events/context-menu-event.d.ts.map +1 -0
- package/lib/types/ink/events/context-menu-event.js +20 -0
- package/lib/types/ink/events/drag-event.d.ts +44 -0
- package/lib/types/ink/events/drag-event.d.ts.map +1 -0
- package/lib/types/ink/events/drag-event.js +39 -0
- package/lib/types/ink/events/event-handlers.d.ts +8 -0
- package/lib/types/ink/events/event-handlers.d.ts.map +1 -1
- package/lib/types/ink/events/event-handlers.js +8 -0
- package/lib/types/ink/hit-test.d.ts +69 -0
- package/lib/types/ink/hit-test.d.ts.map +1 -1
- package/lib/types/ink/hit-test.js +260 -6
- package/lib/types/ink/ink.d.ts +25 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +74 -10
- package/lib/types/ink/parse-keypress.d.ts +20 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +190 -22
- package/lib/types/ink/renderer.d.ts.map +1 -1
- package/lib/types/ink/renderer.js +15 -1
- package/lib/types/ink/screen.d.ts +7 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +8 -1
- package/lib/types/ink/termio/osc.d.ts +2 -1
- package/lib/types/ink/termio/osc.d.ts.map +1 -1
- package/lib/types/ink/termio/osc.js +26 -5
- package/lib/types/plugin-spec/registry.d.ts +1 -1
- package/lib/types/plugin-spec/registry.js +1 -1
- package/lib/types/presetPrefs.d.ts +6 -5
- package/lib/types/presetPrefs.d.ts.map +1 -1
- package/lib/types/presetPrefs.js +10 -5
- package/lib/types/screens/Chat.d.ts +4 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +169 -68
- package/lib/types/screens/SessionBrowser.d.ts +9 -4
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +483 -75
- package/lib/types/screens/SessionTree.d.ts.map +1 -1
- package/lib/types/screens/SessionTree.js +5 -1
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +5 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +5 -1
- package/lib/types/screens/chatOverlay.d.ts +3 -2
- package/lib/types/screens/chatOverlay.d.ts.map +1 -1
- package/lib/types/screens/chatOverlay.js +2 -0
- package/lib/types/sessionPins.d.ts +33 -0
- package/lib/types/sessionPins.d.ts.map +1 -0
- package/lib/types/sessionPins.js +181 -0
- package/lib/types/sessions/format.d.ts +2 -0
- package/lib/types/sessions/format.d.ts.map +1 -1
- package/lib/types/sessions/format.js +9 -0
- package/lib/types/sessions/view.d.ts +42 -6
- package/lib/types/sessions/view.d.ts.map +1 -1
- package/lib/types/sessions/view.js +133 -35
- package/lib/types/test-utils.d.ts +2 -0
- package/lib/types/test-utils.d.ts.map +1 -0
- package/lib/types/test-utils.js +8 -0
- package/lib/types/theme.d.ts +22 -5
- package/lib/types/theme.d.ts.map +1 -1
- package/lib/types/theme.js +57 -7
- package/lib/types/themeCatalog.d.ts +36 -0
- package/lib/types/themeCatalog.d.ts.map +1 -0
- package/lib/types/themeCatalog.js +157 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +114 -18
- package/lib/types/update.d.ts +159 -3
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +497 -16
- package/lib/types/utils/debug.d.ts.map +1 -1
- package/lib/types/utils/debug.js +2 -1
- package/lib/types/utils/keymap.d.ts +1 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +19 -2
- package/lib/types/utils/urlGuard.d.ts +28 -0
- package/lib/types/utils/urlGuard.d.ts.map +1 -0
- package/lib/types/utils/urlGuard.js +21 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +3 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.d.ts +7 -11
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.d.ts +16 -1
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.js +23 -2
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.d.ts +5 -5
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/pi-ai.d.ts +23 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/pi-ai.js +27 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.d.ts +17 -3
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.js +36 -4
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +11 -12
- package/package.json +114 -74
- package/lib/types/dsh-adapter/packaged-skills.d.ts +0 -19
- package/lib/types/dsh-adapter/packaged-skills.d.ts.map +0 -1
- package/lib/types/dsh-adapter/packaged-skills.js +0 -78
- package/skills/audit/SKILL.md +0 -24
- package/skills/bug/SKILL.md +0 -27
- package/skills/pr-comments/SKILL.md +0 -20
- package/skills/practice/SKILL.md +0 -22
- package/skills/release-notes/SKILL.md +0 -25
- package/skills/review/SKILL.md +0 -25
- package/skills/vuln-check/SKILL.md +0 -25
|
@@ -18,11 +18,13 @@ import { stripNarration } from '../utils/narration.js';
|
|
|
18
18
|
import { stringWidth } from '../ink/stringWidth.js';
|
|
19
19
|
import { truncateToWidth } from '../ink/truncateToWidth.js';
|
|
20
20
|
import { clipPreview } from '../ink/timeline-rail.js';
|
|
21
|
+
import { getRevealVersion, revealLengthOf, revealTextOf, subscribeReveal } from './smoothReveal.js';
|
|
21
22
|
/**
|
|
22
23
|
* Transcript rows rendered in the Claude Code visual language: user prompts
|
|
23
24
|
* on a grey bubble with a `❯` pointer, assistant text with a `●` bullet and
|
|
24
|
-
* markdown, thinking
|
|
25
|
-
*
|
|
25
|
+
* markdown, thinking as a live three-line/full toggle then a settled
|
|
26
|
+
* `⚓ Thinking (ctrl+o to expand)` row, and tool calls as status-dot cards.
|
|
27
|
+
* `expanded` (Ctrl+O) shows full reasoning + full tool
|
|
26
28
|
* args/results; `expandedRows` (message-selection mode, Enter) expands single
|
|
27
29
|
* rows; `selectedId` highlights the selected row.
|
|
28
30
|
*/
|
|
@@ -47,13 +49,44 @@ const DEFAULT_ROW_HEIGHT = 2;
|
|
|
47
49
|
/** Cold-start estimate of the header block above the rows; corrected by the
|
|
48
50
|
* first layout measurement. */
|
|
49
51
|
const DEFAULT_HEADER_LINES = 14;
|
|
50
|
-
/** Stable fallbacks for the stream-
|
|
51
|
-
* embedders render MessageList with prop sets that predate them, and the
|
|
52
|
+
/** Stable fallbacks for the stream-view toggle props: verify/repro harnesses
|
|
53
|
+
* and embedders render MessageList with prop sets that predate them, and the
|
|
52
54
|
* render must not throw (same rule as Chat's stubbed channel APIs). Module
|
|
53
55
|
* scope keeps the identities stable so MemoRow's shallow compare and the
|
|
54
56
|
* toggle callback's deps never churn. */
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
+
const NO_STREAM_VIEW_TOGGLED = new Set();
|
|
58
|
+
const NOOP_TOGGLE_STREAM_VIEW = (_rowId) => { };
|
|
59
|
+
// --- smooth-streaming display text -----------------------------------------
|
|
60
|
+
// Render-phase reads of the shared reveal cursors (see smoothReveal.ts for
|
|
61
|
+
// why the cursors live outside React). `active` gates cursor CREATION to
|
|
62
|
+
// live-arrived content (streaming rows, live-settled rows marked `fresh`,
|
|
63
|
+
// replayed history paints complete); once created, a cursor keeps revealing
|
|
64
|
+
// until it catches up — settling mid-reveal must not snap (that is the
|
|
65
|
+
// "non-streaming delivery becomes a smooth flow" contract).
|
|
66
|
+
function assistantRevealText(row, enabled) {
|
|
67
|
+
const stripped = stripNarration(row.text);
|
|
68
|
+
return revealTextOf(`a${row.id}`, stripped, {
|
|
69
|
+
enabled,
|
|
70
|
+
active: row.streaming === true || row.fresh === true,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function reasoningRevealText(row, enabled) {
|
|
74
|
+
return revealTextOf(`r${row.id}`, row.text, { enabled, active: row.streaming === true });
|
|
75
|
+
}
|
|
76
|
+
/** Display length only (layout signature; no slice allocation). */
|
|
77
|
+
function revealDisplayLen(row, enabled) {
|
|
78
|
+
if (row.kind === 'assistant') {
|
|
79
|
+
const stripped = stripNarration(row.text);
|
|
80
|
+
return revealLengthOf(`a${row.id}`, stripped, {
|
|
81
|
+
enabled,
|
|
82
|
+
active: row.streaming === true || row.fresh === true,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (row.kind === 'reasoning') {
|
|
86
|
+
return revealLengthOf(`r${row.id}`, row.text, { enabled, active: row.streaming === true });
|
|
87
|
+
}
|
|
88
|
+
return row.text.length;
|
|
89
|
+
}
|
|
57
90
|
/**
|
|
58
91
|
* Per-kind layout signature PARTS: the O(1) identity of every input that
|
|
59
92
|
* decides a row's rendered HEIGHT (see sigRef in MessageList). Fields are
|
|
@@ -75,11 +108,13 @@ const NOOP_TOGGLE_STREAM_FOLD = (_rowId) => { };
|
|
|
75
108
|
* (parts.slice()).
|
|
76
109
|
*/
|
|
77
110
|
const signatureScratch = [];
|
|
78
|
-
function signatureParts(row, columns, expanded, expandedRows,
|
|
111
|
+
function signatureParts(row, columns, expanded, expandedRows, streamViewToggledRows, thinkingVisible, thinkingFold, diffLayout, foldTerminalCommand, model, failureHintRowId, failureHint, displayTextLen) {
|
|
79
112
|
signatureScratch.length = 0;
|
|
80
113
|
// Universal height inputs: width reflows every row; kind switches height
|
|
81
|
-
// semantics wholesale; text length drives wrapping.
|
|
82
|
-
|
|
114
|
+
// semantics wholesale; text length drives wrapping. `displayTextLen` is the
|
|
115
|
+
// REVEALED length while smooth streaming is painting (the height follows
|
|
116
|
+
// what is on screen, not what has arrived).
|
|
117
|
+
signatureScratch.push(columns, row.kind, displayTextLen);
|
|
83
118
|
switch (row.kind) {
|
|
84
119
|
case 'assistant':
|
|
85
120
|
// Streaming vs settled swaps renderers; Ctrl+O/per-row expand adds the
|
|
@@ -88,10 +123,9 @@ function signatureParts(row, columns, expanded, expandedRows, streamFolded, thin
|
|
|
88
123
|
signatureScratch.push(row.streaming === true, expanded, expandedRows.has(row.id), expanded ? model : '');
|
|
89
124
|
break;
|
|
90
125
|
case 'reasoning':
|
|
91
|
-
// thinkingFold (preview vs full)
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
signatureScratch.push(row.streaming === true, expanded, expandedRows.has(row.id), streamFolded.has(row.id), thinkingVisible, thinkingFold);
|
|
126
|
+
// thinkingFold (preview vs full), its per-row live override, and the
|
|
127
|
+
// visibility filter all change the card's height.
|
|
128
|
+
signatureScratch.push(row.streaming === true, expanded, expandedRows.has(row.id), streamViewToggledRows.has(row.id), thinkingVisible, thinkingFold);
|
|
95
129
|
break;
|
|
96
130
|
case 'tool': {
|
|
97
131
|
const tool = row.tool;
|
|
@@ -119,7 +153,7 @@ function signatureParts(row, columns, expanded, expandedRows, streamFolded, thin
|
|
|
119
153
|
}
|
|
120
154
|
return signatureScratch;
|
|
121
155
|
}
|
|
122
|
-
export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow,
|
|
156
|
+
export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, streamViewToggledRows = NO_STREAM_VIEW_TOGGLED, onToggleStreamView = NOOP_TOGGLE_STREAM_VIEW, model, diffLayout = 'auto', thinkingFold = 'preview', toolBackground = 'none', foldTerminalCommand = false, smoothStreaming = false, activityFrames, showAll, onToggleAll, onLoadOlder, thinkingVisible = true, historyPaintEnabled = true, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, onTimeline, failureHintRowId, failureHint, onOpenSubagent, onOpenFile, }) {
|
|
123
157
|
const hiddenCount = rows.length - MAX_RENDERED_ROWS;
|
|
124
158
|
// The thinking filter runs BEFORE virtualization so window indices line up.
|
|
125
159
|
//
|
|
@@ -225,6 +259,13 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
|
|
|
225
259
|
};
|
|
226
260
|
// --- layout virtualization ---------------------------------------------
|
|
227
261
|
const { columns, rows: termRows } = useTerminalSize();
|
|
262
|
+
// Smooth-reveal wakeups: the scheduler's tick bumps this store, re-running
|
|
263
|
+
// MessageList so the revealed `text`/line-count reads below feed fresh
|
|
264
|
+
// values through the same MemoRow-prop pipeline an arriving chunk uses —
|
|
265
|
+
// memo miss → re-render → post-commit height re-measure. Without this
|
|
266
|
+
// subscription a reveal living in child state would change row heights
|
|
267
|
+
// invisibly to the virtualization (stale cached heights → blank bands).
|
|
268
|
+
React.useSyncExternalStore(subscribeReveal, getRevealVersion);
|
|
228
269
|
// Measured row heights, remembered after a row unmounts so virtualization
|
|
229
270
|
// can compute total content height. Bounded: row ids grow monotonically
|
|
230
271
|
// and rows are never removed from the transcript (foldRows keeps the
|
|
@@ -318,7 +359,7 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
|
|
|
318
359
|
// reasoning height at once, remounting the widened window over rows
|
|
319
360
|
// whose rendering never changed (Yoga spike + measure churn for
|
|
320
361
|
// nothing). Base parts cover the universal height inputs.
|
|
321
|
-
const parts = signatureParts(row, columns, expanded, expandedRows,
|
|
362
|
+
const parts = signatureParts(row, columns, expanded, expandedRows, streamViewToggledRows, thinkingVisible, thinkingFold, diffLayout, foldTerminalCommand, model, failureHintRowId, failureHint, revealDisplayLen(row, smoothStreaming));
|
|
322
363
|
const cachedParts = sigs.get(row.id);
|
|
323
364
|
let same = false;
|
|
324
365
|
if (cachedParts !== undefined && cachedParts.length === parts.length) {
|
|
@@ -832,7 +873,27 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
|
|
|
832
873
|
const addMargin = margins.get(row.id) === true;
|
|
833
874
|
const tool = row.tool;
|
|
834
875
|
const subagent = row.kind === 'subagent' ? row.subagent : undefined;
|
|
835
|
-
|
|
876
|
+
// Smooth reveal feeds the SAME flattened text prop a chunk feeds,
|
|
877
|
+
// and keeps the streaming layout alive until the reveal catches up
|
|
878
|
+
// (settling mid-reveal must not snap — a one-shot non-streaming
|
|
879
|
+
// delivery still paints as a flow).
|
|
880
|
+
let displayText = row.text;
|
|
881
|
+
let displayStreaming = row.streaming === true;
|
|
882
|
+
if (row.kind === 'assistant' && smoothStreaming) {
|
|
883
|
+
const stripped = stripNarration(row.text);
|
|
884
|
+
displayText = revealTextOf(`a${row.id}`, stripped, {
|
|
885
|
+
enabled: true,
|
|
886
|
+
active: displayStreaming || row.fresh === true,
|
|
887
|
+
});
|
|
888
|
+
displayStreaming = displayStreaming || displayText.length !== stripped.length;
|
|
889
|
+
}
|
|
890
|
+
else if (row.kind === 'assistant') {
|
|
891
|
+
displayText = stripNarration(row.text);
|
|
892
|
+
}
|
|
893
|
+
else if (row.kind === 'reasoning' && smoothStreaming) {
|
|
894
|
+
displayText = revealTextOf(`r${row.id}`, row.text, { enabled: true, active: displayStreaming });
|
|
895
|
+
}
|
|
896
|
+
return (_jsx(MemoRow, { rowId: row.id, kind: row.kind, text: displayText, textFull: row.kind === 'reasoning' ? row.text : undefined, executionTarget: row.executionTarget, streaming: displayStreaming, durationMs: row.durationMs, time: row.time, addMargin: addMargin, isSelected: selectedId === row.id, isExpanded: expandedRows.has(row.id), expanded: expanded, model: model, diffLayout: diffLayout, thinkingFold: thinkingFold, toolBackground: toolBackground, foldTerminalCommand: foldTerminalCommand, smoothStreaming: smoothStreaming, fresh: row.fresh === true, activityFrames: activityFrames, background: rowBackground(row.id), toolCallId: tool?.callId, toolName: tool?.name, toolArgsText: tool?.argsText, toolArgsFull: tool?.argsFull, toolStatus: tool?.status, toolResultText: tool?.resultText, toolResultFull: tool?.resultFull, toolErrorText: tool?.errorText, toolFootnote: failureHintRowId === row.id ? failureHint : undefined, toolCallView: tool?.callView, toolResultView: tool?.resultView, toolStartedAt: tool?.startedAt, toolDurationMs: tool?.durationMs, subagent: subagent, onToggleRow: onToggleRow, onToggleStreamView: onToggleStreamView, streamViewToggled: streamViewToggledRows.has(row.id), onOpenSubagent: onOpenSubagent, onOpenFile: onOpenFile, setRowRef: setRowRef }, row.id));
|
|
836
897
|
}), bottomPad > 0 && _jsx(Box, { height: bottomPad, flexShrink: 0 })] }));
|
|
837
898
|
}
|
|
838
899
|
/** Load-earlier / show-previous divider row with a mouse hover tint — the
|
|
@@ -841,7 +902,7 @@ function ClickableDivider({ title, onClick }) {
|
|
|
841
902
|
const [hovered, setHovered] = useState(false);
|
|
842
903
|
return (_jsx(Box, { marginTop: 1, onClick: onClick, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), backgroundColor: hovered ? 'userMessageBackgroundHover' : undefined, children: _jsx(Divider, { title: title }) }));
|
|
843
904
|
}
|
|
844
|
-
function TranscriptRow({ rowId, kind, text, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, diffLayout, thinkingFold, toolBackground, foldTerminalCommand, activityFrames, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, subagent, onToggleRow,
|
|
905
|
+
function TranscriptRow({ rowId, kind, text, textFull, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, diffLayout, smoothStreaming, fresh, thinkingFold, toolBackground, foldTerminalCommand, activityFrames, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, subagent, onToggleRow, onToggleStreamView, streamViewToggled, onOpenSubagent, onOpenFile, setRowRef, }) {
|
|
845
906
|
const ref = React.useCallback((el) => {
|
|
846
907
|
setRowRef(rowId, el);
|
|
847
908
|
}, [setRowRef, rowId]);
|
|
@@ -854,13 +915,13 @@ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, duration
|
|
|
854
915
|
return;
|
|
855
916
|
onToggleRow(rowId);
|
|
856
917
|
}, [onToggleRow, rowId]);
|
|
857
|
-
// 流式 reasoning
|
|
858
|
-
//
|
|
859
|
-
const
|
|
918
|
+
// 流式 reasoning 行:点击在三行预览/全文间切换。它反转 thinkingFold
|
|
919
|
+
// 的默认值,落定后语义自动回到 foldOnClick。
|
|
920
|
+
const streamViewOnClick = React.useCallback((event) => {
|
|
860
921
|
if (event.cellIsBlank)
|
|
861
922
|
return;
|
|
862
|
-
|
|
863
|
-
}, [
|
|
923
|
+
onToggleStreamView(rowId);
|
|
924
|
+
}, [onToggleStreamView, rowId]);
|
|
864
925
|
// 子代理卡:点击打开详情场景(不是折叠)。
|
|
865
926
|
const openSubagent = React.useCallback(() => {
|
|
866
927
|
if (subagent !== undefined)
|
|
@@ -873,15 +934,16 @@ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, duration
|
|
|
873
934
|
return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(UserPromptMessage, { text: text, addMargin: addMargin, isSelected: isSelected }) }));
|
|
874
935
|
case 'assistant':
|
|
875
936
|
return streaming ? (_jsxs(Box, { alignItems: "flex-start", flexDirection: "row", marginTop: addMargin ? 1 : 0, width: "100%", backgroundColor: background, ref: ref, children: [_jsx(Box, { minWidth: 2, children: _jsx(Text, { color: "text", children: "\u25CF" }) }), _jsx(Box, { flexDirection: "column", children: _jsx(StreamingMarkdown, { children: stripNarration(text) }) })] })) : (_jsxs(Box, { width: "100%", flexDirection: "column", backgroundColor: background, ref: ref, children: [expanded && (_jsx(Box, { flexDirection: "row", justifyContent: "flex-end", gap: 1, marginTop: 1, children: _jsx(MessageMetadata, { timestamp: time, model: model }) })), _jsx(AssistantTextMessage, { text: stripNarration(text), addMargin: addMargin, isSelected: isSelected, isExpanded: isExpanded })] }));
|
|
876
|
-
case 'reasoning':
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
//
|
|
883
|
-
//
|
|
884
|
-
verbose: isExpanded || expanded || (streaming && !
|
|
937
|
+
case 'reasoning': {
|
|
938
|
+
// The setting chooses the live default; a row click reverses it. Global
|
|
939
|
+
// or per-row transcript expansion always wins and shows the full text.
|
|
940
|
+
const streamPreview = streaming && !expanded && !isExpanded &&
|
|
941
|
+
(streamViewToggled ? thinkingFold === 'full' : thinkingFold === 'preview');
|
|
942
|
+
return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantThinkingMessage, { thinking: text, textFull: textFull, addMargin: addMargin, streaming: streaming, preview: streamPreview,
|
|
943
|
+
// Settled rows keep the fold-on-settle default and expand via
|
|
944
|
+
// expandedRows/Ctrl+O; a live row is always preview or full.
|
|
945
|
+
verbose: isExpanded || expanded || (streaming && !streamPreview), durationMs: durationMs, isSelected: isSelected, onClick: streaming ? streamViewOnClick : foldOnClick }) }));
|
|
946
|
+
}
|
|
885
947
|
case 'tool': {
|
|
886
948
|
if (toolCallId === undefined ||
|
|
887
949
|
toolName === undefined ||
|
|
@@ -906,7 +968,7 @@ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, duration
|
|
|
906
968
|
startedAt: toolStartedAt,
|
|
907
969
|
durationMs: toolDurationMs,
|
|
908
970
|
};
|
|
909
|
-
return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote, diffLayout: diffLayout, toolBackground: toolBackground, foldTerminalCommand: foldTerminalCommand, onClick: foldOnClick, onOpenFile: onOpenFile }) }));
|
|
971
|
+
return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote, diffLayout: diffLayout, toolBackground: toolBackground, smoothReveal: smoothStreaming, fresh: fresh, foldTerminalCommand: foldTerminalCommand, onClick: foldOnClick, onOpenFile: onOpenFile }) }));
|
|
910
972
|
}
|
|
911
973
|
case 'notice':
|
|
912
974
|
return (_jsx(Box, { marginTop: 1, ref: ref, children: _jsx(Divider, { title: ` ${text} ` }) }));
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { PermissionPresetOption } from '../dsh-adapter/channel.js';
|
|
2
3
|
/**
|
|
3
4
|
* `/permission` sandbox-preset picker. The command itself is registered by
|
|
4
5
|
* the harness side (dsh-sandbox-policy / dsh-base permission-presets row);
|
|
5
6
|
* bare `/permission` opens this picker and Enter dispatches
|
|
6
7
|
* `/permission <preset>` through the same external-command path a hand-typed
|
|
7
|
-
* argument takes. The
|
|
8
|
-
*
|
|
9
|
-
* mode the TUI derives from the session log.
|
|
8
|
+
* argument takes. The roster comes from the adapter snapshot so host plugins
|
|
9
|
+
* can contribute additional preset identities without UI changes.
|
|
10
10
|
*/
|
|
11
|
-
export declare
|
|
12
|
-
|
|
13
|
-
export declare function PermissionsPicker({ focusIndex, currentMode, cwd, onPick, }: {
|
|
11
|
+
export declare function PermissionsPicker({ options, focusIndex, currentValue, cwd, onPick, }: {
|
|
12
|
+
options: readonly PermissionPresetOption[];
|
|
14
13
|
focusIndex: number;
|
|
15
|
-
|
|
14
|
+
currentValue: string | undefined;
|
|
16
15
|
cwd: string;
|
|
17
16
|
/** Mouse pick (fullscreen): clicked row's absolute index (Chat applies
|
|
18
17
|
* the same code path as the keyboard Enter). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PermissionsPicker.d.ts","sourceRoot":"","sources":["../../../src/components/PermissionsPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"PermissionsPicker.d.ts","sourceRoot":"","sources":["../../../src/components/PermissionsPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAEvE;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,UAAU,EACV,YAAY,EACZ,GAAG,EACH,MAAM,GACP,EAAE;IACD,OAAO,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,GAAG,EAAE,MAAM,CAAA;IACX;qDACiD;IACjD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC,GAAG,KAAK,CAAC,SAAS,CAwClB"}
|
|
@@ -9,19 +9,25 @@ import { HintLine } from './design-system/HintLine.js';
|
|
|
9
9
|
* the harness side (dsh-sandbox-policy / dsh-base permission-presets row);
|
|
10
10
|
* bare `/permission` opens this picker and Enter dispatches
|
|
11
11
|
* `/permission <preset>` through the same external-command path a hand-typed
|
|
12
|
-
* argument takes. The
|
|
13
|
-
*
|
|
14
|
-
* mode the TUI derives from the session log.
|
|
12
|
+
* argument takes. The roster comes from the adapter snapshot so host plugins
|
|
13
|
+
* can contribute additional preset identities without UI changes.
|
|
15
14
|
*/
|
|
16
|
-
export
|
|
17
|
-
'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
export function PermissionsPicker({ options, focusIndex, currentValue, cwd, onPick, }) {
|
|
16
|
+
return (_jsx(Pane, { color: "permission", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "remember", bold: true, children: t('permission-picker-title') }) }), _jsx(Select, { options: options.map(option => ({
|
|
17
|
+
value: option.value,
|
|
18
|
+
label: option.value === 'read-only'
|
|
19
|
+
? t('permission-preset-readonly')
|
|
20
|
+
: option.value === 'workspace-write'
|
|
21
|
+
? t('permission-preset-workspace-write')
|
|
22
|
+
: option.value === 'danger-full-access'
|
|
23
|
+
? t('permission-preset-full-access')
|
|
24
|
+
: option.name,
|
|
25
|
+
description: option.value === 'read-only'
|
|
26
|
+
? t('permission-preset-readonly-desc')
|
|
27
|
+
: option.value === 'workspace-write'
|
|
28
|
+
? t('permission-preset-workspace-write-desc')
|
|
29
|
+
: option.value === 'danger-full-access'
|
|
30
|
+
? t('permission-preset-full-access-desc')
|
|
31
|
+
: option.description ?? option.name,
|
|
32
|
+
})), focusIndex: focusIndex, selectedValue: currentValue, onPick: onPick ? index => onPick(index) : undefined }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-confirm-exit') }) }), _jsx(Text, { dimColor: true, children: t('permission-root-hint', { cwd }) })] }) }));
|
|
27
33
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Color } from '../ink/styles.js';
|
|
3
|
+
import type { Theme } from '../theme.js';
|
|
4
|
+
/**
|
|
5
|
+
* 全屏草稿编辑的挂载层。编辑状态(value/caret/选区/折叠)全部住在
|
|
6
|
+
* PromptInput 内部,展开视图却必须盖住整棵 Chat 树的每个后绘兄弟
|
|
7
|
+
* (StatusLine、OverlayAbove、TooltipLayer)——渲染器按树序绘制,
|
|
8
|
+
* absolute 浮层只有作为根 Box 的最后一个孩子才天然压过一切
|
|
9
|
+
* (TooltipLayer 的同款契约)。PromptInput 因此把展开视图的 React
|
|
10
|
+
* 节点发布到这个 module 级 store,`PromptEditorLayer`(挂在 Chat 根
|
|
11
|
+
* Box 末尾)订阅并渲染;节点是 PromptInput 每次渲染的新鲜闭包,
|
|
12
|
+
* 命中/拖拽/按钮 handler 无需任何额外的状态同步管道。
|
|
13
|
+
*
|
|
14
|
+
* 节点写入用 useInsertionEffect:sink 的同步重渲染发生在 layout
|
|
15
|
+
* 阶段之前,PromptInput 的 useDeclaredCursor(layout effect)读到
|
|
16
|
+
* 的 ref 已经指向编辑区的 Box,首帧光标声明即正确。
|
|
17
|
+
*/
|
|
18
|
+
type EditorNode = React.ReactNode | null;
|
|
19
|
+
/** Publish (or withdraw, with null) the fullscreen editor subtree. */
|
|
20
|
+
export declare function setPromptEditorNode(node: EditorNode): void;
|
|
21
|
+
/**
|
|
22
|
+
* The fullscreen sink, mounted once at the very end of Chat's root Box.
|
|
23
|
+
* The absolute cover is `opaque` so its padding/blank cells never bleed
|
|
24
|
+
* the covered transcript through, and it swallows stray clicks so the
|
|
25
|
+
* conversation underneath cannot react to a click meant for the editor.
|
|
26
|
+
*/
|
|
27
|
+
export declare function PromptEditorLayer(): React.ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* A mouse-friendly pill button for the editor chrome (send / collapse /
|
|
30
|
+
* the ⤢ close affordance). Hover swaps the surface so the affordance
|
|
31
|
+
* reads at a glance — the same interaction language as the transcript's
|
|
32
|
+
* clickable rows and the session browser's menu items.
|
|
33
|
+
*/
|
|
34
|
+
export declare function EditorButton({ label, hint, onClick, primary, accent, }: {
|
|
35
|
+
/** Button text, e.g. `⏎ 发送`. */
|
|
36
|
+
label: string;
|
|
37
|
+
/** Dim trailing hint inside the pill, e.g. `Ctrl+Enter`. */
|
|
38
|
+
hint?: string;
|
|
39
|
+
onClick: () => void;
|
|
40
|
+
/** Filled variant (the primary action); default is the outline look. */
|
|
41
|
+
primary?: boolean;
|
|
42
|
+
/** Accent theme token / raw color for the filled variant. */
|
|
43
|
+
accent?: keyof Theme | Color;
|
|
44
|
+
}): React.ReactNode;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=PromptEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptEditor.d.ts","sourceRoot":"","sources":["../../../src/components/PromptEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;;;;;;;;;;;GAaG;AAEH,KAAK,UAAU,GAAG,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;AAKxC,sEAAsE;AACtE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAI1D;AAaD;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,CAAC,SAAS,CAqBnD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,OAAO,EACP,OAAO,EACP,MAAM,GACP,EAAE;IACD,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,KAAK,GAAG,KAAK,CAAA;CAC7B,GAAG,KAAK,CAAC,SAAS,CAmClB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text } from '../ui.js';
|
|
4
|
+
let editorNode = null;
|
|
5
|
+
const listeners = new Set();
|
|
6
|
+
/** Publish (or withdraw, with null) the fullscreen editor subtree. */
|
|
7
|
+
export function setPromptEditorNode(node) {
|
|
8
|
+
if (node === editorNode)
|
|
9
|
+
return;
|
|
10
|
+
editorNode = node;
|
|
11
|
+
for (const listener of listeners)
|
|
12
|
+
listener();
|
|
13
|
+
}
|
|
14
|
+
function subscribe(callback) {
|
|
15
|
+
listeners.add(callback);
|
|
16
|
+
return () => {
|
|
17
|
+
listeners.delete(callback);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function snapshot() {
|
|
21
|
+
return editorNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The fullscreen sink, mounted once at the very end of Chat's root Box.
|
|
25
|
+
* The absolute cover is `opaque` so its padding/blank cells never bleed
|
|
26
|
+
* the covered transcript through, and it swallows stray clicks so the
|
|
27
|
+
* conversation underneath cannot react to a click meant for the editor.
|
|
28
|
+
*/
|
|
29
|
+
export function PromptEditorLayer() {
|
|
30
|
+
const node = React.useSyncExternalStore(subscribe, snapshot);
|
|
31
|
+
if (node === null)
|
|
32
|
+
return null;
|
|
33
|
+
return (_jsx(Box, { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", flexDirection: "column", flexShrink: 0, overflow: "hidden", opaque: true, onClick: (event) => {
|
|
34
|
+
event.stopImmediatePropagation();
|
|
35
|
+
}, children: node }));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A mouse-friendly pill button for the editor chrome (send / collapse /
|
|
39
|
+
* the ⤢ close affordance). Hover swaps the surface so the affordance
|
|
40
|
+
* reads at a glance — the same interaction language as the transcript's
|
|
41
|
+
* clickable rows and the session browser's menu items.
|
|
42
|
+
*/
|
|
43
|
+
export function EditorButton({ label, hint, onClick, primary, accent, }) {
|
|
44
|
+
const [hovered, setHovered] = React.useState(false);
|
|
45
|
+
const text = hint === undefined ? ` ${label} ` : ` ${label} ${hint} `;
|
|
46
|
+
return (_jsx(Box, { flexShrink: 0, backgroundColor: primary
|
|
47
|
+
? hovered
|
|
48
|
+
? 'userMessageBackgroundHover'
|
|
49
|
+
: (accent ?? 'claude')
|
|
50
|
+
: hovered
|
|
51
|
+
? 'userMessageBackgroundHover'
|
|
52
|
+
: undefined, onClick: (event) => {
|
|
53
|
+
event.stopImmediatePropagation();
|
|
54
|
+
onClick();
|
|
55
|
+
}, onMouseEnter: () => {
|
|
56
|
+
setHovered(true);
|
|
57
|
+
}, onMouseLeave: () => {
|
|
58
|
+
setHovered(false);
|
|
59
|
+
}, children: _jsx(Text, { bold: primary || hovered, color: primary && !hovered ? 'inverseText' : undefined, dimColor: !primary && !hovered, children: text }) }));
|
|
60
|
+
}
|
|
@@ -9,6 +9,18 @@ import type { Channel } from '../dsh-adapter/channel.js';
|
|
|
9
9
|
export interface PromptController {
|
|
10
10
|
hasText(): boolean;
|
|
11
11
|
clear(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Copy the active mouse selection to the system clipboard (OSC 52 + the
|
|
14
|
+
* native fallback) and KEEP the selection for further editing. Returns
|
|
15
|
+
* true when a selection existed and consumed the key; Chat's Ctrl+C
|
|
16
|
+
* branch calls this first, before its clear/exit semantics.
|
|
17
|
+
*/
|
|
18
|
+
consumeSelectionCopy(): boolean;
|
|
19
|
+
/** Toggle vim editing mode (`/vim`); returns the new state (true = on). */
|
|
20
|
+
toggleVim(): boolean;
|
|
21
|
+
/** True while vim mode is on (either submode). Esc belongs to vim then —
|
|
22
|
+
* Chat's working-turn Esc interrupt must yield in BOTH submodes. */
|
|
23
|
+
vimActive(): boolean;
|
|
12
24
|
}
|
|
13
25
|
export interface PromptInputProps {
|
|
14
26
|
channel: Channel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAwBzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA4OxD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,IAAI,OAAO,CAAA;IAClB,KAAK,IAAI,IAAI,CAAA;IACb;;;;;OAKG;IACH,oBAAoB,IAAI,OAAO,CAAA;IAC/B,2EAA2E;IAC3E,SAAS,IAAI,OAAO,CAAA;IACpB;yEACqE;IACrE,SAAS,IAAI,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,IAAI,IAAI,CAAA;IACpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACrD,6EAA6E;IAC7E,eAAe,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,IAAI,IAAI,CAAA;IACvB,8EAA8E;IAC9E,eAAe,CAAC,IAAI,IAAI,CAAA;IACxB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,cAAc,EACd,eAAe,EACf,aAAa,GACd,EAAE,gBAAgB,qBA85ElB"}
|