@deepseek-harness-tui/dsh-tui 0.8.5 → 0.8.7
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 +13 -3
- package/bin/dsh-tui.js +269 -218
- package/cordis.patch.yml +48 -22
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
- package/dsh-ecosystem-spec/registry/README.md +14 -14
- package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
- package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
- package/lib/types/cc/figures.d.ts +7 -0
- package/lib/types/cc/figures.d.ts.map +1 -1
- package/lib/types/cc/figures.js +24 -0
- package/lib/types/cc/markdown.d.ts.map +1 -1
- package/lib/types/cc/markdown.js +47 -14
- package/lib/types/cc/syntaxRuns.d.ts +16 -0
- package/lib/types/cc/syntaxRuns.d.ts.map +1 -0
- package/lib/types/cc/syntaxRuns.js +79 -0
- package/lib/types/cc/syntaxTheme.d.ts +12 -0
- package/lib/types/cc/syntaxTheme.d.ts.map +1 -0
- package/lib/types/cc/syntaxTheme.js +76 -0
- package/lib/types/commands.d.ts +14 -0
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +20 -1
- package/lib/types/components/Chat/SubagentMessage.d.ts +19 -0
- package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -0
- package/lib/types/components/Chat/SubagentMessage.js +75 -0
- package/lib/types/components/EffortChargeGlyph.d.ts +26 -0
- package/lib/types/components/EffortChargeGlyph.d.ts.map +1 -0
- package/lib/types/components/EffortChargeGlyph.js +70 -0
- package/lib/types/components/EffortInputBorder.d.ts +36 -0
- package/lib/types/components/EffortInputBorder.d.ts.map +1 -0
- package/lib/types/components/EffortInputBorder.js +73 -0
- package/lib/types/components/EffortTierBadge.d.ts +26 -0
- package/lib/types/components/EffortTierBadge.d.ts.map +1 -0
- package/lib/types/components/EffortTierBadge.js +97 -0
- package/lib/types/components/HelpMenu.d.ts +8 -1
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +15 -4
- package/lib/types/components/LoadedContextPanel.js +1 -1
- package/lib/types/components/LogoV2.d.ts +3 -1
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +2 -2
- package/lib/types/components/MessageList.d.ts +6 -2
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +22 -13
- package/lib/types/components/ModelPicker.js +2 -2
- package/lib/types/components/PromptInput.d.ts +1 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +83 -18
- package/lib/types/components/SkillsPicker.js +2 -2
- package/lib/types/components/SplitDiffView.d.ts +2 -17
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +9 -162
- package/lib/types/components/StreamingMarkdown.js +1 -1
- package/lib/types/components/SubagentCard.d.ts +9 -0
- package/lib/types/components/SubagentCard.d.ts.map +1 -0
- package/lib/types/components/SubagentCard.js +26 -0
- package/lib/types/components/SubagentDashboard.d.ts +13 -0
- package/lib/types/components/SubagentDashboard.d.ts.map +1 -0
- package/lib/types/components/SubagentDashboard.js +50 -0
- package/lib/types/components/SubagentDetailScene.d.ts +16 -0
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -0
- package/lib/types/components/SubagentDetailScene.js +141 -0
- package/lib/types/components/SyntaxText.d.ts +15 -0
- package/lib/types/components/SyntaxText.d.ts.map +1 -0
- package/lib/types/components/SyntaxText.js +34 -0
- package/lib/types/components/ThinkingToggle.d.ts +3 -10
- package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
- package/lib/types/components/ThinkingToggle.js +4 -9
- package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
- package/lib/types/components/design-system/ListItem.js +1 -1
- package/lib/types/components/design-system/ThemedBox.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemedBox.js +4 -1
- package/lib/types/components/design-system/ThemedText.js +2 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +12 -6
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +37 -10
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -0
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +71 -18
- package/lib/types/components/messages/UserPromptMessage.d.ts +4 -6
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +19 -10
- package/lib/types/dsh-adapter/channel.d.ts +58 -2
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +337 -7
- package/lib/types/dsh-adapter/contract.d.ts +27 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +56 -10
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +9 -3
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +38 -0
- package/lib/types/dsh-adapter/shortcuts.js +3 -3
- package/lib/types/dsh-adapter/subagents.d.ts +87 -0
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -0
- package/lib/types/dsh-adapter/subagents.js +204 -0
- package/lib/types/herdr.d.ts +28 -0
- package/lib/types/herdr.d.ts.map +1 -0
- package/lib/types/herdr.js +133 -0
- package/lib/types/i18n.d.ts +215 -31
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +65 -14
- package/lib/types/ink/ink.d.ts +4 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +46 -15
- package/lib/types/minimalMode.d.ts +13 -0
- package/lib/types/minimalMode.d.ts.map +1 -0
- package/lib/types/minimalMode.js +17 -0
- package/lib/types/screens/Chat.d.ts +1 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +95 -45
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +6 -2
- package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
- package/lib/types/screens/TrajectoryScene.js +4 -2
- package/lib/types/theme.d.ts +20 -0
- package/lib/types/theme.d.ts.map +1 -1
- package/lib/types/theme.js +77 -23
- package/lib/types/tips.js +3 -3
- package/lib/types/trajectory/effortIgnition.d.ts +66 -0
- package/lib/types/trajectory/effortIgnition.d.ts.map +1 -0
- package/lib/types/trajectory/effortIgnition.js +142 -0
- package/lib/types/update.d.ts +18 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +73 -2
- package/lib/types/utils/execFileNoThrow.d.ts +3 -20
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
- package/lib/types/utils/execFileNoThrow.js +53 -32
- package/lib/types/utils/externalEditor.d.ts +12 -11
- package/lib/types/utils/externalEditor.d.ts.map +1 -1
- package/lib/types/utils/externalEditor.js +11 -11
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/command/LICENSE +21 -21
- package/node_modules/@dsh-std/command/README.md +26 -26
- package/node_modules/@dsh-std/command/README.zh.md +28 -28
- package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/command/package.json +22 -22
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/node_modules/@dsh-std/connection/README.md +42 -42
- package/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +20 -20
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/core/LICENSE +21 -21
- package/node_modules/@dsh-std/core/README.md +13 -13
- package/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/core/package.json +21 -21
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/node_modules/@dsh-std/manifest/README.md +5 -5
- package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/manifest/package.json +20 -20
- package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/messages/LICENSE +21 -21
- package/node_modules/@dsh-std/messages/README.md +5 -5
- package/node_modules/@dsh-std/messages/README.zh.md +7 -7
- package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/messages/package.json +20 -20
- package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/node_modules/@dsh-std/presentation/README.md +27 -27
- package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +25 -25
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/storage/LICENSE +21 -21
- package/node_modules/@dsh-std/storage/README.md +5 -5
- package/node_modules/@dsh-std/storage/README.zh.md +7 -7
- package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/storage/package.json +20 -20
- package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
- package/package.json +64 -58
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
|
@@ -12,7 +12,10 @@ function resolveColor(color, theme) {
|
|
|
12
12
|
color.startsWith('ansi:')) {
|
|
13
13
|
return color;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
// Theme keys may be '' ("no color" in that theme) - collapse to undefined
|
|
16
|
+
// so empty tokens render as no background/foreground instead of feeding
|
|
17
|
+
// an empty color string to Ink.
|
|
18
|
+
return theme[color] || undefined;
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
21
|
* Theme-aware Box component that resolves theme color keys to raw colors
|
|
@@ -20,8 +20,8 @@ function resolveColor(color, theme) {
|
|
|
20
20
|
color.startsWith('ansi:')) {
|
|
21
21
|
return color;
|
|
22
22
|
}
|
|
23
|
-
// It's a theme key - resolve it
|
|
24
|
-
return theme[color];
|
|
23
|
+
// It's a theme key - resolve it ('' means "no color" in that theme)
|
|
24
|
+
return theme[color] || undefined;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Theme-aware Text component that resolves theme color keys to raw colors
|
|
@@ -5,6 +5,10 @@ type Props = {
|
|
|
5
5
|
addMargin: boolean;
|
|
6
6
|
/** True when Ctrl+O transcript/verbose mode is on — show the full text. */
|
|
7
7
|
verbose: boolean;
|
|
8
|
+
/** True while the reasoning block is still streaming — the leading anchor
|
|
9
|
+
* becomes a rotating braille spinner (Kimi Code style) and settles back
|
|
10
|
+
* to the anchor once the step ends. */
|
|
11
|
+
streaming?: boolean;
|
|
8
12
|
/** Streaming compact mode (thinkingFold=preview): a 3-row live ticker of
|
|
9
13
|
* the model's latest reasoning lines instead of the full block —
|
|
10
14
|
* kimicode-style constant height; the block never resizes mid-stream. */
|
|
@@ -16,12 +20,14 @@ type Props = {
|
|
|
16
20
|
onClick?(): void;
|
|
17
21
|
};
|
|
18
22
|
/**
|
|
19
|
-
* Thinking block: folded
|
|
20
|
-
* full reasoning text indented under
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
23
|
+
* Thinking block: folded `⚓ Thinking (ctrl+o to expand)`, expanded shows the
|
|
24
|
+
* full reasoning text indented under `⚓ Thinking…`. While the reasoning
|
|
25
|
+
* streams the leading mark is a rotating braille spinner (`⠋⠙⠹…`, Kimi Code
|
|
26
|
+
* style), settling back to the static anchor (`⚓`) once the turn ends. When
|
|
27
|
+
* the channel records the reasoning duration, the label carries it
|
|
28
|
+
* (`⚓ Thinking · 12s …`) — dsh-tui's take on making thinking time visible in
|
|
29
|
+
* the transcript.
|
|
24
30
|
*/
|
|
25
|
-
export declare function AssistantThinkingMessage({ thinking, addMargin, verbose, preview, durationMs, isSelected, onClick, }: Props): React.ReactNode;
|
|
31
|
+
export declare function AssistantThinkingMessage({ thinking, addMargin, verbose, streaming, preview, durationMs, isSelected, onClick, }: Props): React.ReactNode;
|
|
26
32
|
export {};
|
|
27
33
|
//# sourceMappingURL=AssistantThinkingMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantThinkingMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantThinkingMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"AssistantThinkingMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantThinkingMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAuBzB,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAA;IAChB;;4CAEwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;8EAE0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,IAAI,IAAI,CAAA;CACjB,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,SAAS,EACT,OAAO,EACP,SAAiB,EACjB,OAAe,EACf,UAAU,EACV,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAwHzB"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import chalk from 'chalk';
|
|
2
4
|
import { Box, Text } from '../../ui.js';
|
|
3
5
|
import { t } from '../../i18n.js';
|
|
4
6
|
import { StreamingMarkdown } from '../StreamingMarkdown.js';
|
|
5
7
|
import { formatDuration } from '../../cc/format.js';
|
|
8
|
+
import { THINKING_SPINNER_FRAMES, THINKING_SPINNER_INTERVAL_MS, THINKING_SETTLED_MARKER, } from '../../cc/figures.js';
|
|
9
|
+
import { BRAND, ICE } from '../shimmer.js';
|
|
10
|
+
import { interpolateColor } from '../Spinner/spinnerUtils.js';
|
|
11
|
+
import { isMinimalMode } from '../../minimalMode.js';
|
|
6
12
|
/** Preview body rows — a FIXED row count (kimicode-style constant-height
|
|
7
13
|
* ticker). Ink's truncate slices the whole string across newlines as one
|
|
8
14
|
* logical line, so a single joined Text collapses to 1-2 rows whenever
|
|
@@ -11,18 +17,39 @@ import { formatDuration } from '../../cc/format.js';
|
|
|
11
17
|
* to exactly this many rows, keeps the block height stream-independent. */
|
|
12
18
|
const PREVIEW_ROWS = 3;
|
|
13
19
|
/**
|
|
14
|
-
* Thinking block: folded
|
|
15
|
-
* full reasoning text indented under
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
20
|
+
* Thinking block: folded `⚓ Thinking (ctrl+o to expand)`, expanded shows the
|
|
21
|
+
* full reasoning text indented under `⚓ Thinking…`. While the reasoning
|
|
22
|
+
* streams the leading mark is a rotating braille spinner (`⠋⠙⠹…`, Kimi Code
|
|
23
|
+
* style), settling back to the static anchor (`⚓`) once the turn ends. When
|
|
24
|
+
* the channel records the reasoning duration, the label carries it
|
|
25
|
+
* (`⚓ Thinking · 12s …`) — dsh-tui's take on making thinking time visible in
|
|
26
|
+
* the transcript.
|
|
19
27
|
*/
|
|
20
|
-
export function AssistantThinkingMessage({ thinking, addMargin, verbose, preview = false, durationMs, isSelected = false, onClick, }) {
|
|
28
|
+
export function AssistantThinkingMessage({ thinking, addMargin, verbose, streaming = false, preview = false, durationMs, isSelected = false, onClick, }) {
|
|
21
29
|
if (!thinking)
|
|
22
30
|
return null;
|
|
31
|
+
// Spinner frame (80ms cadence, only while the reasoning is still
|
|
32
|
+
// streaming — same pattern as BtwPanel's answering spinner).
|
|
33
|
+
const [frame, setFrame] = React.useState(0);
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
if (!streaming)
|
|
36
|
+
return;
|
|
37
|
+
const interval = setInterval(() => setFrame(f => f + 1), THINKING_SPINNER_INTERVAL_MS);
|
|
38
|
+
return () => clearInterval(interval);
|
|
39
|
+
}, [streaming]);
|
|
23
40
|
const duration = durationMs !== undefined && durationMs >= 1000
|
|
24
41
|
? ` · ${formatDuration(durationMs)}`
|
|
25
42
|
: '';
|
|
43
|
+
// Kimi Code style blue pulse: the streaming glyph breathes along the
|
|
44
|
+
// header's brand→ice ladder, one sine period per ~7 frames (≈0.56s) —
|
|
45
|
+
// lively without strobing. Minimal mode drops the color (plain glyph);
|
|
46
|
+
// settled always keeps the plain dim anchor.
|
|
47
|
+
const label = `${t('thinking-label')}${duration}${streaming ? '…' : ` ${t('hint-expand-ctrl-o')}`}`;
|
|
48
|
+
const minimal = isMinimalMode();
|
|
49
|
+
const pulse = (Math.sin(frame * 0.9) + 1) / 2;
|
|
50
|
+
const pulseColor = interpolateColor(BRAND, ICE, pulse);
|
|
51
|
+
const frameText = THINKING_SPINNER_FRAMES[frame % THINKING_SPINNER_FRAMES.length];
|
|
52
|
+
const header = streaming ? (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { children: minimal ? frameText : chalk.rgb(pulseColor.r, pulseColor.g, pulseColor.b).bold(frameText) }), _jsx(Text, { dimColor: true, italic: true, children: ` ${label}` })] })) : (_jsx(Text, { dimColor: true, italic: true, children: `${minimal ? '*' : THINKING_SETTLED_MARKER} ${label}` }));
|
|
26
53
|
if (preview) {
|
|
27
54
|
// Live ticker: the model's last few reasoning lines, dimmed, one Text
|
|
28
55
|
// per row so each truncates to the width independently, padded to a
|
|
@@ -37,10 +64,10 @@ export function AssistantThinkingMessage({ thinking, addMargin, verbose, preview
|
|
|
37
64
|
// Pad with single spaces — an empty-string Text renders with zero
|
|
38
65
|
// height in ink, so '' padding would not hold the row open.
|
|
39
66
|
const rows = Array.from({ length: PREVIEW_ROWS }, (_, i) => visible[i] ?? ' ');
|
|
40
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: addMargin ? 1 : 0, backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children: [
|
|
67
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: addMargin ? 1 : 0, backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children: [header, _jsx(Box, { flexDirection: "column", paddingLeft: 2, height: PREVIEW_ROWS, flexShrink: 0, overflow: "hidden", children: rows.map((line, i) => (_jsxs(Box, { flexDirection: "row", height: 1, children: [_jsx(Text, { dimColor: true, italic: true, children: '│ ' }), _jsx(Box, { flexDirection: "row", flexGrow: 1, children: _jsx(Text, { dimColor: true, italic: true, wrap: i === rows.length - 1 ? 'truncate-start' : 'truncate', children: i === 0 && clipped ? `…${line}` : line }) })] }, i))) })] }));
|
|
41
68
|
}
|
|
42
69
|
if (!verbose) {
|
|
43
|
-
return (_jsx(Box, { marginTop: addMargin ? 1 : 0, backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children:
|
|
70
|
+
return (_jsx(Box, { marginTop: addMargin ? 1 : 0, backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children: header }));
|
|
44
71
|
}
|
|
45
|
-
return (_jsxs(Box, { flexDirection: "column", gap: 1, marginTop: addMargin ? 1 : 0, width: "100%", backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children: [
|
|
72
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, marginTop: addMargin ? 1 : 0, width: "100%", backgroundColor: isSelected ? 'messageActionsBackground' : undefined, onClick: onClick, children: [header, _jsx(Box, { paddingLeft: 2, children: _jsx(StreamingMarkdown, { dimColor: true, children: thinking }) })] }));
|
|
46
73
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ToolRow } from '../../dsh-adapter/channel.js';
|
|
3
3
|
import type { ToolBackground } from '../../tuiDisplayPrefs.js';
|
|
4
|
+
import type { Theme } from '../../theme.js';
|
|
4
5
|
type Props = {
|
|
5
6
|
tool: ToolRow;
|
|
6
7
|
/** Adds the top margin between messages (CC: addMargin). */
|
|
@@ -25,6 +26,7 @@ type Props = {
|
|
|
25
26
|
/** Background treatment for the ordinary, unselected tool card surface. */
|
|
26
27
|
toolBackground?: ToolBackground;
|
|
27
28
|
};
|
|
29
|
+
export declare function toolNameColor(raw: string): keyof Theme;
|
|
28
30
|
/**
|
|
29
31
|
* Tool-call card: `● Edit /path` header with a blinking status dot, then the
|
|
30
32
|
* structured body under a ` ⎿ ` gutter — diff hunks in red/green, terminal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantToolUseMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantToolUseMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"AssistantToolUseMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantToolUseMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAA8C,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAKvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAA;IACb,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAA;IAClB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAA;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC,CAAA;AAgFD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,CAKtD;AAwKD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,SAAS,EACT,OAAO,EACP,UAAkB,EAClB,UAAkB,EAClB,QAAQ,EACR,UAAmB,EACnB,cAAuB,GACxB,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAmKzB"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { extname } from 'node:path';
|
|
2
3
|
import { Box, Text, useTerminalSize } from '../../ui.js';
|
|
3
4
|
import { stringWidth } from '../../ink/stringWidth.js';
|
|
4
5
|
import { useAnimationFrame } from '../../ink/hooks/use-animation-frame.js';
|
|
5
6
|
import { ToolUseLoader } from '../ToolUseLoader.js';
|
|
6
7
|
import { SplitDiffView } from '../SplitDiffView.js';
|
|
8
|
+
import { SyntaxText } from '../SyntaxText.js';
|
|
7
9
|
import { formatDuration } from '../../cc/format.js';
|
|
8
10
|
/** Tool display names: DSH emits lowercase tool ids (`bash`); Claude Code
|
|
9
11
|
* shows capitalized names (`Bash`). Map the common ones, fall back to the
|
|
@@ -28,6 +30,33 @@ function displayName(name) {
|
|
|
28
30
|
return name;
|
|
29
31
|
return name[0].toUpperCase() + name.slice(1);
|
|
30
32
|
}
|
|
33
|
+
function parseJsonArgs(args) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(args);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function jsonArgsLanguage(args) {
|
|
42
|
+
return parseJsonArgs(args) === undefined ? undefined : 'json';
|
|
43
|
+
}
|
|
44
|
+
function filePathFromTool(tool, view) {
|
|
45
|
+
if (view !== undefined && 'path' in view && typeof view.path === 'string')
|
|
46
|
+
return view.path;
|
|
47
|
+
const parsed = parseJsonArgs(tool.argsFull ?? tool.argsText);
|
|
48
|
+
if (parsed !== null && typeof parsed === 'object') {
|
|
49
|
+
const record = parsed;
|
|
50
|
+
for (const key of ['file_path', 'path'])
|
|
51
|
+
if (typeof record[key] === 'string')
|
|
52
|
+
return record[key];
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
function languageFromPath(path) {
|
|
57
|
+
const language = path === undefined ? undefined : extname(path).slice(1).toLowerCase();
|
|
58
|
+
return language === '' ? undefined : language;
|
|
59
|
+
}
|
|
31
60
|
/** CC's collapsed text body keeps 3 lines (renderTruncatedContent). */
|
|
32
61
|
const TEXT_BODY_MAX_LINES = 3;
|
|
33
62
|
/** Diff bodies cap at the upstream chat row's 8 (dsh-client-ui-tool's
|
|
@@ -42,6 +71,20 @@ const add = (text) => ({ text, tone: 'add' });
|
|
|
42
71
|
const del = (text) => ({ text, tone: 'del' });
|
|
43
72
|
const dim = (text) => ({ text, tone: 'dim' });
|
|
44
73
|
const plain = (text) => ({ text, tone: 'plain' });
|
|
74
|
+
/** Tool-name color by category (mist-blue accents): read/search tools keep
|
|
75
|
+
* the brand blue, file-mutating tools get the warm gold accent, exec /
|
|
76
|
+
* terminal tools get mist cyan. Exported for the subagent card, which
|
|
77
|
+
* mirrors the transcript tool-card name styling. */
|
|
78
|
+
const TOOL_NAME_MUTATE = new Set(['edit', 'write', 'multiedit', 'notebookedit']);
|
|
79
|
+
const TOOL_NAME_EXEC = new Set(['bash', 'bashpersistent', 'sh', 'shell', 'terminal']);
|
|
80
|
+
export function toolNameColor(raw) {
|
|
81
|
+
const n = raw.toLowerCase();
|
|
82
|
+
if (TOOL_NAME_MUTATE.has(n))
|
|
83
|
+
return 'toolNameMutate';
|
|
84
|
+
if (TOOL_NAME_EXEC.has(n))
|
|
85
|
+
return 'toolNameExec';
|
|
86
|
+
return 'claude';
|
|
87
|
+
}
|
|
45
88
|
/** One side's text → display lines (upstream contentLines rule: empty text
|
|
46
89
|
* is zero lines; a single trailing newline is a terminator, not a line;
|
|
47
90
|
* interior blanks survive). */
|
|
@@ -62,7 +105,7 @@ function diffLines(diffs) {
|
|
|
62
105
|
for (const diff of diffs) {
|
|
63
106
|
if (diffs.length > 1) {
|
|
64
107
|
if (diff.path !== prevPath)
|
|
65
|
-
out.push(
|
|
108
|
+
out.push({ text: diff.path, tone: 'path' });
|
|
66
109
|
else
|
|
67
110
|
out.push(dim('⋯'));
|
|
68
111
|
}
|
|
@@ -81,7 +124,7 @@ function contentLines(content) {
|
|
|
81
124
|
const text = (content ?? []).map(block => (block.type === 'text' ? block.text ?? '' : '')).join('').trimEnd();
|
|
82
125
|
if (text === '')
|
|
83
126
|
return [];
|
|
84
|
-
return text.split('\n').map(
|
|
127
|
+
return text.split('\n').map(plain);
|
|
85
128
|
}
|
|
86
129
|
/** Per-card body lines; unknown/absent shapes yield [] so the caller falls
|
|
87
130
|
* back to the raw result text. */
|
|
@@ -93,7 +136,7 @@ function viewLines(view) {
|
|
|
93
136
|
// The call-side terminal card has no output yet; only presentResult's
|
|
94
137
|
// does. `in` narrows the call/result union without extra types.
|
|
95
138
|
const out = (('output' in view ? view.output : undefined) ?? '').trimEnd();
|
|
96
|
-
const lines = out === '' ? [] : out.split('\n').map(
|
|
139
|
+
const lines = out === '' ? [] : out.split('\n').map(plain);
|
|
97
140
|
if ('exitCode' in view && view.exitCode !== undefined && view.exitCode !== 0) {
|
|
98
141
|
lines.push({ text: `Exit code ${view.exitCode}`, tone: 'error' });
|
|
99
142
|
}
|
|
@@ -117,7 +160,7 @@ function viewLines(view) {
|
|
|
117
160
|
for (const file of view.files) {
|
|
118
161
|
lines.push(plain(file.path));
|
|
119
162
|
for (const match of file.matches) {
|
|
120
|
-
lines.push(
|
|
163
|
+
lines.push(plain(`${match.lineNumber}: ${match.line}`));
|
|
121
164
|
}
|
|
122
165
|
}
|
|
123
166
|
if (view.truncated)
|
|
@@ -156,21 +199,21 @@ function clipHeaderArgs(args) {
|
|
|
156
199
|
return args;
|
|
157
200
|
return `${args.slice(0, HEADER_ARGS_BUDGET)}…`;
|
|
158
201
|
}
|
|
159
|
-
function HeaderTitle({ name, title, isTerminal, displayArgs }) {
|
|
202
|
+
function HeaderTitle({ name, title, isTerminal, displayArgs, argsLanguage, nameColor }) {
|
|
160
203
|
if (title === undefined) {
|
|
161
|
-
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, wrap: "truncate-end", children: name }) }), displayArgs !== '' && (
|
|
204
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), displayArgs !== '' && (_jsxs(Box, { flexWrap: "nowrap", children: [_jsx(Text, { children: "(" }), _jsx(SyntaxText, { text: clipHeaderArgs(displayArgs), sourceText: displayArgs, language: argsLanguage }), _jsx(Text, { children: ")" })] }))] }));
|
|
162
205
|
}
|
|
163
206
|
if (isTerminal) {
|
|
164
|
-
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { children: ["(", title, ")"] }) })] }));
|
|
207
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { children: ["(", title, ")"] }) })] }));
|
|
165
208
|
}
|
|
166
209
|
const trimmed = title.trim();
|
|
167
210
|
if (trimmed === '') {
|
|
168
|
-
return (_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, wrap: "truncate-end", children: name }) }));
|
|
211
|
+
return (_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }));
|
|
169
212
|
}
|
|
170
213
|
const space = trimmed.indexOf(' ');
|
|
171
214
|
const head = space === -1 ? trimmed : trimmed.slice(0, space);
|
|
172
215
|
const tail = space === -1 ? '' : trimmed.slice(space);
|
|
173
|
-
return (_jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { bold: true, wrap: "truncate-end", children: [head, _jsx(Text, { bold: false, children: tail })] }) }));
|
|
216
|
+
return (_jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: [head, _jsx(Text, { bold: false, color: "text", children: tail })] }) }));
|
|
174
217
|
}
|
|
175
218
|
/**
|
|
176
219
|
* Tool-call card: `● Edit /path` header with a blinking status dot, then the
|
|
@@ -188,6 +231,10 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
188
231
|
// The settled view carries the applied diff / actual output; while running,
|
|
189
232
|
// the call view already shows the pending change (CC's pending Edit diff).
|
|
190
233
|
const view = tool.resultView ?? tool.callView;
|
|
234
|
+
const filePath = filePathFromTool(tool, view);
|
|
235
|
+
const syntaxLanguage = view?.card === 'read' || view?.card === 'generic' || view === undefined
|
|
236
|
+
? languageFromPath(filePath)
|
|
237
|
+
: undefined;
|
|
191
238
|
// presentResult may omit a title (terminal results carry output, not a
|
|
192
239
|
// command) — then the call view's title stands.
|
|
193
240
|
const headerTitle = tool.resultView?.title ?? tool.callView?.title;
|
|
@@ -218,13 +265,15 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
218
265
|
if (view !== undefined)
|
|
219
266
|
body = viewLines(view);
|
|
220
267
|
if (body.length === 0 && result) {
|
|
221
|
-
body = result.trimEnd().split('\n').map(
|
|
268
|
+
body = result.trimEnd().split('\n').map(plain);
|
|
222
269
|
}
|
|
223
270
|
if (isRunning && body.length === 0) {
|
|
224
271
|
body = [dim(`Running… (${formatDuration(Math.max(0, Date.now() - (tool.startedAt ?? Date.now())))})`)];
|
|
225
272
|
}
|
|
226
273
|
}
|
|
227
274
|
const cap = view?.card === 'diff' ? DIFF_BODY_MAX_LINES : TEXT_BODY_MAX_LINES;
|
|
275
|
+
const bodySource = body.map(line => line.text).join('\n');
|
|
276
|
+
const argsLanguage = jsonArgsLanguage(displayArgs);
|
|
228
277
|
// The footnote rides OUTSIDE the cap: it is a pointer, not content, and a
|
|
229
278
|
// long error body must not be the reason it disappears.
|
|
230
279
|
const lines = capLines(body, cap, verbose);
|
|
@@ -238,13 +287,15 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
238
287
|
? 'toolCardBackground'
|
|
239
288
|
: undefined;
|
|
240
289
|
return (_jsx(Box, { ref: viewportRef, flexDirection: "row", justifyContent: "space-between", marginTop: addMargin ? 1 : 0, width: "100%",
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
backgroundColor: isSelected
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
290
|
+
// Only selection paints a highlight; the configured treatment applies
|
|
291
|
+
// to an ordinary card. Diff line tints stay - they are content, not chrome.
|
|
292
|
+
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
|
+
? 'diffAddedWord'
|
|
294
|
+
: line.tone === 'del'
|
|
295
|
+
? 'diffRemovedWord'
|
|
296
|
+
: line.tone === 'path'
|
|
297
|
+
? 'ide'
|
|
298
|
+
: undefined, dimColor: line.tone !== 'add' && line.tone !== 'del' && line.tone !== 'path', children: index === 0 ? GUTTER_FIRST : GUTTER_REST }) }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { color: line.tone === 'add'
|
|
248
299
|
? 'diffAddedWord'
|
|
249
300
|
: line.tone === 'del'
|
|
250
301
|
? 'diffRemovedWord'
|
|
@@ -252,5 +303,7 @@ export function AssistantToolUseMessage({ tool, addMargin, verbose, isSelected =
|
|
|
252
303
|
? 'error'
|
|
253
304
|
: line.tone === 'hint'
|
|
254
305
|
? 'subtle'
|
|
255
|
-
:
|
|
306
|
+
: line.tone === 'path'
|
|
307
|
+
? 'ide'
|
|
308
|
+
: undefined, dimColor: line.tone === 'dim', wrap: "wrap", children: line.tone === 'plain' && syntaxLanguage !== undefined ? (_jsx(SyntaxText, { text: line.text, sourceText: bodySource, lineIndex: index, language: syntaxLanguage })) : (line.text === '' ? ' ' : line.text) }) })] }, index)))), useSplitDiff && footnote !== undefined && (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: 3, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: GUTTER_REST }) }), _jsx(Text, { color: "subtle", children: footnote })] }))] }) }));
|
|
256
309
|
}
|
|
@@ -5,15 +5,13 @@ type Props = {
|
|
|
5
5
|
addMargin: boolean;
|
|
6
6
|
/** Message-selection mode highlight. */
|
|
7
7
|
isSelected?: boolean;
|
|
8
|
-
/** Row expanded on its own (persistent hover-grey background, CC). */
|
|
9
|
-
isExpanded?: boolean;
|
|
10
8
|
onClick?(): void;
|
|
11
9
|
};
|
|
12
10
|
/**
|
|
13
|
-
* User prompt bubble: `❯ text`
|
|
14
|
-
* (
|
|
15
|
-
*
|
|
11
|
+
* User prompt bubble: `❯ text` in bold briefLabelYou gold with no background
|
|
12
|
+
* fill (Kimi Code style: the user turn gets a distinct bold tint so it reads
|
|
13
|
+
* apart from assistant text; only selection mode paints a highlight).
|
|
16
14
|
*/
|
|
17
|
-
export declare function UserPromptMessage({ text, addMargin, isSelected,
|
|
15
|
+
export declare function UserPromptMessage({ text, addMargin, isSelected, onClick, }: Props): React.ReactNode;
|
|
18
16
|
export {};
|
|
19
17
|
//# sourceMappingURL=UserPromptMessage.d.ts.map
|
|
@@ -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;AAMzB,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,IAAI,IAAI,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,SAAS,EACT,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA6BzB"}
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from '../../ui.js';
|
|
2
|
+
import { Box, Text, useTerminalSize } from '../../ui.js';
|
|
3
3
|
import { POINTER } from '../../cc/figures.js';
|
|
4
|
+
import { stringWidth } from '../../ink/stringWidth.js';
|
|
5
|
+
import { wrapWidth } from '../../sessions/format.js';
|
|
4
6
|
/**
|
|
5
|
-
* User prompt bubble: `❯ text`
|
|
6
|
-
* (
|
|
7
|
-
*
|
|
7
|
+
* User prompt bubble: `❯ text` in bold briefLabelYou gold with no background
|
|
8
|
+
* fill (Kimi Code style: the user turn gets a distinct bold tint so it reads
|
|
9
|
+
* apart from assistant text; only selection mode paints a highlight).
|
|
8
10
|
*/
|
|
9
|
-
export function UserPromptMessage({ text, addMargin, isSelected = false,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
export function UserPromptMessage({ text, addMargin, isSelected = false, onClick, }) {
|
|
12
|
+
const { columns } = useTerminalSize();
|
|
13
|
+
const promptPrefix = `${POINTER} `;
|
|
14
|
+
const prefixWidth = stringWidth(promptPrefix);
|
|
15
|
+
// Wrap here instead of letting Ink wrap the whole Text node. Ink starts an
|
|
16
|
+
// automatic continuation at column zero, while a prompt needs a hanging
|
|
17
|
+
// indent for both explicit newlines and width-based visual lines.
|
|
18
|
+
// Leave a small safety margin for the ScrollBox edge/scrollbar. The Text
|
|
19
|
+
// nodes below are explicitly wrapped, so they must never be wrapped again by
|
|
20
|
+
// Ink; a second wrap would move the continuation back to column zero.
|
|
21
|
+
const lines = wrapWidth(text, Math.max(1, columns - prefixWidth - 3));
|
|
22
|
+
const continuationIndent = ' '.repeat(prefixWidth);
|
|
23
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: addMargin ? 1 : 0, backgroundColor: isSelected ? 'messageActionsBackground' : undefined, paddingRight: 1, onClick: onClick, children: lines.map((line, index) => (_jsxs(Text, { color: "briefLabelYou", bold: true, wrap: "truncate-end", children: [index === 0 ? `${POINTER} ` : continuationIndent, line] }, index))) }));
|
|
15
24
|
}
|
|
@@ -8,6 +8,8 @@ import { type PreviewEntry, type SessionSummary } from './sessions/index.js';
|
|
|
8
8
|
import type { ProviderSetupHost } from './providerWizard.js';
|
|
9
9
|
import { type SessionModeSpec } from '../sessionModes.js';
|
|
10
10
|
import { type StatusBarConfig, type ToolBackground } from '../tuiDisplayPrefs.js';
|
|
11
|
+
import { type SubagentState } from './subagents.js';
|
|
12
|
+
export type { SubagentState } from './subagents.js';
|
|
11
13
|
import type { SpinnerMode } from '../components/Spinner/spinnerMode.js';
|
|
12
14
|
import { type ActivityState } from 'dsh-working-activity/status';
|
|
13
15
|
import { type TuiWorkspaceCommand, type TuiWorkspaceCommandResult, type TuiWorkspaceTarget } from './workspaces.js';
|
|
@@ -125,6 +127,31 @@ export interface ToolViewPresenter {
|
|
|
125
127
|
call(name: string, rawArgs: string): ToolCallView | undefined;
|
|
126
128
|
result(name: string, rawArgs: string, data: SessionEvent<'tool/result'>['data']): ToolResultView | undefined;
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Subagent row: displays a subagent's lifecycle (started → running → completed/failed).
|
|
132
|
+
* Derived from agent.task events and history events.
|
|
133
|
+
*/
|
|
134
|
+
export interface SubagentControl {
|
|
135
|
+
interrupt(agentId: string): boolean;
|
|
136
|
+
}
|
|
137
|
+
export interface SubagentRow {
|
|
138
|
+
agentId: string;
|
|
139
|
+
runId?: string;
|
|
140
|
+
description: string;
|
|
141
|
+
provider?: string;
|
|
142
|
+
model?: string;
|
|
143
|
+
effort?: string;
|
|
144
|
+
status: SubagentState['status'];
|
|
145
|
+
startedAt: number;
|
|
146
|
+
completedAt?: number;
|
|
147
|
+
durationMs?: number;
|
|
148
|
+
outputLines: string[];
|
|
149
|
+
toolCalls: SubagentState['toolCalls'];
|
|
150
|
+
tokens?: SubagentState['tokens'];
|
|
151
|
+
summary?: string;
|
|
152
|
+
stopReason?: string;
|
|
153
|
+
error?: string;
|
|
154
|
+
}
|
|
128
155
|
/**
|
|
129
156
|
* One rendered transcript row. The DSH session log is the source of truth:
|
|
130
157
|
* rows are derived from `session/event` records (and the initial
|
|
@@ -132,7 +159,7 @@ export interface ToolViewPresenter {
|
|
|
132
159
|
*/
|
|
133
160
|
export interface ChatRow {
|
|
134
161
|
id: number;
|
|
135
|
-
kind: 'user' | 'assistant' | 'tool' | 'notice' | 'reasoning' | 'interrupt' | 'local' | 'local-output' | 'compact';
|
|
162
|
+
kind: 'user' | 'assistant' | 'tool' | 'notice' | 'reasoning' | 'interrupt' | 'local' | 'local-output' | 'compact' | 'subagent';
|
|
136
163
|
/** Extra label for non-human user rows (e.g. `steering`). */
|
|
137
164
|
label?: string;
|
|
138
165
|
/** Actual execution location for `!command` rows. */
|
|
@@ -142,6 +169,8 @@ export interface ChatRow {
|
|
|
142
169
|
streaming?: boolean;
|
|
143
170
|
/** Present on `tool` rows; the card model. */
|
|
144
171
|
tool?: ToolRow;
|
|
172
|
+
/** Present on `subagent` rows; the subagent state snapshot. */
|
|
173
|
+
subagent?: SubagentRow;
|
|
145
174
|
/** Event wall-clock time (transcript-mode metadata, assistant rows). */
|
|
146
175
|
time?: number;
|
|
147
176
|
/** Present on `reasoning` rows once settled: thinking wall-clock duration. */
|
|
@@ -317,6 +346,9 @@ export interface Channel {
|
|
|
317
346
|
readonly contextWindow: number | undefined;
|
|
318
347
|
/** Reasoning effort of the latest request header, when the adapter sets one. */
|
|
319
348
|
readonly reasoningEffort: string | undefined;
|
|
349
|
+
/** The live route's reasoning-effort level ids, low → high (the last entry
|
|
350
|
+
* is the top tier). Consumed by top-tier-triggered UI (effort ignition). */
|
|
351
|
+
readonly effortLevels: readonly string[] | undefined;
|
|
320
352
|
/** Usage of the most recent request (context share + cache hits come from
|
|
321
353
|
* this, not the running totals — each request's input IS the context). */
|
|
322
354
|
readonly lastUsage: {
|
|
@@ -345,6 +377,11 @@ export interface Channel {
|
|
|
345
377
|
readonly toolBackground: ToolBackground;
|
|
346
378
|
/** Live status-footer visibility and compactness preferences. */
|
|
347
379
|
readonly statusBar: Readonly<StatusBarConfig>;
|
|
380
|
+
/** Whether the header's pixel whale art shows (settings `dsh-tui.whale`). */
|
|
381
|
+
readonly whale: boolean;
|
|
382
|
+
/** Minimal mode (settings `dsh-tui.minimal`): no header splash, no emoji
|
|
383
|
+
* glyphs, no decorative colors; code highlight and tool colors stay. */
|
|
384
|
+
readonly minimal: boolean;
|
|
348
385
|
/** Whether the in-process working-activity line is shown (config.activity). */
|
|
349
386
|
readonly activityEnabled: boolean;
|
|
350
387
|
/** Whether the segmented context bar row shows in the status footer
|
|
@@ -426,6 +463,10 @@ export interface Channel {
|
|
|
426
463
|
thinking: number;
|
|
427
464
|
tools: number;
|
|
428
465
|
};
|
|
466
|
+
/** Active subagents spawned by the current session. */
|
|
467
|
+
readonly subagents: readonly SubagentState[];
|
|
468
|
+
/** Native control operations; unavailable providers safely return false. */
|
|
469
|
+
readonly subagentControl: SubagentControl;
|
|
429
470
|
subscribe: (listener: () => void) => () => void;
|
|
430
471
|
/** Validate and persist a pasted image, returning its prompt placeholder. */
|
|
431
472
|
stageImage(input: StagedImageInput): Promise<string>;
|
|
@@ -667,6 +708,8 @@ export interface ChannelState {
|
|
|
667
708
|
contextWindow: number | undefined;
|
|
668
709
|
/** Reasoning effort of the latest request header, when the adapter sets one. */
|
|
669
710
|
reasoningEffort: string | undefined;
|
|
711
|
+
/** The live route's reasoning-effort level ids, low → high. */
|
|
712
|
+
effortLevels: readonly string[] | undefined;
|
|
670
713
|
/** Usage of the most recent request (context share + cache hits). */
|
|
671
714
|
lastUsage: {
|
|
672
715
|
input: number;
|
|
@@ -701,6 +744,13 @@ export interface ChannelState {
|
|
|
701
744
|
setToolBackground(background: ToolBackground): void;
|
|
702
745
|
/** Apply status-footer preference changes. */
|
|
703
746
|
setStatusBar(config: Partial<StatusBarConfig>): void;
|
|
747
|
+
/** Whale header art switch (see the public Channel type). */
|
|
748
|
+
whale: boolean;
|
|
749
|
+
/** Apply a whale-visibility change (see the public Channel type). */
|
|
750
|
+
setWhale(visible: boolean): void;
|
|
751
|
+
minimal: boolean;
|
|
752
|
+
/** Apply a minimal-mode change (see the public Channel type). */
|
|
753
|
+
setMinimal(enabled: boolean): void;
|
|
704
754
|
/** Working-activity display switch (see the public Channel type). */
|
|
705
755
|
activityEnabled: boolean;
|
|
706
756
|
/** Context bar row switch (see the public Channel type). */
|
|
@@ -742,6 +792,9 @@ export interface ChannelState {
|
|
|
742
792
|
thinking: number;
|
|
743
793
|
tools: number;
|
|
744
794
|
};
|
|
795
|
+
/** Active subagents roster (see the public Channel type). */
|
|
796
|
+
subagents: readonly SubagentState[];
|
|
797
|
+
subagentControl: SubagentControl;
|
|
745
798
|
subscribe: (listener: () => void) => () => void;
|
|
746
799
|
stageImage(input: StagedImageInput): Promise<string>;
|
|
747
800
|
/** @internal event bump (the public `notify(text)` posts a notification). */
|
|
@@ -881,6 +934,10 @@ export declare function createChannel(ctx: Context, initialAgent: Agent, options
|
|
|
881
934
|
toolBackground?: ToolBackground;
|
|
882
935
|
/** Status-footer field visibility and compactness. */
|
|
883
936
|
statusBar?: Partial<StatusBarConfig>;
|
|
937
|
+
/** Show the header's pixel whale art; default on. */
|
|
938
|
+
whale?: boolean;
|
|
939
|
+
/** Minimal mode; default off (settings `dsh-tui.minimal`). */
|
|
940
|
+
minimal?: boolean;
|
|
884
941
|
/** Show the segmented context bar row in the status footer; default on
|
|
885
942
|
* (cordis.yml `contextBar: false` hides it, issue #29). */
|
|
886
943
|
contextBar?: boolean;
|
|
@@ -978,5 +1035,4 @@ export interface MentionExpansion {
|
|
|
978
1035
|
* verbatim. Best-effort failures degrade to `missing`, never a failed send.
|
|
979
1036
|
*/
|
|
980
1037
|
export declare function expandMentions(fs: MentionFs | undefined, cwd: string, text: string, attachments?: MentionAttachments, stagedImages?: ReadonlyMap<string, MentionImageBlock['attachment']>): Promise<MentionExpansion>;
|
|
981
|
-
export {};
|
|
982
1038
|
//# sourceMappingURL=channel.d.ts.map
|