@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.
Files changed (253) hide show
  1. package/README.md +13 -3
  2. package/bin/dsh-tui.js +269 -218
  3. package/cordis.patch.yml +48 -22
  4. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
  5. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
  6. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
  7. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
  8. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
  9. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
  10. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
  11. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
  12. package/dsh-ecosystem-spec/registry/README.md +14 -14
  13. package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
  14. package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
  15. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
  16. package/lib/types/cc/figures.d.ts +7 -0
  17. package/lib/types/cc/figures.d.ts.map +1 -1
  18. package/lib/types/cc/figures.js +24 -0
  19. package/lib/types/cc/markdown.d.ts.map +1 -1
  20. package/lib/types/cc/markdown.js +47 -14
  21. package/lib/types/cc/syntaxRuns.d.ts +16 -0
  22. package/lib/types/cc/syntaxRuns.d.ts.map +1 -0
  23. package/lib/types/cc/syntaxRuns.js +79 -0
  24. package/lib/types/cc/syntaxTheme.d.ts +12 -0
  25. package/lib/types/cc/syntaxTheme.d.ts.map +1 -0
  26. package/lib/types/cc/syntaxTheme.js +76 -0
  27. package/lib/types/commands.d.ts +14 -0
  28. package/lib/types/commands.d.ts.map +1 -1
  29. package/lib/types/commands.js +20 -1
  30. package/lib/types/components/Chat/SubagentMessage.d.ts +19 -0
  31. package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -0
  32. package/lib/types/components/Chat/SubagentMessage.js +75 -0
  33. package/lib/types/components/EffortChargeGlyph.d.ts +26 -0
  34. package/lib/types/components/EffortChargeGlyph.d.ts.map +1 -0
  35. package/lib/types/components/EffortChargeGlyph.js +70 -0
  36. package/lib/types/components/EffortInputBorder.d.ts +36 -0
  37. package/lib/types/components/EffortInputBorder.d.ts.map +1 -0
  38. package/lib/types/components/EffortInputBorder.js +73 -0
  39. package/lib/types/components/EffortTierBadge.d.ts +26 -0
  40. package/lib/types/components/EffortTierBadge.d.ts.map +1 -0
  41. package/lib/types/components/EffortTierBadge.js +97 -0
  42. package/lib/types/components/HelpMenu.d.ts +8 -1
  43. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  44. package/lib/types/components/HelpMenu.js +15 -4
  45. package/lib/types/components/LoadedContextPanel.js +1 -1
  46. package/lib/types/components/LogoV2.d.ts +3 -1
  47. package/lib/types/components/LogoV2.d.ts.map +1 -1
  48. package/lib/types/components/LogoV2.js +2 -2
  49. package/lib/types/components/MessageList.d.ts +6 -2
  50. package/lib/types/components/MessageList.d.ts.map +1 -1
  51. package/lib/types/components/MessageList.js +22 -13
  52. package/lib/types/components/ModelPicker.js +2 -2
  53. package/lib/types/components/PromptInput.d.ts +1 -1
  54. package/lib/types/components/PromptInput.d.ts.map +1 -1
  55. package/lib/types/components/PromptInput.js +83 -18
  56. package/lib/types/components/SkillsPicker.js +2 -2
  57. package/lib/types/components/SplitDiffView.d.ts +2 -17
  58. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  59. package/lib/types/components/SplitDiffView.js +9 -162
  60. package/lib/types/components/StreamingMarkdown.js +1 -1
  61. package/lib/types/components/SubagentCard.d.ts +9 -0
  62. package/lib/types/components/SubagentCard.d.ts.map +1 -0
  63. package/lib/types/components/SubagentCard.js +26 -0
  64. package/lib/types/components/SubagentDashboard.d.ts +13 -0
  65. package/lib/types/components/SubagentDashboard.d.ts.map +1 -0
  66. package/lib/types/components/SubagentDashboard.js +50 -0
  67. package/lib/types/components/SubagentDetailScene.d.ts +16 -0
  68. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -0
  69. package/lib/types/components/SubagentDetailScene.js +141 -0
  70. package/lib/types/components/SyntaxText.d.ts +15 -0
  71. package/lib/types/components/SyntaxText.d.ts.map +1 -0
  72. package/lib/types/components/SyntaxText.js +34 -0
  73. package/lib/types/components/ThinkingToggle.d.ts +3 -10
  74. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  75. package/lib/types/components/ThinkingToggle.js +4 -9
  76. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  77. package/lib/types/components/design-system/ListItem.js +1 -1
  78. package/lib/types/components/design-system/ThemedBox.d.ts.map +1 -1
  79. package/lib/types/components/design-system/ThemedBox.js +4 -1
  80. package/lib/types/components/design-system/ThemedText.js +2 -2
  81. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +12 -6
  82. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  83. package/lib/types/components/messages/AssistantThinkingMessage.js +37 -10
  84. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -0
  85. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  86. package/lib/types/components/messages/AssistantToolUseMessage.js +71 -18
  87. package/lib/types/components/messages/UserPromptMessage.d.ts +4 -6
  88. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  89. package/lib/types/components/messages/UserPromptMessage.js +19 -10
  90. package/lib/types/dsh-adapter/channel.d.ts +58 -2
  91. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  92. package/lib/types/dsh-adapter/channel.js +337 -7
  93. package/lib/types/dsh-adapter/contract.d.ts +27 -4
  94. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  95. package/lib/types/dsh-adapter/contract.js +56 -10
  96. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  97. package/lib/types/dsh-adapter/index.js +9 -3
  98. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  99. package/lib/types/dsh-adapter/plugin.js +38 -0
  100. package/lib/types/dsh-adapter/shortcuts.js +3 -3
  101. package/lib/types/dsh-adapter/subagents.d.ts +87 -0
  102. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -0
  103. package/lib/types/dsh-adapter/subagents.js +204 -0
  104. package/lib/types/herdr.d.ts +28 -0
  105. package/lib/types/herdr.d.ts.map +1 -0
  106. package/lib/types/herdr.js +133 -0
  107. package/lib/types/i18n.d.ts +215 -31
  108. package/lib/types/i18n.d.ts.map +1 -1
  109. package/lib/types/i18n.js +65 -14
  110. package/lib/types/ink/ink.d.ts +4 -0
  111. package/lib/types/ink/ink.d.ts.map +1 -1
  112. package/lib/types/ink/ink.js +46 -15
  113. package/lib/types/minimalMode.d.ts +13 -0
  114. package/lib/types/minimalMode.d.ts.map +1 -0
  115. package/lib/types/minimalMode.js +17 -0
  116. package/lib/types/screens/Chat.d.ts +1 -1
  117. package/lib/types/screens/Chat.d.ts.map +1 -1
  118. package/lib/types/screens/Chat.js +95 -45
  119. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  120. package/lib/types/screens/StatusLine.js +6 -2
  121. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
  122. package/lib/types/screens/TrajectoryScene.js +4 -2
  123. package/lib/types/theme.d.ts +20 -0
  124. package/lib/types/theme.d.ts.map +1 -1
  125. package/lib/types/theme.js +77 -23
  126. package/lib/types/tips.js +3 -3
  127. package/lib/types/trajectory/effortIgnition.d.ts +66 -0
  128. package/lib/types/trajectory/effortIgnition.d.ts.map +1 -0
  129. package/lib/types/trajectory/effortIgnition.js +142 -0
  130. package/lib/types/update.d.ts +18 -0
  131. package/lib/types/update.d.ts.map +1 -1
  132. package/lib/types/update.js +73 -2
  133. package/lib/types/utils/execFileNoThrow.d.ts +3 -20
  134. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  135. package/lib/types/utils/execFileNoThrow.js +53 -32
  136. package/lib/types/utils/externalEditor.d.ts +12 -11
  137. package/lib/types/utils/externalEditor.d.ts.map +1 -1
  138. package/lib/types/utils/externalEditor.js +11 -11
  139. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
  140. package/node_modules/@dsh-std/command/LICENSE +21 -21
  141. package/node_modules/@dsh-std/command/README.md +26 -26
  142. package/node_modules/@dsh-std/command/README.zh.md +28 -28
  143. package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
  144. package/node_modules/@dsh-std/command/package.json +22 -22
  145. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  146. package/node_modules/@dsh-std/connection/LICENSE +21 -21
  147. package/node_modules/@dsh-std/connection/README.md +42 -42
  148. package/node_modules/@dsh-std/connection/README.zh.md +42 -42
  149. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  150. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  151. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  152. package/node_modules/@dsh-std/connection/package.json +20 -20
  153. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  154. package/node_modules/@dsh-std/core/LICENSE +21 -21
  155. package/node_modules/@dsh-std/core/README.md +13 -13
  156. package/node_modules/@dsh-std/core/README.zh.md +13 -13
  157. package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  158. package/node_modules/@dsh-std/core/package.json +21 -21
  159. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  160. package/node_modules/@dsh-std/manifest/LICENSE +21 -21
  161. package/node_modules/@dsh-std/manifest/README.md +5 -5
  162. package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  163. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  164. package/node_modules/@dsh-std/manifest/package.json +20 -20
  165. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  166. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
  167. package/node_modules/@dsh-std/messages/LICENSE +21 -21
  168. package/node_modules/@dsh-std/messages/README.md +5 -5
  169. package/node_modules/@dsh-std/messages/README.zh.md +7 -7
  170. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
  171. package/node_modules/@dsh-std/messages/package.json +20 -20
  172. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
  173. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  174. package/node_modules/@dsh-std/presentation/LICENSE +21 -21
  175. package/node_modules/@dsh-std/presentation/README.md +27 -27
  176. package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  177. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  178. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  179. package/node_modules/@dsh-std/presentation/package.json +25 -25
  180. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
  181. package/node_modules/@dsh-std/storage/LICENSE +21 -21
  182. package/node_modules/@dsh-std/storage/README.md +5 -5
  183. package/node_modules/@dsh-std/storage/README.zh.md +7 -7
  184. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
  185. package/node_modules/@dsh-std/storage/package.json +20 -20
  186. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
  187. package/package.json +64 -58
  188. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  189. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
  190. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
  191. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
  192. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  193. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  194. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  195. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
  196. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  197. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
  198. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
  199. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
  200. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  201. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
  202. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  203. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
  204. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
  205. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  206. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  207. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
  208. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  209. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  210. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
  211. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
  212. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  213. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  214. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  215. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
  216. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  217. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
  218. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
  219. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
  220. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  221. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
  222. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  223. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
  224. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
  225. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
  226. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  227. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
  228. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  229. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
  230. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
  231. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
  232. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  233. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
  234. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  235. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
  236. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
  237. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
  238. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  239. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  240. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  241. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
  242. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  243. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
  244. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
  245. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
  246. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  247. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
  248. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  249. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
  250. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
  251. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
  252. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  253. 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
- return theme[color];
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 `∴ Thinking (ctrl+o to expand)`, expanded shows the
20
- * full reasoning text indented under `∴ Thinking…`, mirroring Claude Code's
21
- * `messages/AssistantThinkingMessage.tsx`. When the channel records the
22
- * reasoning duration, the label carries it (`∴ Thinking · 12s …`) — dsh-tui's
23
- * take on making thinking time visible in the transcript.
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;AAczB,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAA;IAChB;;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;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,SAAS,EACT,OAAO,EACP,OAAe,EACf,UAAU,EACV,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA2FzB"}
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 { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
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 `∴ Thinking (ctrl+o to expand)`, expanded shows the
15
- * full reasoning text indented under `∴ Thinking…`, mirroring Claude Code's
16
- * `messages/AssistantThinkingMessage.tsx`. When the channel records the
17
- * reasoning duration, the label carries it (`∴ Thinking · 12s …`) — dsh-tui's
18
- * take on making thinking time visible in the transcript.
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: [_jsxs(Text, { dimColor: true, italic: true, children: ["\u2234 ", t('thinking-label'), duration, "\u2026"] }), _jsx(Box, { flexDirection: "column", paddingLeft: 2, height: PREVIEW_ROWS, flexShrink: 0, overflow: "hidden", children: rows.map((line, i) => (_jsx(Text, { dimColor: true, italic: true, wrap: i === rows.length - 1 ? 'truncate-start' : 'truncate', children: i === 0 && clipped ? `…${line}` : line }, i))) })] }));
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: _jsxs(Text, { dimColor: true, italic: true, children: ["\u2234 ", t('thinking-label'), duration, " ", t('hint-expand-ctrl-o')] }) }));
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: [_jsxs(Text, { dimColor: true, italic: true, children: ["\u2234 ", t('thinking-label'), duration, "\u2026"] }), _jsx(Box, { paddingLeft: 2, children: _jsx(StreamingMarkdown, { dimColor: true, children: thinking }) })] }));
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;AAIzB,OAAO,KAAK,EAA8C,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAIvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,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;AAqND;;;;;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,CAgJzB"}
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(plain(diff.path));
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(dim);
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(dim);
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(dim(`${match.lineNumber}: ${match.line}`));
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 !== '' && (_jsx(Box, { flexWrap: "nowrap", children: _jsxs(Text, { children: ["(", clipHeaderArgs(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(dim);
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
- // Selection and per-row expansion remain higher-priority interaction
242
- // highlights; the configured treatment applies only to an ordinary card.
243
- backgroundColor: isSelected
244
- ? 'messageActionsBackground'
245
- : isExpanded
246
- ? 'userMessageBackgroundHover'
247
- : 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 }), !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, { dimColor: true, children: index === 0 ? GUTTER_FIRST : GUTTER_REST }) }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { color: line.tone === 'add'
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
- : undefined, dimColor: line.tone === 'dim', wrap: "wrap", children: 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 })] }))] }) }));
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` on the theme's userMessageBackground grey
14
- * (mirroring Claude Code's `messages/UserPromptMessage.tsx` +
15
- * `HighlightedThinkingText.tsx`, with the ultrathink rainbow removed).
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, isExpanded, onClick, }: Props): React.ReactNode;
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;AAIzB,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAA;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,sEAAsE;IACtE,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,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAqBzB"}
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` on the theme's userMessageBackground grey
6
- * (mirroring Claude Code's `messages/UserPromptMessage.tsx` +
7
- * `HighlightedThinkingText.tsx`, with the ultrathink rainbow removed).
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, isExpanded = false, onClick, }) {
10
- return (_jsx(Box, { flexDirection: "column", marginTop: addMargin ? 1 : 0, backgroundColor: isSelected
11
- ? 'messageActionsBackground'
12
- : isExpanded
13
- ? 'userMessageBackgroundHover'
14
- : 'userMessageBackground', paddingRight: 1, onClick: onClick, children: _jsxs(Text, { children: [_jsxs(Text, { color: "subtle", children: [POINTER, " "] }), _jsx(Text, { color: "text", children: text })] }) }));
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