@deepseek-harness-tui/dsh-tui 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/README.md +55 -20
  2. package/assets/whale-girl/whale-girl-dark.png +0 -0
  3. package/assets/whale-girl/whale-girl-happy.png +0 -0
  4. package/assets/whale-girl/whale-girl.png +0 -0
  5. package/bin/dsh-tui.js +63 -3
  6. package/cordis.patch.yml +43 -20
  7. package/cordis.yml +6 -4
  8. package/lib/settings.json +1272 -0
  9. package/lib/types/activityPrefs.d.ts +24 -0
  10. package/lib/types/activityPrefs.d.ts.map +1 -1
  11. package/lib/types/activityPrefs.js +50 -1
  12. package/lib/types/adapter/channel/state.d.ts.map +1 -1
  13. package/lib/types/adapter/channel/state.js +3 -1
  14. package/lib/types/adapter/channel/ui-policy.d.ts +9 -2
  15. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  16. package/lib/types/adapter/channel/ui-policy.js +14 -1
  17. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  18. package/lib/types/adapter/kernel/replay.js +2 -0
  19. package/lib/types/adapter/ports/channel-display.d.ts +12 -0
  20. package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
  21. package/lib/types/adapter/ports/channel-session.d.ts +38 -0
  22. package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
  23. package/lib/types/adapter/ports/channel-settings.d.ts +12 -0
  24. package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
  25. package/lib/types/adapter/ports/channel-ui.d.ts +53 -7
  26. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  27. package/lib/types/adapter/ports/channel-view.d.ts +43 -12
  28. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  29. package/lib/types/adapter/ports/channel.d.ts +4 -1
  30. package/lib/types/adapter/ports/channel.d.ts.map +1 -1
  31. package/lib/types/commands.d.ts.map +1 -1
  32. package/lib/types/commands.js +2 -0
  33. package/lib/types/components/ActivityLine.d.ts +7 -2
  34. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  35. package/lib/types/components/ActivityLine.js +0 -8
  36. package/lib/types/components/BalanceReportRow.d.ts +10 -2
  37. package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
  38. package/lib/types/components/BalanceReportRow.js +18 -4
  39. package/lib/types/components/CompactionStatusRow.d.ts +24 -0
  40. package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
  41. package/lib/types/components/CompactionStatusRow.js +72 -0
  42. package/lib/types/components/GoalTodoPanel.js +2 -2
  43. package/lib/types/components/HelpMenu.d.ts +2 -2
  44. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  45. package/lib/types/components/HelpMenu.js +5 -4
  46. package/lib/types/components/InlineMathParagraph.d.ts +22 -0
  47. package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
  48. package/lib/types/components/InlineMathParagraph.js +178 -0
  49. package/lib/types/components/LogoV2.d.ts +41 -3
  50. package/lib/types/components/LogoV2.d.ts.map +1 -1
  51. package/lib/types/components/LogoV2.js +148 -24
  52. package/lib/types/components/Markdown.d.ts +10 -3
  53. package/lib/types/components/Markdown.d.ts.map +1 -1
  54. package/lib/types/components/Markdown.js +47 -14
  55. package/lib/types/components/MathBlock.d.ts +13 -0
  56. package/lib/types/components/MathBlock.d.ts.map +1 -0
  57. package/lib/types/components/MathBlock.js +136 -0
  58. package/lib/types/components/MessageList.d.ts +10 -1
  59. package/lib/types/components/MessageList.d.ts.map +1 -1
  60. package/lib/types/components/MessageList.js +15 -5
  61. package/lib/types/components/MigratePicker.d.ts +30 -0
  62. package/lib/types/components/MigratePicker.d.ts.map +1 -0
  63. package/lib/types/components/MigratePicker.js +38 -0
  64. package/lib/types/components/PromptInput.d.ts +17 -0
  65. package/lib/types/components/PromptInput.d.ts.map +1 -1
  66. package/lib/types/components/PromptInput.js +96 -9
  67. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  68. package/lib/types/components/SplitDiffView.js +3 -1
  69. package/lib/types/components/StarPrompt.d.ts +53 -0
  70. package/lib/types/components/StarPrompt.d.ts.map +1 -0
  71. package/lib/types/components/StarPrompt.js +281 -0
  72. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  73. package/lib/types/components/StreamingMarkdown.js +20 -3
  74. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  75. package/lib/types/components/SubagentCard.js +12 -6
  76. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
  77. package/lib/types/components/SubagentDetailScene.js +8 -3
  78. package/lib/types/components/TimelineRail.d.ts.map +1 -1
  79. package/lib/types/components/TimelineRail.js +9 -1
  80. package/lib/types/components/Whale.d.ts +17 -8
  81. package/lib/types/components/Whale.d.ts.map +1 -1
  82. package/lib/types/components/Whale.js +25 -15
  83. package/lib/types/components/WhaleGirl.d.ts +29 -0
  84. package/lib/types/components/WhaleGirl.d.ts.map +1 -0
  85. package/lib/types/components/WhaleGirl.js +32 -0
  86. package/lib/types/components/WorkingSpinner.d.ts +4 -1
  87. package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
  88. package/lib/types/components/WorkingSpinner.js +2 -2
  89. package/lib/types/components/bigfont.d.ts +47 -18
  90. package/lib/types/components/bigfont.d.ts.map +1 -1
  91. package/lib/types/components/bigfont.js +55 -40
  92. package/lib/types/components/design-system/HintLine.d.ts +1 -2
  93. package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
  94. package/lib/types/components/design-system/HintLine.js +1 -2
  95. package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
  96. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  97. package/lib/types/components/design-system/ThemeProvider.js +40 -1
  98. package/lib/types/components/maidPortrait.d.ts +44 -0
  99. package/lib/types/components/maidPortrait.d.ts.map +1 -0
  100. package/lib/types/components/maidPortrait.js +178 -0
  101. package/lib/types/components/mathPreview.d.ts +25 -0
  102. package/lib/types/components/mathPreview.d.ts.map +1 -0
  103. package/lib/types/components/mathPreview.js +48 -0
  104. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
  105. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  106. package/lib/types/components/messages/AssistantThinkingMessage.js +4 -2
  107. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
  108. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  109. package/lib/types/components/messages/AssistantToolUseMessage.js +31 -26
  110. package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
  111. package/lib/types/components/messages/TranscriptImages.js +11 -1
  112. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
  113. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  114. package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
  115. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  116. package/lib/types/components/questions/PlanReviewPanel.js +3 -3
  117. package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
  118. package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
  119. package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
  120. package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
  121. package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
  122. package/lib/types/components/sessions/SourceTabs.js +70 -0
  123. package/lib/types/components/splashEggs.d.ts +56 -0
  124. package/lib/types/components/splashEggs.d.ts.map +1 -0
  125. package/lib/types/components/splashEggs.js +67 -0
  126. package/lib/types/components/splashFonts.d.ts +119 -0
  127. package/lib/types/components/splashFonts.d.ts.map +1 -0
  128. package/lib/types/components/splashFonts.js +267 -0
  129. package/lib/types/components/splashLayout.d.ts +41 -0
  130. package/lib/types/components/splashLayout.d.ts.map +1 -0
  131. package/lib/types/components/splashLayout.js +40 -0
  132. package/lib/types/components/whaleGirlSprite.d.ts +17 -0
  133. package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
  134. package/lib/types/components/whaleGirlSprite.js +47 -0
  135. package/lib/types/deepseekPricing.d.ts +74 -0
  136. package/lib/types/deepseekPricing.d.ts.map +1 -1
  137. package/lib/types/deepseekPricing.js +110 -11
  138. package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
  139. package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
  140. package/lib/types/dsh-adapter/activity-store.js +359 -0
  141. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  142. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  143. package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
  144. package/lib/types/dsh-adapter/channel/background-action.d.ts +2 -1
  145. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  146. package/lib/types/dsh-adapter/channel/background-action.js +2 -0
  147. package/lib/types/dsh-adapter/channel/binding-events.d.ts +15 -14
  148. package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
  149. package/lib/types/dsh-adapter/channel/binding-events.js +70 -21
  150. package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -2
  151. package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
  152. package/lib/types/dsh-adapter/channel/compaction.js +35 -4
  153. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  154. package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
  155. package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
  156. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  157. package/lib/types/dsh-adapter/channel/model-switch.js +6 -2
  158. package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
  159. package/lib/types/dsh-adapter/channel/paths.js +7 -1
  160. package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
  161. package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
  162. package/lib/types/dsh-adapter/channel/preferences.js +16 -0
  163. package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
  164. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/channel/projection.js +127 -17
  166. package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
  167. package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
  168. package/lib/types/dsh-adapter/channel/question-record.js +107 -0
  169. package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
  170. package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
  171. package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
  172. package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
  173. package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
  174. package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
  175. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +3 -1
  176. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  177. package/lib/types/dsh-adapter/channel/session-live-adoption.js +10 -3
  178. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
  179. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  180. package/lib/types/dsh-adapter/channel/session-metadata.js +43 -9
  181. package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
  182. package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
  183. package/lib/types/dsh-adapter/channel/session-reset.js +7 -1
  184. package/lib/types/dsh-adapter/channel/session-resume.d.ts +2 -1
  185. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  186. package/lib/types/dsh-adapter/channel/session-resume.js +5 -2
  187. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  188. package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
  189. package/lib/types/dsh-adapter/channel/state.d.ts +19 -1
  190. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  191. package/lib/types/dsh-adapter/channel/state.js +8 -3
  192. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +32 -17
  193. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
  194. package/lib/types/dsh-adapter/channel/subagent-projection.js +309 -8
  195. package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
  196. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  197. package/lib/types/dsh-adapter/channel.d.ts +1 -1
  198. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  199. package/lib/types/dsh-adapter/channel.js +34 -18
  200. package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
  201. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
  202. package/lib/types/dsh-adapter/compat/index.js +1 -1
  203. package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
  204. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
  205. package/lib/types/dsh-adapter/compat/messages.js +9 -0
  206. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
  207. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
  208. package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
  209. package/lib/types/dsh-adapter/compat/settings.d.ts +2 -0
  210. package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -1
  211. package/lib/types/dsh-adapter/compat/settings.js +14 -0
  212. package/lib/types/dsh-adapter/contract.d.ts +5 -4
  213. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  214. package/lib/types/dsh-adapter/contract.js +9 -5
  215. package/lib/types/dsh-adapter/index.d.ts +36 -1
  216. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  217. package/lib/types/dsh-adapter/index.js +22 -6
  218. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
  219. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
  220. package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
  221. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
  222. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
  223. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
  224. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
  225. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
  226. package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
  227. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
  228. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
  229. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
  230. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
  231. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
  232. package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
  233. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
  234. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
  235. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
  236. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
  237. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
  238. package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
  239. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
  240. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
  241. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
  242. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
  243. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
  244. package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
  245. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
  246. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
  247. package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
  248. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
  249. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
  250. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
  251. package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
  252. package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
  253. package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
  254. package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
  255. package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
  256. package/lib/types/dsh-adapter/migrate/browse.js +90 -0
  257. package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
  258. package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
  259. package/lib/types/dsh-adapter/migrate/cli.js +106 -0
  260. package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
  261. package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
  262. package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
  263. package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
  264. package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
  265. package/lib/types/dsh-adapter/migrate/index.js +107 -0
  266. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
  267. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
  268. package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
  269. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
  270. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
  271. package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
  272. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
  273. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
  274. package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
  275. package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
  276. package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
  277. package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
  278. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
  279. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
  280. package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
  281. package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
  282. package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
  283. package/lib/types/dsh-adapter/migrate/picker.js +86 -0
  284. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
  285. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
  286. package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
  287. package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
  288. package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
  289. package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
  290. package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
  291. package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
  292. package/lib/types/dsh-adapter/migrate/types.js +11 -0
  293. package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
  294. package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
  295. package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
  296. package/lib/types/dsh-adapter/plugin.d.ts +5 -3
  297. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  298. package/lib/types/dsh-adapter/plugin.js +168 -372
  299. package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
  300. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  301. package/lib/types/dsh-adapter/providerWizard.js +254 -66
  302. package/lib/types/dsh-adapter/questions.d.ts +22 -15
  303. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  304. package/lib/types/dsh-adapter/questions.js +47 -45
  305. package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
  306. package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
  307. package/lib/types/dsh-adapter/sessions/digest.js +20 -13
  308. package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
  309. package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
  310. package/lib/types/dsh-adapter/sessions/frames.js +5 -4
  311. package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
  312. package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
  313. package/lib/types/dsh-adapter/sessions/list.js +188 -164
  314. package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
  315. package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
  316. package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
  317. package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
  318. package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
  319. package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
  320. package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
  321. package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
  322. package/lib/types/dsh-adapter/sessions/store.js +62 -25
  323. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  324. package/lib/types/dsh-adapter/settings-sections.js +7 -4
  325. package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
  326. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
  327. package/lib/types/dsh-adapter/sideQuestion.js +98 -2
  328. package/lib/types/dsh-adapter/subagents.d.ts +44 -6
  329. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  330. package/lib/types/dsh-adapter/subagents.js +163 -26
  331. package/lib/types/herdr.d.ts +2 -0
  332. package/lib/types/herdr.d.ts.map +1 -1
  333. package/lib/types/herdr.js +9 -3
  334. package/lib/types/history.d.ts +13 -1
  335. package/lib/types/history.d.ts.map +1 -1
  336. package/lib/types/history.js +15 -2
  337. package/lib/types/i18n.d.ts +512 -41
  338. package/lib/types/i18n.d.ts.map +1 -1
  339. package/lib/types/i18n.js +199 -20
  340. package/lib/types/ink/components/App.d.ts +2 -2
  341. package/lib/types/ink/components/App.d.ts.map +1 -1
  342. package/lib/types/ink/components/App.js +5 -1
  343. package/lib/types/ink/components/Image.d.ts +14 -1
  344. package/lib/types/ink/components/Image.d.ts.map +1 -1
  345. package/lib/types/ink/components/Image.js +2 -2
  346. package/lib/types/ink/events/input-event.js +3 -3
  347. package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
  348. package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
  349. package/lib/types/ink/hooks/use-terminal-images.js +13 -0
  350. package/lib/types/ink/ink.d.ts +6 -0
  351. package/lib/types/ink/ink.d.ts.map +1 -1
  352. package/lib/types/ink/ink.js +16 -1
  353. package/lib/types/ink/kitty-graphics.d.ts +44 -3
  354. package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
  355. package/lib/types/ink/kitty-graphics.js +184 -23
  356. package/lib/types/ink/log-update.d.ts.map +1 -1
  357. package/lib/types/ink/log-update.js +19 -1
  358. package/lib/types/ink/output.d.ts +24 -2
  359. package/lib/types/ink/output.d.ts.map +1 -1
  360. package/lib/types/ink/output.js +83 -5
  361. package/lib/types/ink/parse-keypress.d.ts +26 -1
  362. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  363. package/lib/types/ink/parse-keypress.js +156 -13
  364. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  365. package/lib/types/ink/render-node-to-output.js +8 -1
  366. package/lib/types/ink/screen.d.ts +24 -0
  367. package/lib/types/ink/screen.d.ts.map +1 -1
  368. package/lib/types/ink/screen.js +89 -0
  369. package/lib/types/ink/selection.d.ts +68 -18
  370. package/lib/types/ink/selection.d.ts.map +1 -1
  371. package/lib/types/ink/selection.js +178 -31
  372. package/lib/types/ink/sixel-codec.d.ts +12 -1
  373. package/lib/types/ink/sixel-codec.d.ts.map +1 -1
  374. package/lib/types/ink/sixel-codec.js +29 -5
  375. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  376. package/lib/types/ink/sixel-graphics.js +5 -3
  377. package/lib/types/ink/styles.d.ts +9 -0
  378. package/lib/types/ink/styles.d.ts.map +1 -1
  379. package/lib/types/ink/terminal-image.d.ts +8 -0
  380. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  381. package/lib/types/ink/terminal-querier.d.ts +7 -1
  382. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  383. package/lib/types/ink/terminal-querier.js +12 -2
  384. package/lib/types/ink/timeline-rail.d.ts +5 -0
  385. package/lib/types/ink/timeline-rail.d.ts.map +1 -1
  386. package/lib/types/math/inline-layout.d.ts +29 -0
  387. package/lib/types/math/inline-layout.d.ts.map +1 -0
  388. package/lib/types/math/inline-layout.js +106 -0
  389. package/lib/types/math/layout.d.ts +58 -0
  390. package/lib/types/math/layout.d.ts.map +1 -0
  391. package/lib/types/math/layout.js +59 -0
  392. package/lib/types/math/renderer.d.ts +64 -0
  393. package/lib/types/math/renderer.d.ts.map +1 -0
  394. package/lib/types/math/renderer.js +256 -0
  395. package/lib/types/screens/Chat.d.ts +17 -1
  396. package/lib/types/screens/Chat.d.ts.map +1 -1
  397. package/lib/types/screens/Chat.js +618 -57
  398. package/lib/types/screens/SessionSupervisor.d.ts +2 -1
  399. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
  400. package/lib/types/screens/SessionSupervisor.js +156 -19
  401. package/lib/types/screens/Settings.d.ts.map +1 -1
  402. package/lib/types/screens/Settings.js +49 -11
  403. package/lib/types/screens/StatusLine.d.ts +5 -1
  404. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  405. package/lib/types/screens/StatusLine.js +47 -17
  406. package/lib/types/screens/chatOverlay.d.ts +5 -0
  407. package/lib/types/screens/chatOverlay.d.ts.map +1 -1
  408. package/lib/types/screens/chatOverlay.js +1 -0
  409. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
  410. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
  411. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
  412. package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
  413. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
  414. package/lib/types/screens/sessionSupervisor/model.js +26 -0
  415. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
  416. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
  417. package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
  418. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
  419. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
  420. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
  421. package/lib/types/sessionHistory.d.ts +2 -2
  422. package/lib/types/sessionHistory.d.ts.map +1 -1
  423. package/lib/types/sessionHistory.js +31 -5
  424. package/lib/types/settings/definitions.d.ts +681 -0
  425. package/lib/types/settings/definitions.d.ts.map +1 -0
  426. package/lib/types/settings/definitions.js +511 -0
  427. package/lib/types/starAction.d.ts +44 -0
  428. package/lib/types/starAction.d.ts.map +1 -0
  429. package/lib/types/starAction.js +52 -0
  430. package/lib/types/terminal-utils/latex.d.ts +10 -0
  431. package/lib/types/terminal-utils/latex.d.ts.map +1 -0
  432. package/lib/types/terminal-utils/latex.js +1417 -0
  433. package/lib/types/terminal-utils/markdown.d.ts +3 -1
  434. package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
  435. package/lib/types/terminal-utils/markdown.js +26 -1
  436. package/lib/types/terminal-utils/math.d.ts +66 -0
  437. package/lib/types/terminal-utils/math.d.ts.map +1 -0
  438. package/lib/types/terminal-utils/math.js +337 -0
  439. package/lib/types/tips.d.ts.map +1 -1
  440. package/lib/types/tips.js +6 -0
  441. package/lib/types/tuiDisplayPrefs.d.ts +67 -0
  442. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  443. package/lib/types/tuiDisplayPrefs.js +59 -0
  444. package/lib/types/ui.d.ts +1 -1
  445. package/lib/types/ui.d.ts.map +1 -1
  446. package/lib/types/ui.js +1 -1
  447. package/lib/types/usageStats.d.ts +98 -0
  448. package/lib/types/usageStats.d.ts.map +1 -0
  449. package/lib/types/usageStats.js +169 -0
  450. package/lib/types/utils/bmp.d.ts +17 -0
  451. package/lib/types/utils/bmp.d.ts.map +1 -0
  452. package/lib/types/utils/bmp.js +154 -0
  453. package/lib/types/utils/clipboard.d.ts +14 -2
  454. package/lib/types/utils/clipboard.d.ts.map +1 -1
  455. package/lib/types/utils/clipboard.js +143 -8
  456. package/lib/types/utils/fold-long-lines.d.ts +1 -1
  457. package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
  458. package/lib/types/utils/fold-long-lines.js +3 -2
  459. package/lib/types/utils/keymap.d.ts +4 -1
  460. package/lib/types/utils/keymap.d.ts.map +1 -1
  461. package/lib/types/utils/keymap.js +8 -0
  462. package/lib/types/utils/modifiers.d.ts +4 -3
  463. package/lib/types/utils/modifiers.d.ts.map +1 -1
  464. package/lib/types/utils/modifiers.js +4 -3
  465. package/lib/types/working-activity.d.ts +10 -9
  466. package/lib/types/working-activity.d.ts.map +1 -1
  467. package/lib/types/working-activity.js +17 -10
  468. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
  469. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
  470. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
  471. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
  472. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
  473. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
  474. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
  475. package/package.json +117 -99
  476. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
  477. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
  478. package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
  479. package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
  480. package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
  481. package/lib/types/dsh-adapter/channel/activity.js +0 -113
  482. package/lib/types/terminal-utils/terminal.d.ts +0 -18
  483. package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
  484. package/lib/types/terminal-utils/terminal.js +0 -96
@@ -46,6 +46,7 @@ const ThemeContext = createContext({
46
46
  theme: 'dark',
47
47
  autoBase: 'dark',
48
48
  setTheme: () => false,
49
+ terminalBackground: '#000000',
49
50
  });
50
51
  /**
51
52
  * DSH_TUI_THEME skips terminal detection (tests, debugging). Accepts a
@@ -225,7 +226,17 @@ export function ThemeProvider({ children, theme, themeHost, }) {
225
226
  : isThemeAvailable(active)
226
227
  ? active
227
228
  : AUTO_THEME_NAME;
228
- const value = React.useMemo(() => ({ theme: renderedTheme, autoBase, setTheme }), [renderedTheme, autoBase, setTheme]);
229
+ const value = React.useMemo(() => ({
230
+ theme: renderedTheme,
231
+ autoBase,
232
+ setTheme,
233
+ // 与下面 setShadeTarget 用同一个口径(OSC 11 的回答,缺失时按明暗取
234
+ // 白/黑)——terminal 图像的不透明衬底就合成到这个颜色上。
235
+ // 只在与主题明暗**一致**时才采信 OSC 11 的回答:透明背景/背景图形态
236
+ // 的终端会报一个跟画面对不上的颜色,那时宁可用纯白(浅色主题)或
237
+ // 纯黑(深色主题)——深色终端上糊一块白底最突兀。
238
+ terminalBackground: hexRgb(imageBackingColor(detectedBackground, renderedTheme)),
239
+ }), [renderedTheme, autoBase, setTheme, detectedBackground]);
229
240
  useEffect(() => {
230
241
  if (active !== null)
231
242
  setActiveThemeName(renderedTheme);
@@ -254,3 +265,31 @@ export function useTheme() {
254
265
  const { theme, setTheme } = useContext(ThemeContext);
255
266
  return [theme, setTheme];
256
267
  }
268
+ /** `{r,g,b}` → `#rrggbb` for colour strings the style layer accepts. */
269
+ function hexRgb(color) {
270
+ const part = (value) => Math.max(0, Math.min(255, Math.round(value))).toString(16).padStart(2, '0');
271
+ return `#${part(color.r)}${part(color.g)}${part(color.b)}`;
272
+ }
273
+ /**
274
+ * The opaque colour terminal images composite onto: the OSC 11 answer while
275
+ * it agrees with the rendered palette's lightness, else pure white (light
276
+ * palette) / pure black (dark palette). A light terminal must never get a
277
+ * dark slab, and a dark terminal must never get a white one.
278
+ */
279
+ function imageBackingColor(detected, themeName) {
280
+ const light = isLightThemeActive(themeName);
281
+ const fallback = light ? { r: 255, g: 255, b: 255 } : { r: 0, g: 0, b: 0 };
282
+ if (detected === null)
283
+ return fallback;
284
+ // Rec. 601 luma: > 0.5 counts as a light background.
285
+ const luma = (0.299 * detected.r + 0.587 * detected.g + 0.114 * detected.b) / 255;
286
+ return (luma > 0.5) === light ? detected : fallback;
287
+ }
288
+ /**
289
+ * The colour the terminal shows behind the UI (`#rrggbb`): the OSC 11
290
+ * answer when available, else white/black by palette lightness. Terminal
291
+ * image placements use it as their opaque Sixel backing.
292
+ */
293
+ export function useTerminalBackground() {
294
+ return useContext(ThemeContext).terminalBackground;
295
+ }
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import type { TerminalImageSource } from '../ink/terminal-image.js';
3
+ /** 一台机器上的两张立绘都解好、并补齐到**同一像素画布**上——几何完全一致,
4
+ * 换图时宿主是「擦旧 + 画新」一次写入,不会留残影。 */
5
+ export interface MaidPortraits {
6
+ readonly normal: TerminalImageSource;
7
+ readonly happy: TerminalImageSource;
8
+ }
9
+ /**
10
+ * 解码两张立绘一次(进程内缓存;失败缓存成 `undefined`,坏安装不会每次
11
+ * 渲染都重试)。两张都裁掉透明边后**居中补到同一张透明画布**(取两者
12
+ * 较大的宽高)——所以它们的像素尺寸与单元格盒完全一致。
13
+ * @returns 两张 RGBA 源;任一张缺失/解码失败时整体 `undefined`。
14
+ */
15
+ export declare function loadMaidPortraits(): Promise<MaidPortraits | undefined>;
16
+ /**
17
+ * 两张立绘,终端图像能力确认后解码(一次把两张都备好,点击换图不等待)。
18
+ * @param enabled - `useTerminalImages()` 的结果;为假时根本不解码。
19
+ * @returns 两张 RGBA 源;未就绪/不可用时为 `undefined`。
20
+ */
21
+ export declare function useMaidPortraits(enabled: boolean): MaidPortraits | undefined;
22
+ /**
23
+ * The portrait's center column inside the whale's 40-column slot: the
24
+ * aspect-fit image spans columns 5..34 (center 19.5). The welcome tagline
25
+ * centers on this instead of `WHALE_CENTER` while the portrait shows.
26
+ */
27
+ export declare const MAID_BOX_CENTER = 19.5;
28
+ /**
29
+ * The portrait as an Ink component: a `width × height` cell box (aspect-fit
30
+ * from the real cell metrics so pixels stay square), centered horizontally
31
+ * by the caller's slot. `presentation` follows the surface — `'transcript'`
32
+ * opts into Sixel for the scrollable header, `'preview'` for modal cards —
33
+ * and the portrait always floats `transparent`: her trimmed silhouette sits
34
+ * on whatever the terminal shows, with no backing rectangle behind it.
35
+ */
36
+ export declare function MaidPortrait({ source, maxColumns, maxRows, presentation, }: {
37
+ /** Decoded RGBA snapshot; `undefined` keeps the caller's fallback. */
38
+ readonly source?: TerminalImageSource;
39
+ /** Cell budget (the header passes the whale's 40-column slot). */
40
+ readonly maxColumns: number;
41
+ readonly maxRows: number;
42
+ readonly presentation: 'transcript' | 'preview';
43
+ }): React.ReactNode;
44
+ //# sourceMappingURL=maidPortrait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maidPortrait.d.ts","sourceRoot":"","sources":["../../../src/components/maidPortrait.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAuBnE;iCACiC;AACjC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAA;CACpC;AASD;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CA+BtE;AAsDD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAW5E;AAKD;;;;GAIG;AACH,eAAO,MAAM,eAAe,OAAO,CAAA;AAEnC;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,UAAU,EACV,OAAO,EACP,YAAY,GACb,EAAE;IACD,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAA;IACrC,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,SAAS,CAAA;CAChD,GAAG,KAAK,CAAC,SAAS,CAuBlB"}
@@ -0,0 +1,178 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Image, useTerminalImageCellSize } from '../ui.js';
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { DEFAULT_TERMINAL_CELL_SIZE } from '../ink/terminal-image.js';
7
+ import { loadSharp } from '../dsh-adapter/sharp.js';
8
+ /**
9
+ * The maid portrait (鲸鱼娘) for `dsh-tui.whaleGirl` and the star modal —
10
+ * the author-designed 464×464 pixel art shipped at `assets/whale-girl/`,
11
+ * rendered FIRST as a real raster through the terminal image protocols
12
+ * (Kitty graphics / Sixel): full fidelity, anti-aliased curves, the whole
13
+ * palette. The chain degrades per surface when images cannot show — the
14
+ * header falls back to the character-art maid (`WhaleGirl.tsx`, the
15
+ * author's placeholder), the star modal to the animated pixel whale — so
16
+ * the setting never leaves the header worse than the whale it replaces.
17
+ */
18
+ /** 两张立绘:`normal` 是安静版,`happy` 是「高兴鲸娘」(点击她 / star 成功
19
+ * 时替换)。资产候选同时覆盖两种目录深度:`lib/types/components`(发布形态)
20
+ * 比 `src/components`(仓库形态)深一层。 */
21
+ const ASSET_FILES = {
22
+ normal: 'whale-girl.png',
23
+ happy: 'whale-girl-happy.png',
24
+ };
25
+ const assetPath = (file) => [`../../../assets/whale-girl/${file}`, `../../assets/whale-girl/${file}`]
26
+ .map(relative => fileURLToPath(new URL(relative, import.meta.url)))
27
+ .find(candidate => existsSync(candidate));
28
+ let loadOnce;
29
+ /**
30
+ * 解码两张立绘一次(进程内缓存;失败缓存成 `undefined`,坏安装不会每次
31
+ * 渲染都重试)。两张都裁掉透明边后**居中补到同一张透明画布**(取两者
32
+ * 较大的宽高)——所以它们的像素尺寸与单元格盒完全一致。
33
+ * @returns 两张 RGBA 源;任一张缺失/解码失败时整体 `undefined`。
34
+ */
35
+ export function loadMaidPortraits() {
36
+ loadOnce ??= (async () => {
37
+ try {
38
+ const sharp = await loadSharp();
39
+ if (sharp === undefined)
40
+ return undefined;
41
+ const trimmed = { normal: undefined, happy: undefined };
42
+ for (const variant of ['normal', 'happy']) {
43
+ const path = assetPath(ASSET_FILES[variant]);
44
+ if (path === undefined)
45
+ return undefined;
46
+ const decoded = await sharp(readFileSync(path), { failOn: 'error' })
47
+ .toColourspace('srgb')
48
+ .ensureAlpha()
49
+ .raw()
50
+ .toBuffer({ resolveWithObject: true });
51
+ if (decoded.info.channels !== 4
52
+ || decoded.data.byteLength !== decoded.info.width * decoded.info.height * 4)
53
+ return undefined;
54
+ const rgba = {
55
+ data: new Uint8Array(decoded.data.buffer, decoded.data.byteOffset, decoded.data.byteLength),
56
+ width: decoded.info.width,
57
+ height: decoded.info.height,
58
+ };
59
+ trimmed[variant] = trimTransparent(rgba);
60
+ }
61
+ const width = Math.max(trimmed.normal.width, trimmed.happy.width);
62
+ const height = Math.max(trimmed.normal.height, trimmed.happy.height);
63
+ return { normal: centerOnCanvas(trimmed.normal, width, height), happy: centerOnCanvas(trimmed.happy, width, height) };
64
+ }
65
+ catch {
66
+ return undefined;
67
+ }
68
+ })();
69
+ return loadOnce;
70
+ }
71
+ /** 把一张已裁边的图居中放进 `width × height` 的透明画布(几何对齐用)。 */
72
+ function centerOnCanvas(source, width, height) {
73
+ if (source.width === width && source.height === height)
74
+ return source;
75
+ const data = new Uint8Array(width * height * 4);
76
+ const left = Math.floor((width - source.width) / 2);
77
+ const top = Math.floor((height - source.height) / 2);
78
+ for (let y = 0; y < source.height; y++) {
79
+ const from = y * source.width * 4;
80
+ data.set(source.data.subarray(from, from + source.width * 4), ((top + y) * width + left) * 4);
81
+ }
82
+ return { data, width, height };
83
+ }
84
+ /**
85
+ * Trim fully-transparent borders (the art's canvas margins) with a small
86
+ * transparent pad. Sixel cannot express partial alpha, so the pad is dropped
87
+ * by the coverage mask at encode time; trimming first hands the terminal the
88
+ * artwork itself and lets the same cell box draw her larger.
89
+ */
90
+ function trimTransparent(source, pad = 4) {
91
+ const { data, width, height } = source;
92
+ let minX = width;
93
+ let minY = height;
94
+ let maxX = -1;
95
+ let maxY = -1;
96
+ for (let y = 0; y < height; y++) {
97
+ for (let x = 0; x < width; x++) {
98
+ // Anti-aliased edges carry alpha > 0, so only truly empty pixels fall
99
+ // outside the bounding box.
100
+ if (data[(y * width + x) * 4 + 3] === 0)
101
+ continue;
102
+ if (x < minX)
103
+ minX = x;
104
+ if (x > maxX)
105
+ maxX = x;
106
+ if (y < minY)
107
+ minY = y;
108
+ if (y > maxY)
109
+ maxY = y;
110
+ }
111
+ }
112
+ if (maxX < minX || maxY < minY)
113
+ return source;
114
+ const left = Math.max(0, minX - pad);
115
+ const top = Math.max(0, minY - pad);
116
+ const right = Math.min(width - 1, maxX + pad);
117
+ const bottom = Math.min(height - 1, maxY + pad);
118
+ const cropWidth = right - left + 1;
119
+ const cropHeight = bottom - top + 1;
120
+ if (cropWidth === width && cropHeight === height)
121
+ return source;
122
+ const cropped = new Uint8Array(cropWidth * cropHeight * 4);
123
+ for (let y = 0; y < cropHeight; y++) {
124
+ const from = ((top + y) * width + left) * 4;
125
+ cropped.set(data.subarray(from, from + cropWidth * 4), y * cropWidth * 4);
126
+ }
127
+ return { data: cropped, width: cropWidth, height: cropHeight };
128
+ }
129
+ /**
130
+ * 两张立绘,终端图像能力确认后解码(一次把两张都备好,点击换图不等待)。
131
+ * @param enabled - `useTerminalImages()` 的结果;为假时根本不解码。
132
+ * @returns 两张 RGBA 源;未就绪/不可用时为 `undefined`。
133
+ */
134
+ export function useMaidPortraits(enabled) {
135
+ const [sources, setSources] = React.useState(undefined);
136
+ React.useEffect(() => {
137
+ if (!enabled)
138
+ return;
139
+ let live = true;
140
+ void loadMaidPortraits().then(next => {
141
+ if (live && next !== undefined)
142
+ setSources(next);
143
+ });
144
+ return () => { live = false; };
145
+ }, [enabled]);
146
+ return enabled ? sources : undefined;
147
+ }
148
+ /** Fallback aspect before the source lands (square canvas). */
149
+ const MAID_RATIO = 1;
150
+ /**
151
+ * The portrait's center column inside the whale's 40-column slot: the
152
+ * aspect-fit image spans columns 5..34 (center 19.5). The welcome tagline
153
+ * centers on this instead of `WHALE_CENTER` while the portrait shows.
154
+ */
155
+ export const MAID_BOX_CENTER = 19.5;
156
+ /**
157
+ * The portrait as an Ink component: a `width × height` cell box (aspect-fit
158
+ * from the real cell metrics so pixels stay square), centered horizontally
159
+ * by the caller's slot. `presentation` follows the surface — `'transcript'`
160
+ * opts into Sixel for the scrollable header, `'preview'` for modal cards —
161
+ * and the portrait always floats `transparent`: her trimmed silhouette sits
162
+ * on whatever the terminal shows, with no backing rectangle behind it.
163
+ */
164
+ export function MaidPortrait({ source, maxColumns, maxRows, presentation, }) {
165
+ const cell = useTerminalImageCellSize() ?? DEFAULT_TERMINAL_CELL_SIZE;
166
+ const cellRatio = cell.height / cell.width;
167
+ // Fit the TRIMMED artwork's own aspect, not the source canvas: the raster
168
+ // is her bounding box, so she fills the slot instead of floating in
169
+ // transparent padding.
170
+ const ratio = source !== undefined && source.height > 0 ? source.width / source.height : MAID_RATIO;
171
+ let width = maxColumns;
172
+ let height = Math.round(width / (cellRatio * ratio));
173
+ if (height > maxRows) {
174
+ height = maxRows;
175
+ width = Math.max(1, Math.min(maxColumns, Math.round(cellRatio * height * ratio)));
176
+ }
177
+ return (_jsx(Image, { transparent: true, source: source, width: width, height: height, alt: "", presentation: presentation }));
178
+ }
@@ -0,0 +1,25 @@
1
+ import type { TerminalImageSource } from '../ink/terminal-image.js';
2
+ import type { MathRenderRequest } from '../math/renderer.js';
3
+ /** What a click on a formula image hands to the preview host. */
4
+ export interface MathPreviewRequest {
5
+ /** The formula's TeX without delimiters; the card shows it as its title. */
6
+ readonly tex: string;
7
+ /** The request that produced the raster currently on screen. */
8
+ readonly request: MathRenderRequest;
9
+ /** Those pixels, used as-is when a sharper raster cannot be produced. */
10
+ readonly source: TerminalImageSource;
11
+ }
12
+ export type MathPreviewOpener = (request: MathPreviewRequest) => void;
13
+ /** Published by the transcript host; cleared when it unmounts. */
14
+ export declare function setMathPreviewOpener(next: MathPreviewOpener | undefined): void;
15
+ export declare function getMathPreviewOpener(): MathPreviewOpener | undefined;
16
+ export declare function subscribeMathPreviewOpener(listener: () => void): () => void;
17
+ /** The host's opener, or undefined when nothing can show a preview card. */
18
+ export declare function useMathPreviewOpener(): MathPreviewOpener | undefined;
19
+ /**
20
+ * RGBA raster → PNG bytes, the form the image preview card decodes. Sharp is
21
+ * already a runtime dependency (Sixel encoding uses it) and is optional, so a
22
+ * missing build rejects rather than returning a broken byte string.
23
+ */
24
+ export declare function rasterToPng(source: TerminalImageSource): Promise<Uint8Array>;
25
+ //# sourceMappingURL=mathPreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mathPreview.d.ts","sourceRoot":"","sources":["../../../src/components/mathPreview.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG5D,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;IACnC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;CACrC;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAA;AAKrE,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAI9E;AAED,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,SAAS,CAEpE;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAK3E;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,SAAS,CAEpE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAOlF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Formula-image previews.
3
+ *
4
+ * The transcript host (Chat) publishes an opener for as long as it is mounted,
5
+ * and the math components call it when a formula image is clicked. A
6
+ * module-level registry — the same shape the live display settings use —
7
+ * keeps that callback out of the MessageList → Markdown prop chain, which
8
+ * would otherwise thread it through every message row.
9
+ */
10
+ import React from 'react';
11
+ import { loadSharp } from '../dsh-adapter/sharp.js';
12
+ let opener;
13
+ const listeners = new Set();
14
+ /** Published by the transcript host; cleared when it unmounts. */
15
+ export function setMathPreviewOpener(next) {
16
+ if (opener === next)
17
+ return;
18
+ opener = next;
19
+ for (const listener of listeners)
20
+ listener();
21
+ }
22
+ export function getMathPreviewOpener() {
23
+ return opener;
24
+ }
25
+ export function subscribeMathPreviewOpener(listener) {
26
+ listeners.add(listener);
27
+ return () => {
28
+ listeners.delete(listener);
29
+ };
30
+ }
31
+ /** The host's opener, or undefined when nothing can show a preview card. */
32
+ export function useMathPreviewOpener() {
33
+ return React.useSyncExternalStore(subscribeMathPreviewOpener, getMathPreviewOpener);
34
+ }
35
+ /**
36
+ * RGBA raster → PNG bytes, the form the image preview card decodes. Sharp is
37
+ * already a runtime dependency (Sixel encoding uses it) and is optional, so a
38
+ * missing build rejects rather than returning a broken byte string.
39
+ */
40
+ export async function rasterToPng(source) {
41
+ const sharp = await loadSharp();
42
+ if (sharp === undefined)
43
+ throw new Error('image encoder unavailable');
44
+ const buffer = await sharp(Buffer.from(source.data), {
45
+ raw: { width: source.width, height: source.height, channels: 4 },
46
+ }).png().toBuffer();
47
+ return new Uint8Array(buffer);
48
+ }
@@ -26,7 +26,8 @@ type Props = {
26
26
  onClick?(event: ClickEvent): void;
27
27
  };
28
28
  /**
29
- * Thinking block: settled rows fold to `⚓ Thinking (ctrl+o to expand)`;
29
+ * Thinking block: settled rows fold to `⚓ Thinking` plus the localized
30
+ * ctrl+o expand hint (hint-expand-ctrl-o);
30
31
  * streaming rows switch between a three-line preview and the full reasoning
31
32
  * text on click. The live leading mark is a rotating braille spinner
32
33
  * (`⠋⠙⠹…`, Kimi Code style), settling back to the static anchor (`⚓`). When
@@ -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,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAUjE,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB;;;sDAGkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,eAAe,EAAE,OAAO,CAAA;IACxB,4EAA4E;IAC5E,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,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAClC,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,OAAO,EACP,SAAiB,EACjB,OAAe,EACf,UAAU,EACV,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAuIzB"}
1
+ {"version":3,"file":"AssistantThinkingMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/AssistantThinkingMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAWjE,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB;;;sDAGkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,eAAe,EAAE,OAAO,CAAA;IACxB,4EAA4E;IAC5E,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,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CAClC,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,OAAO,EACP,SAAiB,EACjB,OAAe,EACf,UAAU,EACV,UAAkB,EAClB,OAAO,GACR,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAuIzB"}
@@ -9,6 +9,7 @@ import { THINKING_SPINNER_FRAMES, THINKING_SPINNER_INTERVAL_MS, THINKING_SETTLED
9
9
  import { BRAND, ICE } from '../shimmer.js';
10
10
  import { interpolateColor } from '../Spinner/spinnerUtils.js';
11
11
  import { isMinimalMode } from '../../minimalMode.js';
12
+ import { primaryComboString } from '../../utils/keymap.js';
12
13
  /** Preview body rows — a FIXED row count (kimicode-style constant-height
13
14
  * ticker). Ink's truncate slices the whole string across newlines as one
14
15
  * logical line, so a single joined Text collapses to 1-2 rows whenever
@@ -17,7 +18,8 @@ import { isMinimalMode } from '../../minimalMode.js';
17
18
  * to exactly this many rows, keeps the block height stream-independent. */
18
19
  const PREVIEW_ROWS = 3;
19
20
  /**
20
- * Thinking block: settled rows fold to `⚓ Thinking (ctrl+o to expand)`;
21
+ * Thinking block: settled rows fold to `⚓ Thinking` plus the localized
22
+ * ctrl+o expand hint (hint-expand-ctrl-o);
21
23
  * streaming rows switch between a three-line preview and the full reasoning
22
24
  * text on click. The live leading mark is a rotating braille spinner
23
25
  * (`⠋⠙⠹…`, Kimi Code style), settling back to the static anchor (`⚓`). When
@@ -48,7 +50,7 @@ export function AssistantThinkingMessage({ thinking, textFull, marginTopOnTurn,
48
50
  // header's brand→ice ladder, one sine period per ~7 frames (≈0.56s) —
49
51
  // lively without strobing. Minimal mode drops the color (plain glyph);
50
52
  // settled always keeps the plain dim anchor.
51
- const label = `${t('thinking-label')}${duration}${streaming ? '…' : ` ${t('hint-expand-ctrl-o')}`}`;
53
+ const label = `${t('thinking-label')}${duration}${streaming ? '…' : ` ${t('hint-expand-ctrl-o', { key: primaryComboString('transcript') })}`}`;
52
54
  const minimal = isMinimalMode();
53
55
  const pulse = (Math.sin(frame * 0.9) + 1) / 2;
54
56
  const pulseColor = interpolateColor(BRAND, ICE, pulse);
@@ -15,8 +15,8 @@ type Props = {
15
15
  isExpanded?: boolean;
16
16
  /**
17
17
  * Mouse click (fullscreen): toggles the row's expansion — same action as
18
- * clicking other transcript rows. Also makes the `(ctrl+o to expand)`
19
- * hint actionable with the mouse.
18
+ * clicking other transcript rows. Also makes the localized ctrl+o expand
19
+ * hint (lines-folded-expand) actionable with the mouse.
20
20
  */
21
21
  onClick?(event: ClickEvent): void;
22
22
  /**
@@ -1 +1 @@
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;AASvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAIjE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAA;IACb,4CAA4C;IAC5C,eAAe,EAAE,OAAO,CAAA;IACxB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAA;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC;;;;;;;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;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;8CAC0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAsFD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,CAKtD;AAsVD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,eAAe,EACf,OAAO,EACP,UAAkB,EAClB,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,UAAmB,EACnB,cAAuB,EACvB,UAAU,EACV,mBAA2B,EAC3B,YAAoB,EACpB,KAAa,EACb,aAAa,GACd,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA2PzB"}
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;AASvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAKjE,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAA;IACb,4CAA4C;IAC5C,eAAe,EAAE,OAAO,CAAA;IACxB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAA;IAChB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC;;;;;;;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;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;8CAC0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,qFAAqF;IACrF,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AA2FD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,KAAK,CAKtD;AAsVD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,eAAe,EACf,OAAO,EACP,UAAkB,EAClB,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,UAAmB,EACnB,cAAuB,EACvB,UAAU,EACV,mBAA2B,EAC3B,YAAoB,EACpB,KAAa,EACb,aAAa,GACd,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA2PzB"}
@@ -14,25 +14,30 @@ import { foldLongLines } from '../../utils/fold-long-lines.js';
14
14
  import { getLang, t } from '../../i18n.js';
15
15
  import { revealLinesOf, snapReveal } from '../smoothReveal.js';
16
16
  import { useRevealVersion } from '../../hooks/useRevealVersion.js';
17
- /** Tool display names: DSH emits lowercase tool ids (`bash`); display common
18
- * names with an initial capital and fall back to the id with its first letter
19
- * uppercased. */
17
+ import { primaryComboString } from '../../utils/keymap.js';
18
+ /** Tool display names localize through the `tool-name-*` dictionary family
19
+ * (i18n.ts): DSH emits lowercase tool ids (`bash`), display names resolve
20
+ * per language — proper nouns (Bash, PowerShell) stay identical in zh.
21
+ * Unmapped ids (plugins, new upstream tools) fall back to the id with its
22
+ * first letter uppercased: that is a name, not copy — there is nothing to
23
+ * translate. Keys appear as literals here, so verify-i18n's dead-key scan
24
+ * sees them without a DYNAMIC_PREFIXES entry. */
25
+ const TOOL_NAME_KEYS = {
26
+ bash: 'tool-name-bash',
27
+ powershell: 'tool-name-powershell',
28
+ read: 'tool-name-read',
29
+ glob: 'tool-name-glob',
30
+ grep: 'tool-name-grep',
31
+ write: 'tool-name-write',
32
+ edit: 'tool-name-edit',
33
+ todo_write: 'tool-name-todo_write',
34
+ subagent: 'tool-name-subagent',
35
+ web_search: 'tool-name-web_search',
36
+ };
20
37
  function displayName(name) {
21
- const KNOWN = {
22
- bash: 'Bash',
23
- powershell: 'PowerShell',
24
- read: 'Read',
25
- glob: 'Glob',
26
- grep: 'Grep',
27
- write: 'Write',
28
- edit: 'Edit',
29
- todo_write: 'TodoWrite',
30
- subagent: 'Task',
31
- web_search: 'WebSearch',
32
- };
33
- const mapped = KNOWN[name];
34
- if (mapped)
35
- return mapped;
38
+ const key = TOOL_NAME_KEYS[name];
39
+ if (key !== undefined)
40
+ return t(key);
36
41
  if (name.length === 0)
37
42
  return name;
38
43
  return name[0].toUpperCase() + name.slice(1);
@@ -145,10 +150,10 @@ function viewLines(view) {
145
150
  const out = (('output' in view ? view.output : undefined) ?? '').trimEnd();
146
151
  const lines = out === '' ? [] : out.split('\n').map(plain);
147
152
  if ('exitCode' in view && view.exitCode !== undefined && view.exitCode !== 0) {
148
- lines.push({ text: `Exit code ${view.exitCode}`, tone: 'error' });
153
+ lines.push({ text: t('tool-exit-code', { code: view.exitCode }), tone: 'error' });
149
154
  }
150
155
  if ('signal' in view && view.signal !== undefined) {
151
- lines.push({ text: `Killed by signal ${view.signal}`, tone: 'error' });
156
+ lines.push({ text: t('tool-killed-signal', { name: String(view.signal) }), tone: 'error' });
152
157
  }
153
158
  return lines;
154
159
  }
@@ -160,7 +165,7 @@ function viewLines(view) {
160
165
  if (view.shape === 'paths') {
161
166
  const lines = view.paths.map(plain);
162
167
  if (view.truncated)
163
- lines.push(dim(`… (${view.total} total)`));
168
+ lines.push(dim(t('search-results-total', { n: view.total })));
164
169
  return lines;
165
170
  }
166
171
  const lines = [];
@@ -187,7 +192,7 @@ function capLines(lines, max, verbose) {
187
192
  return lines;
188
193
  return [
189
194
  ...lines.slice(0, max),
190
- { ...dim(`… +${lines.length - max} lines (ctrl+o to expand)`), revealOnHover: true },
195
+ { ...dim(t('lines-folded-expand', { n: lines.length - max, key: primaryComboString('transcript') })), revealOnHover: true },
191
196
  ];
192
197
  }
193
198
  /** Long-line clip for the body rows (utils/fold-long-lines.ts): the line cap
@@ -326,7 +331,7 @@ function HeaderTitle({ name, title, isTerminal, folded, displayArgs, argsLanguag
326
331
  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", ...headerTooltip, children: [_jsx(Text, { children: "(" }), _jsx(SyntaxText, { text: clipHeaderArgs(displayArgs), sourceText: displayArgs, language: argsLanguage }), _jsx(Text, { children: ")" })] }))] }));
327
332
  }
328
333
  if (isTerminal) {
329
- return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", ...headerTooltip, children: folded === undefined ? (_jsxs(Text, { children: ["(", title, ")"] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["(", folded.first, ")"] }), folded.hiddenLines > 0 && (_jsx(Text, { dimColor: true, children: ` … +${folded.hiddenLines} lines (ctrl+o to expand)` }))] })) })] }));
334
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { bold: true, color: nameColor, wrap: "truncate-end", children: name }) }), _jsx(Box, { flexWrap: "nowrap", ...headerTooltip, children: folded === undefined ? (_jsxs(Text, { children: ["(", title, ")"] })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["(", folded.first, ")"] }), folded.hiddenLines > 0 && (_jsx(Text, { dimColor: true, children: ` ${t('lines-folded-expand', { n: folded.hiddenLines, key: primaryComboString('transcript') })}` }))] })) })] }));
330
335
  }
331
336
  const trimmed = title.trim();
332
337
  if (trimmed === '') {
@@ -439,7 +444,7 @@ export function AssistantToolUseMessage({ tool, marginTopOnTurn, verbose, isSele
439
444
  body = result.trimEnd().split('\n').map(plain);
440
445
  }
441
446
  if (isRunning && body.length === 0) {
442
- body = [dim(`Running… (${formatDuration(Math.max(0, Date.now() - (tool.startedAt ?? Date.now())))})`)];
447
+ body = [dim(t('tool-running-elapsed', { duration: formatDuration(Math.max(0, Date.now() - (tool.startedAt ?? Date.now()))) }))];
443
448
  }
444
449
  }
445
450
  const cap = view?.card === 'diff' ? DIFF_BODY_MAX_LINES : TEXT_BODY_MAX_LINES;
@@ -479,8 +484,8 @@ export function AssistantToolUseMessage({ tool, marginTopOnTurn, verbose, isSele
479
484
  // Hover affordance for the click-to-toggle row: the theme's tool-card blue
480
485
  // face marks the call's content area while the pointer dwells (the
481
486
  // toolBackground treatment steps up one level to the strong card face), the
482
- // collapsed `(ctrl+o to expand)` hint steps from dim to text, the elapsed
483
- // clock stops dimming, and a ▾/▴ discloses the row is a toggle.
487
+ // collapsed fold hint (lines-folded-expand) steps from dim to text, the
488
+ // elapsed clock stops dimming, and a ▾/▴ discloses the row is a toggle.
484
489
  // No layout change: the indicator is a fixed column on the header line, the
485
490
  // body never moves.
486
491
  const [hovered, setHovered] = React.useState(false);
@@ -1 +1 @@
1
- {"version":3,"file":"TranscriptImages.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/TranscriptImages.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAS7E,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,gFAAgB,CAAA;AAEpD;wEACwE;AACxE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAGnE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAU,EACV,SAAS,EACT,gBAAwB,GACzB,EAAE;IACD,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IACrD;iDAC6C;IAC7C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC,GAAG,KAAK,CAAC,SAAS,CA6BlB;AA0FD,yEAAyE;AACzE,wBAAgB,iCAAiC,IAAI,IAAI,CAGxD"}
1
+ {"version":3,"file":"TranscriptImages.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/TranscriptImages.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAW7E,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,gFAAgB,CAAA;AAEpD;wEACwE;AACxE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAGnE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAU,EACV,SAAS,EACT,gBAAwB,GACzB,EAAE;IACD,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IACrD;iDAC6C;IAC7C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC,GAAG,KAAK,CAAC,SAAS,CA6BlB;AAqGD,yEAAyE;AACzE,wBAAgB,iCAAiC,IAAI,IAAI,CAGxD"}
@@ -5,6 +5,8 @@ import { TERMINAL_IMAGE_PREVIEW_MAX_EDGE, TERMINAL_IMAGE_PREVIEW_MAX_BYTES } fro
5
5
  import { makeDecodeTier } from './transcriptImageDecode.js';
6
6
  import { cleanRenderText } from '../../dsh-adapter/sanitize.js';
7
7
  import { getLang, subscribeLang, t } from '../../i18n.js';
8
+ import { useTerminalBackground } from '../design-system/ThemeProvider.js';
9
+ import { getImageBacking, subscribeImageBacking } from '../../tuiDisplayPrefs.js';
8
10
  const thumbnailTier = makeDecodeTier(384, 24);
9
11
  // One modal at a time: current + previous suffices for instant reopen.
10
12
  const fullTier = makeDecodeTier(TERMINAL_IMAGE_PREVIEW_MAX_EDGE, 2, TERMINAL_IMAGE_PREVIEW_MAX_BYTES / 4);
@@ -42,6 +44,14 @@ function TranscriptImagePreview({ image, width, height, graphicsAvailable, onPre
42
44
  setState({ kind: 'failed' }); });
43
45
  return () => { live = false; controller.abort(); };
44
46
  }, [image, graphicsAvailable]);
47
+ // What sits behind the raster follows `dsh-tui.imageBacking`: photos
48
+ // may float transparent like formulas (the wallpaper shows at
49
+ // anti-aliased edges and transparent corners — Sixel's binary alpha drops
50
+ // their softest pixels) or composite onto the terminal colour, which
51
+ // keeps soft edges smooth on any background.
52
+ const backing = React.useSyncExternalStore(subscribeImageBacking, getImageBacking);
53
+ const composited = backing === 'terminal';
54
+ const terminalBackground = useTerminalBackground();
45
55
  const label = transcriptImageLabel(image);
46
56
  const fallback = !graphicsAvailable
47
57
  ? t('transcript-image-ready', { name: label })
@@ -50,7 +60,7 @@ function TranscriptImagePreview({ image, width, height, graphicsAvailable, onPre
50
60
  : state.kind === 'loading'
51
61
  ? t('transcript-image-loading', { name: label })
52
62
  : t('transcript-image-ready', { name: label });
53
- const preview = (_jsx(Image, { presentation: "transcript", source: graphicsAvailable && state.kind === 'ready' ? state.source : undefined, width: width, height: height, alt: label, children: _jsx(Box, { width: width, height: height, alignItems: "center", justifyContent: "center", children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: ["[", fallback, "]"] }) }) }));
63
+ const preview = (_jsx(Box, { backgroundColor: composited ? terminalBackground : undefined, children: _jsx(Image, { ...(composited ? {} : { transparent: true }), presentation: "transcript", source: graphicsAvailable && state.kind === 'ready' ? state.source : undefined, width: width, height: height, alt: label, children: _jsx(Box, { width: width, height: height, alignItems: "center", justifyContent: "center", children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: ["[", fallback, "]"] }) }) }) }));
54
64
  if (onPreview === undefined)
55
65
  return preview;
56
66
  return (_jsx(Box, { onClick: event => {
@@ -64,8 +64,20 @@ export type AskUserQuestionPanelProps = {
64
64
  readonly onAnswer: (selection: QuestionSelection) => void;
65
65
  /** Esc on the first question / Ctrl+C — aborts the whole ask. */
66
66
  readonly onCancel: () => void;
67
- /** Esc on later questions — navigates to the previous question. */
67
+ /**
68
+ * Esc, when the host wants to decide back-vs-cancel from the live store.
69
+ * A same-batch → then Esc still runs on the panel mounted for question 1,
70
+ * whose `onBack` is absent; this callback sees that → already advanced.
71
+ */
72
+ readonly onEscape?: (draft: QuestionDraft) => void;
73
+ /** Esc / ← on later questions — navigates to the previous question. */
68
74
  readonly onBack?: (draft: QuestionDraft) => void;
75
+ /**
76
+ * → — navigates to the next question without submitting. On the free-text
77
+ * row this only fires when the caret is already at the end, so ←/→ keep
78
+ * editing the answer.
79
+ */
80
+ readonly onForward?: (draft: QuestionDraft) => void;
69
81
  /**
70
82
  * Test seam: clipboard reader for the Ctrl+V paste arm. Defaults to the
71
83
  * real cross-platform reader (PowerShell/pbpaste/wl-paste…); headless
@@ -89,5 +101,5 @@ export type AskUserQuestionPanelProps = {
89
101
  * pointer, so an unclickable row would just eat a line. */
90
102
  readonly fullscreen?: boolean;
91
103
  };
92
- export declare function AskUserQuestionPanel({ question, position, total, answered, initialDraft, onAnswer, onCancel, onBack, readClipboardOverride, collapsed, onExpand, onToggleFold, fullscreen, }: AskUserQuestionPanelProps): React.ReactNode;
104
+ export declare function AskUserQuestionPanel({ question, position, total, answered, initialDraft, onAnswer, onCancel, onEscape, onBack, onForward, readClipboardOverride, collapsed, onExpand, onToggleFold, fullscreen, }: AskUserQuestionPanelProps): React.ReactNode;
93
105
  //# sourceMappingURL=AskUserQuestionPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AskUserQuestionPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/AskUserQuestionPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAMtF,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAkB5E,MAAM,MAAM,yBAAyB,GAAG;IACtC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;QAC9B;;oEAE4D;QAC5D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;QAClC;;qEAE6D;QAC7D,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5C;0EACkE;QAClE,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAChD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IAC7D;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IAClC;;gEAE4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,qBAAqB,EACrB,SAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,UAAkB,GACnB,EAAE,yBAAyB,GAAG,KAAK,CAAC,SAAS,CAsmB7C"}
1
+ {"version":3,"file":"AskUserQuestionPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/questions/AskUserQuestionPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAMtF,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAuB5E,MAAM,MAAM,yBAAyB,GAAG;IACtC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;QAC3F,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;QAC9B;;oEAE4D;QAC5D,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;QAClC;;qEAE6D;QAC7D,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5C;0EACkE;QAClE,QAAQ,CAAC,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7E,CAAA;IACD,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACzD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAClD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAChD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IACnD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IAC7D;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IAClC;;gEAE4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,SAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,UAAkB,GACnB,EAAE,yBAAyB,GAAG,KAAK,CAAC,SAAS,CA2pB7C"}