@deepseek-harness-tui/dsh-tui 0.11.1 → 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 (427) hide show
  1. package/README.md +50 -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 +39 -17
  7. package/cordis.yml +3 -2
  8. package/lib/settings.json +1272 -0
  9. package/lib/types/adapter/channel/ui-policy.d.ts +9 -2
  10. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  11. package/lib/types/adapter/channel/ui-policy.js +13 -0
  12. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  13. package/lib/types/adapter/kernel/replay.js +2 -0
  14. package/lib/types/adapter/ports/channel-display.d.ts +12 -0
  15. package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
  16. package/lib/types/adapter/ports/channel-session.d.ts +38 -0
  17. package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
  18. package/lib/types/adapter/ports/channel-settings.d.ts +12 -0
  19. package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
  20. package/lib/types/adapter/ports/channel-ui.d.ts +46 -4
  21. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  22. package/lib/types/adapter/ports/channel-view.d.ts +43 -0
  23. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  24. package/lib/types/commands.d.ts.map +1 -1
  25. package/lib/types/commands.js +2 -0
  26. package/lib/types/components/BalanceReportRow.d.ts +10 -2
  27. package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
  28. package/lib/types/components/BalanceReportRow.js +18 -4
  29. package/lib/types/components/CompactionStatusRow.d.ts +24 -0
  30. package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
  31. package/lib/types/components/CompactionStatusRow.js +72 -0
  32. package/lib/types/components/GoalTodoPanel.js +2 -2
  33. package/lib/types/components/HelpMenu.d.ts +2 -2
  34. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  35. package/lib/types/components/HelpMenu.js +5 -4
  36. package/lib/types/components/InlineMathParagraph.d.ts +22 -0
  37. package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
  38. package/lib/types/components/InlineMathParagraph.js +178 -0
  39. package/lib/types/components/LogoV2.d.ts +41 -3
  40. package/lib/types/components/LogoV2.d.ts.map +1 -1
  41. package/lib/types/components/LogoV2.js +148 -24
  42. package/lib/types/components/Markdown.d.ts +10 -3
  43. package/lib/types/components/Markdown.d.ts.map +1 -1
  44. package/lib/types/components/Markdown.js +47 -14
  45. package/lib/types/components/MathBlock.d.ts +13 -0
  46. package/lib/types/components/MathBlock.d.ts.map +1 -0
  47. package/lib/types/components/MathBlock.js +136 -0
  48. package/lib/types/components/MessageList.d.ts +10 -1
  49. package/lib/types/components/MessageList.d.ts.map +1 -1
  50. package/lib/types/components/MessageList.js +13 -4
  51. package/lib/types/components/MigratePicker.d.ts +30 -0
  52. package/lib/types/components/MigratePicker.d.ts.map +1 -0
  53. package/lib/types/components/MigratePicker.js +38 -0
  54. package/lib/types/components/PromptInput.d.ts +17 -0
  55. package/lib/types/components/PromptInput.d.ts.map +1 -1
  56. package/lib/types/components/PromptInput.js +48 -7
  57. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  58. package/lib/types/components/SplitDiffView.js +2 -1
  59. package/lib/types/components/StarPrompt.d.ts +53 -0
  60. package/lib/types/components/StarPrompt.d.ts.map +1 -0
  61. package/lib/types/components/StarPrompt.js +281 -0
  62. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  63. package/lib/types/components/StreamingMarkdown.js +20 -3
  64. package/lib/types/components/TimelineRail.d.ts.map +1 -1
  65. package/lib/types/components/TimelineRail.js +9 -1
  66. package/lib/types/components/Whale.d.ts +17 -8
  67. package/lib/types/components/Whale.d.ts.map +1 -1
  68. package/lib/types/components/Whale.js +25 -15
  69. package/lib/types/components/WhaleGirl.d.ts +29 -0
  70. package/lib/types/components/WhaleGirl.d.ts.map +1 -0
  71. package/lib/types/components/WhaleGirl.js +32 -0
  72. package/lib/types/components/WorkingSpinner.d.ts +4 -1
  73. package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
  74. package/lib/types/components/WorkingSpinner.js +2 -2
  75. package/lib/types/components/bigfont.d.ts +47 -18
  76. package/lib/types/components/bigfont.d.ts.map +1 -1
  77. package/lib/types/components/bigfont.js +55 -40
  78. package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
  79. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  80. package/lib/types/components/design-system/ThemeProvider.js +40 -1
  81. package/lib/types/components/maidPortrait.d.ts +44 -0
  82. package/lib/types/components/maidPortrait.d.ts.map +1 -0
  83. package/lib/types/components/maidPortrait.js +178 -0
  84. package/lib/types/components/mathPreview.d.ts +25 -0
  85. package/lib/types/components/mathPreview.d.ts.map +1 -0
  86. package/lib/types/components/mathPreview.js +48 -0
  87. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  88. package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
  89. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  90. package/lib/types/components/messages/AssistantToolUseMessage.js +3 -2
  91. package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
  92. package/lib/types/components/messages/TranscriptImages.js +11 -1
  93. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
  94. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  95. package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
  96. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  97. package/lib/types/components/questions/PlanReviewPanel.js +3 -3
  98. package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
  99. package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
  100. package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
  101. package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
  102. package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
  103. package/lib/types/components/sessions/SourceTabs.js +70 -0
  104. package/lib/types/components/splashEggs.d.ts +56 -0
  105. package/lib/types/components/splashEggs.d.ts.map +1 -0
  106. package/lib/types/components/splashEggs.js +67 -0
  107. package/lib/types/components/splashFonts.d.ts +119 -0
  108. package/lib/types/components/splashFonts.d.ts.map +1 -0
  109. package/lib/types/components/splashFonts.js +267 -0
  110. package/lib/types/components/splashLayout.d.ts +41 -0
  111. package/lib/types/components/splashLayout.d.ts.map +1 -0
  112. package/lib/types/components/splashLayout.js +40 -0
  113. package/lib/types/components/whaleGirlSprite.d.ts +17 -0
  114. package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
  115. package/lib/types/components/whaleGirlSprite.js +47 -0
  116. package/lib/types/deepseekPricing.d.ts +74 -0
  117. package/lib/types/deepseekPricing.d.ts.map +1 -1
  118. package/lib/types/deepseekPricing.js +110 -11
  119. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  120. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  121. package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
  122. package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -0
  123. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  124. package/lib/types/dsh-adapter/channel/background-action.js +1 -0
  125. package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -9
  126. package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
  127. package/lib/types/dsh-adapter/channel/binding-events.js +69 -21
  128. package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -1
  129. package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
  130. package/lib/types/dsh-adapter/channel/compaction.js +35 -2
  131. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  132. package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
  133. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  134. package/lib/types/dsh-adapter/channel/model-switch.js +5 -1
  135. package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
  136. package/lib/types/dsh-adapter/channel/paths.js +7 -1
  137. package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
  138. package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
  139. package/lib/types/dsh-adapter/channel/preferences.js +16 -0
  140. package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
  141. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  142. package/lib/types/dsh-adapter/channel/projection.js +127 -17
  143. package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
  144. package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
  145. package/lib/types/dsh-adapter/channel/question-record.js +107 -0
  146. package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
  147. package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
  148. package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
  149. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +2 -0
  150. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  151. package/lib/types/dsh-adapter/channel/session-live-adoption.js +9 -3
  152. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
  153. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  154. package/lib/types/dsh-adapter/channel/session-metadata.js +39 -7
  155. package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
  156. package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
  157. package/lib/types/dsh-adapter/channel/session-reset.js +7 -0
  158. package/lib/types/dsh-adapter/channel/session-resume.d.ts +1 -0
  159. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  160. package/lib/types/dsh-adapter/channel/session-resume.js +4 -2
  161. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  162. package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
  163. package/lib/types/dsh-adapter/channel/state.d.ts +14 -1
  164. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/channel/state.js +6 -1
  166. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +30 -35
  167. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
  168. package/lib/types/dsh-adapter/channel/subagent-projection.js +138 -4
  169. package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
  170. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  171. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  172. package/lib/types/dsh-adapter/channel.js +19 -4
  173. package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
  174. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
  175. package/lib/types/dsh-adapter/compat/messages.js +9 -0
  176. package/lib/types/dsh-adapter/contract.d.ts +5 -5
  177. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  178. package/lib/types/dsh-adapter/contract.js +8 -6
  179. package/lib/types/dsh-adapter/index.d.ts +36 -1
  180. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  181. package/lib/types/dsh-adapter/index.js +22 -6
  182. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
  183. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
  184. package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
  185. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
  186. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
  187. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
  188. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
  189. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
  190. package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
  191. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
  192. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
  193. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
  194. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
  195. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
  196. package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
  197. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
  198. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
  199. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
  200. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
  201. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
  202. package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
  203. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
  204. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
  205. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
  206. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
  207. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
  208. package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
  209. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
  210. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
  211. package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
  212. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
  213. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
  214. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
  215. package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
  216. package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
  217. package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
  218. package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
  219. package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
  220. package/lib/types/dsh-adapter/migrate/browse.js +90 -0
  221. package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
  222. package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
  223. package/lib/types/dsh-adapter/migrate/cli.js +106 -0
  224. package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
  225. package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
  226. package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
  227. package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
  228. package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
  229. package/lib/types/dsh-adapter/migrate/index.js +107 -0
  230. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
  231. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
  232. package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
  233. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
  234. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
  235. package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
  236. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
  237. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
  238. package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
  239. package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
  240. package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
  241. package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
  242. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
  243. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
  244. package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
  245. package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
  246. package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
  247. package/lib/types/dsh-adapter/migrate/picker.js +86 -0
  248. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
  249. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
  250. package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
  251. package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
  252. package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
  253. package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
  254. package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
  255. package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
  256. package/lib/types/dsh-adapter/migrate/types.js +11 -0
  257. package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
  258. package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
  259. package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
  260. package/lib/types/dsh-adapter/plugin.d.ts +4 -2
  261. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  262. package/lib/types/dsh-adapter/plugin.js +143 -364
  263. package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
  264. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  265. package/lib/types/dsh-adapter/providerWizard.js +254 -66
  266. package/lib/types/dsh-adapter/questions.d.ts +22 -15
  267. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  268. package/lib/types/dsh-adapter/questions.js +47 -45
  269. package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
  270. package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
  271. package/lib/types/dsh-adapter/sessions/digest.js +20 -13
  272. package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
  273. package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
  274. package/lib/types/dsh-adapter/sessions/frames.js +5 -4
  275. package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
  276. package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
  277. package/lib/types/dsh-adapter/sessions/list.js +188 -164
  278. package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
  279. package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
  280. package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
  281. package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
  282. package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
  283. package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
  284. package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
  285. package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
  286. package/lib/types/dsh-adapter/sessions/store.js +62 -25
  287. package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
  288. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
  289. package/lib/types/dsh-adapter/sideQuestion.js +98 -2
  290. package/lib/types/dsh-adapter/subagents.d.ts +28 -3
  291. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  292. package/lib/types/dsh-adapter/subagents.js +77 -2
  293. package/lib/types/herdr.d.ts +2 -0
  294. package/lib/types/herdr.d.ts.map +1 -1
  295. package/lib/types/herdr.js +9 -3
  296. package/lib/types/i18n.d.ts +424 -42
  297. package/lib/types/i18n.d.ts.map +1 -1
  298. package/lib/types/i18n.js +145 -20
  299. package/lib/types/ink/components/App.d.ts +2 -2
  300. package/lib/types/ink/components/App.d.ts.map +1 -1
  301. package/lib/types/ink/components/App.js +5 -1
  302. package/lib/types/ink/components/Image.d.ts +14 -1
  303. package/lib/types/ink/components/Image.d.ts.map +1 -1
  304. package/lib/types/ink/components/Image.js +2 -2
  305. package/lib/types/ink/events/input-event.js +3 -3
  306. package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
  307. package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
  308. package/lib/types/ink/hooks/use-terminal-images.js +13 -0
  309. package/lib/types/ink/ink.d.ts +6 -0
  310. package/lib/types/ink/ink.d.ts.map +1 -1
  311. package/lib/types/ink/ink.js +16 -1
  312. package/lib/types/ink/kitty-graphics.d.ts +44 -3
  313. package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
  314. package/lib/types/ink/kitty-graphics.js +184 -23
  315. package/lib/types/ink/output.d.ts +24 -2
  316. package/lib/types/ink/output.d.ts.map +1 -1
  317. package/lib/types/ink/output.js +83 -5
  318. package/lib/types/ink/parse-keypress.d.ts +26 -1
  319. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  320. package/lib/types/ink/parse-keypress.js +156 -13
  321. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  322. package/lib/types/ink/render-node-to-output.js +8 -1
  323. package/lib/types/ink/screen.d.ts +24 -0
  324. package/lib/types/ink/screen.d.ts.map +1 -1
  325. package/lib/types/ink/screen.js +89 -0
  326. package/lib/types/ink/selection.d.ts +40 -18
  327. package/lib/types/ink/selection.d.ts.map +1 -1
  328. package/lib/types/ink/selection.js +142 -30
  329. package/lib/types/ink/sixel-codec.d.ts +12 -1
  330. package/lib/types/ink/sixel-codec.d.ts.map +1 -1
  331. package/lib/types/ink/sixel-codec.js +29 -5
  332. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  333. package/lib/types/ink/sixel-graphics.js +5 -3
  334. package/lib/types/ink/styles.d.ts +9 -0
  335. package/lib/types/ink/styles.d.ts.map +1 -1
  336. package/lib/types/ink/terminal-image.d.ts +8 -0
  337. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  338. package/lib/types/ink/terminal-querier.d.ts +7 -1
  339. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  340. package/lib/types/ink/terminal-querier.js +12 -2
  341. package/lib/types/ink/timeline-rail.d.ts +5 -0
  342. package/lib/types/ink/timeline-rail.d.ts.map +1 -1
  343. package/lib/types/math/inline-layout.d.ts +29 -0
  344. package/lib/types/math/inline-layout.d.ts.map +1 -0
  345. package/lib/types/math/inline-layout.js +106 -0
  346. package/lib/types/math/layout.d.ts +58 -0
  347. package/lib/types/math/layout.d.ts.map +1 -0
  348. package/lib/types/math/layout.js +59 -0
  349. package/lib/types/math/renderer.d.ts +64 -0
  350. package/lib/types/math/renderer.d.ts.map +1 -0
  351. package/lib/types/math/renderer.js +256 -0
  352. package/lib/types/screens/Chat.d.ts +14 -1
  353. package/lib/types/screens/Chat.d.ts.map +1 -1
  354. package/lib/types/screens/Chat.js +606 -53
  355. package/lib/types/screens/SessionSupervisor.d.ts +2 -1
  356. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
  357. package/lib/types/screens/SessionSupervisor.js +156 -19
  358. package/lib/types/screens/Settings.d.ts.map +1 -1
  359. package/lib/types/screens/Settings.js +49 -11
  360. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  361. package/lib/types/screens/StatusLine.js +45 -15
  362. package/lib/types/screens/chatOverlay.d.ts +5 -0
  363. package/lib/types/screens/chatOverlay.d.ts.map +1 -1
  364. package/lib/types/screens/chatOverlay.js +1 -0
  365. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
  366. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
  367. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
  368. package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
  369. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
  370. package/lib/types/screens/sessionSupervisor/model.js +26 -0
  371. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
  372. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
  373. package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
  374. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
  375. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
  376. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
  377. package/lib/types/sessionHistory.d.ts +2 -2
  378. package/lib/types/sessionHistory.d.ts.map +1 -1
  379. package/lib/types/sessionHistory.js +31 -5
  380. package/lib/types/settings/definitions.d.ts +681 -0
  381. package/lib/types/settings/definitions.d.ts.map +1 -0
  382. package/lib/types/settings/definitions.js +511 -0
  383. package/lib/types/starAction.d.ts +44 -0
  384. package/lib/types/starAction.d.ts.map +1 -0
  385. package/lib/types/starAction.js +52 -0
  386. package/lib/types/terminal-utils/latex.d.ts +10 -0
  387. package/lib/types/terminal-utils/latex.d.ts.map +1 -0
  388. package/lib/types/terminal-utils/latex.js +1417 -0
  389. package/lib/types/terminal-utils/markdown.d.ts +3 -1
  390. package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
  391. package/lib/types/terminal-utils/markdown.js +26 -1
  392. package/lib/types/terminal-utils/math.d.ts +66 -0
  393. package/lib/types/terminal-utils/math.d.ts.map +1 -0
  394. package/lib/types/terminal-utils/math.js +337 -0
  395. package/lib/types/tips.d.ts.map +1 -1
  396. package/lib/types/tips.js +6 -0
  397. package/lib/types/tuiDisplayPrefs.d.ts +67 -0
  398. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  399. package/lib/types/tuiDisplayPrefs.js +59 -0
  400. package/lib/types/ui.d.ts +1 -1
  401. package/lib/types/ui.d.ts.map +1 -1
  402. package/lib/types/ui.js +1 -1
  403. package/lib/types/usageStats.d.ts +98 -0
  404. package/lib/types/usageStats.d.ts.map +1 -0
  405. package/lib/types/usageStats.js +169 -0
  406. package/lib/types/utils/bmp.d.ts +17 -0
  407. package/lib/types/utils/bmp.d.ts.map +1 -0
  408. package/lib/types/utils/bmp.js +154 -0
  409. package/lib/types/utils/clipboard.d.ts +14 -2
  410. package/lib/types/utils/clipboard.d.ts.map +1 -1
  411. package/lib/types/utils/clipboard.js +143 -8
  412. package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
  413. package/lib/types/utils/fold-long-lines.js +2 -1
  414. package/lib/types/utils/keymap.d.ts +4 -1
  415. package/lib/types/utils/keymap.d.ts.map +1 -1
  416. package/lib/types/utils/keymap.js +8 -0
  417. package/lib/types/utils/modifiers.d.ts +4 -3
  418. package/lib/types/utils/modifiers.d.ts.map +1 -1
  419. package/lib/types/utils/modifiers.js +4 -3
  420. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
  421. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
  422. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
  423. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
  424. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
  425. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
  426. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
  427. package/package.json +111 -97
@@ -0,0 +1,281 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Box, Text, useInput, useTerminalImages, useTerminalSize } from '../ui.js';
4
+ import { getLang, subscribeLang, t } from '../i18n.js';
5
+ import { Divider } from './design-system/Divider.js';
6
+ import { HintLine } from './design-system/HintLine.js';
7
+ import { ListItem } from './design-system/ListItem.js';
8
+ import { MaidPortrait, useMaidPortraits } from './maidPortrait.js';
9
+ import { useTerminalBackground } from './design-system/ThemeProvider.js';
10
+ import { STANDARD_FRAME_INDEX, WhaleArt } from './Whale.js';
11
+ import { OPENING_SEQUENCES, WHALE_FRAME_INDEX } from './whaleFrames.js';
12
+ /** Art slot width — the pixel whale fallback is 40 columns wide, and the
13
+ * raster portrait fits inside the same slot so the card width never moves. */
14
+ const ART_COLUMNS = 40;
15
+ /** Art slot height: 18 rows (confetti 3 + whale 13 in the celebration), and
16
+ * the text column is pinned to the same height (see the column's comment). */
17
+ const ART_ROWS = 18;
18
+ /** Text column width: every copy line, button and hint stays on ONE row
19
+ * (the "排版不舒适" report: no stranded `⭐`, no mid-sentence breaks). */
20
+ const TEXT_COLUMNS = 48;
21
+ /** Portrait + text side by side need this many columns (art 40 + gap 2 +
22
+ * text 48 + card chrome 6); below that the card drops the art and stacks
23
+ * text at the narrower width. */
24
+ const MIN_ART_COLUMNS = 98;
25
+ /** Card height with the art (18 art rows + 2 border rows); terminals shorter
26
+ * than this + 2 margin rows get the text-only card. */
27
+ const MIN_ART_ROWS = 23;
28
+ /** Dwell on the standard pose before the fallback whale's intro loops. */
29
+ const WHALE_REST_MS = 3000;
30
+ /** How long the celebration stays before the card closes itself. */
31
+ const CELEBRATION_MS = 4200;
32
+ /**
33
+ * The one-time "asks for a star" startup modal (usage milestones `99h` /
34
+ * `999 launches`, see `usageStats.ts`). Chat mounts it over a dimmed
35
+ * click-catcher on boot when `dueStarModal()` says the moment arrived —
36
+ * never mid-turn, at most one milestone per boot, `Esc`/click-outside
37
+ * closes, and unmounting hands the keyboard straight back (nothing is left
38
+ * registered, so it cannot steal keys after closing).
39
+ *
40
+ * Composition follows the house design system: the milestone title sits in
41
+ * the card's top border, the two actions are `ListItem` rows (pointer,
42
+ * focus colour, hover background — the same component every picker uses),
43
+ * a `Divider` separates the footer, and the hint line is a `HintLine` with
44
+ * its bold key. The art slot shows the raster maid first, the animated
45
+ * pixel whale otherwise.
46
+ *
47
+ * A successful star switches the card into a short CELEBRATION instead of
48
+ * closing silently: confetti falls over the whale, which spouts on a loop,
49
+ * with a thank-you line — then the card closes itself. A failed attempt
50
+ * keeps the card open with the reason and the browser escape hatch.
51
+ */
52
+ export function StarPrompt({ milestone, actions, onClose, initialPhase = 'ask', }) {
53
+ React.useSyncExternalStore(subscribeLang, getLang);
54
+ const { columns, rows } = useTerminalSize();
55
+ const imagesAvailable = useTerminalImages();
56
+ const portraits = useMaidPortraits(imagesAvailable);
57
+ const maidSource = portraits?.normal;
58
+ // 卡片底色用**终端真底色**(OSC 11)而不是主题的卡片色:后者是一整块
59
+ // 与终端背景无关的实色板,压在带背景图的终端上很僵硬;用真底色时卡片
60
+ // 与终端同色、只靠边框和暗化的背景区分层次,同时它也是真图立绘的不透明
61
+ // 衬底(Sixel 没有 alpha,透明像素得合成到某个实色上)。
62
+ const terminalBackground = useTerminalBackground();
63
+ const withArt = columns >= MIN_ART_COLUMNS && rows >= MIN_ART_ROWS;
64
+ const [phase, setPhase] = React.useState(initialPhase);
65
+ const [failure, setFailure] = React.useState('');
66
+ const [selected, setSelected] = React.useState(0);
67
+ // Some terminals report one Enter twice (parsed Return then raw CR); the
68
+ // modal must not fire its action twice for one press.
69
+ const lastEnterRef = React.useRef(0);
70
+ const live = React.useRef(true);
71
+ React.useEffect(() => () => { live.current = false; }, []);
72
+ const runStar = () => {
73
+ if (phase === 'working' || phase === 'done')
74
+ return;
75
+ setPhase('working');
76
+ void Promise.resolve(actions.onStar()).then(attempt => {
77
+ if (!live.current)
78
+ return;
79
+ if (attempt.kind === 'starred') {
80
+ setPhase('done');
81
+ return;
82
+ }
83
+ setFailure(attempt.kind === 'failed'
84
+ ? t('star-failed', { detail: attempt.detail, url: attempt.url })
85
+ : t(attempt.kind === 'no-gh' ? 'star-no-gh' : 'star-not-authed', { url: attempt.url }));
86
+ // gh 缺失/未登录这类"本机没法一键"的结局:光标直接落到浏览器那一行,
87
+ // 用户按一下 Enter 就打开浏览器自己去点(不必先按 ↓)。
88
+ if (attempt.kind === 'no-gh' || attempt.kind === 'not-authed')
89
+ setSelected(1);
90
+ setPhase('failed');
91
+ }, (error) => {
92
+ if (!live.current)
93
+ return;
94
+ setFailure(t('star-failed', { detail: String(error), url: '' }));
95
+ setPhase('failed');
96
+ });
97
+ };
98
+ // The celebration bows out on its own; a key press closes it early.
99
+ React.useEffect(() => {
100
+ if (phase !== 'done')
101
+ return;
102
+ const timer = setTimeout(onClose, CELEBRATION_MS);
103
+ return () => { clearTimeout(timer); };
104
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- 只在进入庆祝时起表
105
+ }, [phase]);
106
+ useInput((input, key) => {
107
+ if (phase === 'done') {
108
+ onClose();
109
+ return;
110
+ }
111
+ if (key.escape) {
112
+ onClose();
113
+ return;
114
+ }
115
+ if (key.upArrow || key.downArrow || key.tab) {
116
+ setSelected(previous => (previous + 1) % 2);
117
+ return;
118
+ }
119
+ if (key.return) {
120
+ const now = Date.now();
121
+ if (now - lastEnterRef.current < 50)
122
+ return;
123
+ lastEnterRef.current = now;
124
+ if (selected === 0)
125
+ runStar();
126
+ else
127
+ actions.onOpen();
128
+ }
129
+ });
130
+ const textColumns = withArt ? TEXT_COLUMNS : Math.max(24, Math.min(TEXT_COLUMNS, columns - 6));
131
+ const cardColumns = withArt ? 96 : Math.min(columns, textColumns + 6);
132
+ // 卡片 = 艺术槽 + 上下边框。absolute 卡片的高度上限由**根节点高度**决定:
133
+ // 根只有内容高(内联模式的夹具)时,卡片顶端会被裁掉——夹具因此把 Chat
134
+ // 包在视口大小的 Box 里(真机 alt-screen 的根就是整屏)。
135
+ const cardRows = withArt ? ART_ROWS + 2 : 18;
136
+ const left = Math.max(0, Math.floor((columns - cardColumns) / 2));
137
+ const bottom = Math.max(0, Math.min(Math.floor((rows - cardRows) / 2), rows - cardRows));
138
+ const celebrating = phase === 'done';
139
+ const title = celebrating
140
+ ? t('star-modal-thanks-title')
141
+ : milestone.hours !== undefined
142
+ ? t('star-modal-title-hours', { hours: milestone.hours })
143
+ : t('star-modal-title-launches', { launches: milestone.launches ?? 0 });
144
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { position: "absolute", bottom: 0, left: 0, width: "100%", height: rows, flexShrink: 0, backdrop: "dim", onClick: onClose }), _jsx(Box, { position: "absolute", left: left, bottom: bottom, width: cardColumns, height: cardRows, flexDirection: "column", flexShrink: 0, overflow: "hidden", backgroundColor: terminalBackground, opaque: true, onClick: event => { event.stopImmediatePropagation(); }, children: _jsxs(Box, { flexDirection: "row", gap: 2, alignItems: "center", justifyContent: "center", borderStyle: "round", borderColor: "inactive", paddingX: 2, backgroundColor: terminalBackground, children: [withArt && (_jsx(ArtSlot, { celebrating: celebrating, phase: phase, imagesAvailable: imagesAvailable, maidSource: maidSource, maidHappy: portraits?.happy, background: terminalBackground })), _jsxs(Box, { flexDirection: "column", width: textColumns, ...(withArt ? { height: ART_ROWS } : {}), children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { color: "accent", bold: true, wrap: "truncate-end", children: title }) }), _jsx(Box, { height: 1 }), celebrating ? (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-1') }), _jsx(Box, { height: 1 }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-2') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-3') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-4') }), _jsx(Box, { flexGrow: 1 }), _jsx(Divider, { width: textColumns }), _jsx(Box, { height: 1 }), _jsx(Text, { dimColor: true, wrap: "wrap", children: _jsx(HintLine, { text: t('star-modal-thanks-hint') }) })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: t('star-modal-body-1') }), _jsx(Box, { height: 1 }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-2') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-3') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-4') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-5') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-6') }), _jsx(Box, { height: 1 }), _jsx(ListItem, { isFocused: selected === 0, disabled: phase === 'working', declareCursor: false, onClick: event => {
145
+ event.stopImmediatePropagation();
146
+ setSelected(0);
147
+ runStar();
148
+ }, children: phase === 'working' ? t('star-modal-working') : t('star-modal-star') }), _jsx(ListItem, { isFocused: selected === 1, declareCursor: false, onClick: event => {
149
+ event.stopImmediatePropagation();
150
+ setSelected(1);
151
+ actions.onOpen();
152
+ }, children: t('star-modal-open') }), phase === 'failed' && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Text, { color: "error", wrap: "wrap", children: failure })] })), phase !== 'failed' && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Divider, { width: textColumns })] })), _jsx(Box, { height: 1 }), _jsx(Text, { dimColor: true, wrap: "wrap", children: _jsx(HintLine, { text: t('star-modal-hint') }) })] }))] })] }) })] }));
153
+ }
154
+ /**
155
+ * The card's art column: the raster maid first, the animated pixel whale
156
+ * otherwise. While celebrating it shows the **happy maid** (raster→raster in
157
+ * the same pixel canvas, so the swap is a clean erase+draw) under the star
158
+ * field; without image protocols the whale spouts instead — character
159
+ * blocks never take this slot.
160
+ */
161
+ function ArtSlot({ celebrating, phase, imagesAvailable, maidSource, maidHappy, background, }) {
162
+ const raster = imagesAvailable && maidSource !== undefined;
163
+ const frame = useWhaleFrames(celebrating && !raster ? 'celebrate' : raster || phase === 'working' ? 'none' : 'intro');
164
+ if (celebrating && raster) {
165
+ return (_jsxs(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "column", alignItems: "center", justifyContent: "center", backgroundColor: background, children: [_jsx(Confetti, { width: ART_COLUMNS }), _jsx(MaidPortrait, { source: maidHappy ?? maidSource, maxColumns: ART_COLUMNS, maxRows: ART_ROWS - CONFETTI_ROWS, presentation: "preview" })] }));
166
+ }
167
+ if (celebrating) {
168
+ return (_jsxs(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "column", alignItems: "center", justifyContent: "center", backgroundColor: background, opaque: true, children: [_jsx(Confetti, { width: ART_COLUMNS }), _jsx(WhaleArt, { frameIndex: frame, width: ART_COLUMNS })] }));
169
+ }
170
+ if (raster) {
171
+ return (_jsx(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "row", justifyContent: "center", alignItems: "center", children: _jsx(MaidPortrait, { source: maidSource, maxColumns: ART_COLUMNS, maxRows: ART_ROWS, presentation: "preview" }) }));
172
+ }
173
+ return (_jsx(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "row", justifyContent: "center", alignItems: "center", children: _jsx(WhaleArt, { frameIndex: frame, width: ART_COLUMNS }) }));
174
+ }
175
+ /**
176
+ * Drive the art slot's frame: `intro` loops the classic opener with a rest
177
+ * on the standard pose, `celebrate` loops the water spout (the thank-you
178
+ * animation), `none` parks on the standard pose with no timer at all.
179
+ */
180
+ function useWhaleFrames(mode) {
181
+ const [frame, setFrame] = React.useState(STANDARD_FRAME_INDEX);
182
+ React.useEffect(() => {
183
+ if (mode === 'none') {
184
+ setFrame(STANDARD_FRAME_INDEX);
185
+ return;
186
+ }
187
+ const sequence = mode === 'celebrate' ? CELEBRATION_FRAMES : OPENING_SEQUENCES.classic;
188
+ let step = 0;
189
+ let timer;
190
+ const tick = () => {
191
+ const current = sequence[step] ?? sequence[0];
192
+ setFrame(current.frame);
193
+ const last = step === sequence.length - 1;
194
+ step = (step + 1) % sequence.length;
195
+ const rest = mode === 'celebrate' ? 0 : WHALE_REST_MS;
196
+ timer = setTimeout(tick, last ? (rest || current.ms) : current.ms);
197
+ timer.unref?.();
198
+ };
199
+ tick();
200
+ return () => { if (timer !== undefined)
201
+ clearTimeout(timer); };
202
+ }, [mode]);
203
+ return frame;
204
+ }
205
+ /**
206
+ * The celebration loop, paced instead of frantic: the spout blooms up with
207
+ * easing (130→100ms), falls back slower (110→180ms), rests, then ONE gentle
208
+ * tail wag, then rests again——约 3.2s 一轮,与卡片的关闭时间同量级。
209
+ */
210
+ const CELEBRATION_FRAMES = [
211
+ { frame: WHALE_FRAME_INDEX.spout1, ms: 130 },
212
+ { frame: WHALE_FRAME_INDEX.spout2, ms: 120 },
213
+ { frame: WHALE_FRAME_INDEX.spout3, ms: 110 },
214
+ { frame: WHALE_FRAME_INDEX.spout4, ms: 100 },
215
+ { frame: WHALE_FRAME_INDEX.spout5, ms: 100 },
216
+ { frame: WHALE_FRAME_INDEX.spout6, ms: 110 },
217
+ { frame: WHALE_FRAME_INDEX.spout5, ms: 120 },
218
+ { frame: WHALE_FRAME_INDEX.spout4, ms: 130 },
219
+ { frame: WHALE_FRAME_INDEX.spout3, ms: 150 },
220
+ { frame: WHALE_FRAME_INDEX.spout2, ms: 170 },
221
+ { frame: WHALE_FRAME_INDEX.spout1, ms: 190 },
222
+ { frame: STANDARD_FRAME_INDEX, ms: 620 },
223
+ { frame: WHALE_FRAME_INDEX.tail1, ms: 180 },
224
+ { frame: WHALE_FRAME_INDEX.tail2, ms: 200 },
225
+ { frame: WHALE_FRAME_INDEX.tail3, ms: 200 },
226
+ { frame: WHALE_FRAME_INDEX.tail4, ms: 180 },
227
+ { frame: STANDARD_FRAME_INDEX, ms: 520 },
228
+ ];
229
+ /** 星光两行、稀疏:主星(常亮,金色)+ 闪烁星(各列相位不同,同一帧只有
230
+ * 三分之一亮着)——比随机撒点安静,也比满屏星星精致。 */
231
+ const CONFETTI_GLYPHS = ['✦', '✧'];
232
+ const CONFETTI_COLORS = ['warning', 'accent', 'activity'];
233
+ const CONFETTI_FRAMES = 3;
234
+ const CONFETTI_ROWS = 2;
235
+ /** 每几列一颗主星(常亮)。 */
236
+ const CONFETTI_ANCHOR_STRIDE = 7;
237
+ const CONFETTI = Array.from({ length: CONFETTI_FRAMES }, (_, frameIndex) => Array.from({ length: CONFETTI_ROWS }, (_, row) => {
238
+ const runs = [];
239
+ let current = undefined;
240
+ let buffer = '';
241
+ for (let column = 0; column < ART_COLUMNS; column++) {
242
+ const anchor = column % CONFETTI_ANCHOR_STRIDE === 0;
243
+ // 闪烁星:每列一个固定相位,逐帧轮到自己亮一次(在 3 帧里亮 1 帧)。
244
+ const twinkle = !anchor
245
+ && column % 2 === 0
246
+ && (column / 2 + row) % CONFETTI_FRAMES === frameIndex;
247
+ const glyph = anchor ? CONFETTI_GLYPHS[0] : twinkle ? CONFETTI_GLYPHS[1] : ' ';
248
+ const color = anchor
249
+ ? CONFETTI_COLORS[0]
250
+ : twinkle
251
+ ? (column / 2) % 2 === 0 ? CONFETTI_COLORS[1] : CONFETTI_COLORS[2]
252
+ : undefined;
253
+ if (color !== current) {
254
+ if (buffer !== '')
255
+ runs.push({ text: buffer, color: current });
256
+ buffer = '';
257
+ current = color;
258
+ }
259
+ buffer += glyph;
260
+ }
261
+ if (buffer !== '')
262
+ runs.push({ text: buffer, color: current });
263
+ return runs;
264
+ }));
265
+ /** One confetti band, advancing a frame every 160ms while it is mounted. */
266
+ function Confetti({ width }) {
267
+ const frame = useConfettiFrame();
268
+ const rows = CONFETTI[frame] ?? CONFETTI[0];
269
+ return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: width, children: rows.map((runs, index) => (_jsx(Text, { wrap: "truncate-end", children: runs.map((run, runIndex) => (_jsx(Text, { color: run.color, children: run.text }, runIndex))) }, index))) }));
270
+ }
271
+ function useConfettiFrame() {
272
+ const [frame, setFrame] = React.useState(0);
273
+ React.useEffect(() => {
274
+ const timer = setInterval(() => {
275
+ setFrame(previous => (previous + 1) % CONFETTI_FRAMES);
276
+ }, 220);
277
+ timer.unref?.();
278
+ return () => { clearInterval(timer); };
279
+ }, []);
280
+ return frame;
281
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"StreamingMarkdown.d.ts","sourceRoot":"","sources":["../../../src/components/StreamingMarkdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAuMzB,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,QAAgB,GACjB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CAyIlB"}
1
+ {"version":3,"file":"StreamingMarkdown.d.ts","sourceRoot":"","sources":["../../../src/components/StreamingMarkdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAwMzB,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,QAAgB,GACjB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CA2JlB"}
@@ -2,8 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { marked } from 'marked';
4
4
  import Box from '../ink/components/Box.js';
5
- import { formatToken, stripPromptXMLTags } from '../terminal-utils/markdown.js';
5
+ import { configureMarked, formatToken, stripPromptXMLTags } from '../terminal-utils/markdown.js';
6
6
  import { t } from '../i18n.js';
7
+ import { isMathBlockToken, mayBecomeCodeSpan } from '../terminal-utils/math.js';
7
8
  import { isStandaloneToken, Markdown } from './Markdown.js';
8
9
  /**
9
10
  * Renders streaming markdown in sealed groups of completed top-level blocks.
@@ -177,6 +178,9 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
177
178
  const prefixVisibleRef = React.useRef(false);
178
179
  const prefixEndsWithNodeRef = React.useRef(false);
179
180
  const prefixTrailingEmptyTextRef = React.useRef(false);
181
+ // The boundary lex below must see the same tokenizer extensions (math
182
+ // blocks) as the Markdown children, or the two disagree on block edges.
183
+ configureMarked();
180
184
  const stripped = stripPromptXMLTags(children);
181
185
  // Reset if text was replaced (defensive; normally unmount handles this)
182
186
  if (!stripped.startsWith(prefixRef.current)) {
@@ -209,6 +213,19 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
209
213
  while (lastContentIdx >= 0 && tokens[lastContentIdx].type === 'space') {
210
214
  lastContentIdx--;
211
215
  }
216
+ // A block formula after a paragraph with an open backtick run is
217
+ // provisional until a blank line: the run's closer may still arrive and
218
+ // turn both into one code span, so the paragraph stays unsealed.
219
+ let consumed = 0;
220
+ for (let i = 0; i < lastContentIdx; i++) {
221
+ const token = tokens[i];
222
+ if (token.type === 'paragraph' && isMathBlockToken(tokens[i + 1]) &&
223
+ mayBecomeCodeSpan(token.raw, stripped.substring(boundary + consumed + token.raw.length))) {
224
+ lastContentIdx = i;
225
+ break;
226
+ }
227
+ consumed += token.raw.length;
228
+ }
212
229
  let advance = 0;
213
230
  for (let i = 0; i < lastContentIdx; i++) {
214
231
  advance += tokens[i].raw.length;
@@ -249,7 +266,7 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
249
266
  }
250
267
  }
251
268
  if (blocks.definitions) {
252
- return _jsx(Markdown, { dimColor: dimColor, cacheTokens: false, children: stripped });
269
+ return _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, cacheTokens: false, children: stripped });
253
270
  }
254
271
  const stablePrefix = prefixRef.current;
255
272
  const prefixTail = blocks.tail;
@@ -275,5 +292,5 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
275
292
  // an overlapping empty/duplicate boundary.
276
293
  const hasDistinctSuffix = unstableSuffix !== '' &&
277
294
  (stablePrefix === '' || !unstableSuffix.startsWith(stablePrefix));
278
- return (_jsxs(Box, { flexDirection: "column", children: [blocks.blocks.map((block, index) => (_jsx(Box, { flexDirection: "column", marginTop: block.gap, children: _jsx(Markdown, { dimColor: dimColor, children: block.text }) }, index))), prefixTail && (_jsx(Box, { flexDirection: "column", marginTop: blocks.tailGap, children: _jsx(Markdown, { dimColor: dimColor, children: prefixTail }) }, "prefix")), hasDistinctSuffix && (_jsx(Box, { flexDirection: "column", marginTop: boundaryGap, children: _jsx(Markdown, { dimColor: dimColor, cacheTokens: false, children: unstableSuffix }) }, "suffix"))] }));
295
+ return (_jsxs(Box, { flexDirection: "column", children: [blocks.blocks.map((block, index) => (_jsx(Box, { flexDirection: "column", marginTop: block.gap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, children: block.text }) }, index))), prefixTail && (_jsx(Box, { flexDirection: "column", marginTop: blocks.tailGap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, children: prefixTail }) }, "prefix")), hasDistinctSuffix && (_jsx(Box, { flexDirection: "column", marginTop: boundaryGap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, cacheTokens: false, children: unstableSuffix }) }, "suffix"))] }));
279
296
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TimelineRail.d.ts","sourceRoot":"","sources":["../../../src/components/TimelineRail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEpE,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAwBhC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,qEAAqE;IACrE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAClC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;6DACyD;IACzD,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC,GAAG,KAAK,CAAC,SAAS,CAuNlB"}
1
+ {"version":3,"file":"TimelineRail.d.ts","sourceRoot":"","sources":["../../../src/components/TimelineRail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEpE,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAwBhC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,qEAAqE;IACrE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAClC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;6DACyD;IACzD,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC,GAAG,KAAK,CAAC,SAAS,CA+NlB"}
@@ -177,7 +177,15 @@ export function TimelineRail({ handle, turns, activeId, upId, downId, terminalWi
177
177
  const cardH = lines.length + 2;
178
178
  if (cardH <= viewport) {
179
179
  const top = Math.max(0, Math.min(tickRow - Math.floor(cardH / 2), viewport - cardH));
180
- card = (_jsx(Box, { position: "absolute", top: top, right: RAIL_WIDTH + 1, width: cardW, height: cardH, flexDirection: "column", flexShrink: 0, borderStyle: "round", borderColor: "inactive", paddingX: 1,
180
+ card = (_jsx(Box, { position: "absolute", top: top, right: RAIL_WIDTH + 1, width: cardW, height: cardH, flexDirection: "column", flexShrink: 0, borderStyle: "round", borderColor: "inactive",
181
+ // An opaque surface, like every other card floating over the
182
+ // transcript (Tooltip's card uses the same token). Without it
183
+ // the card is translucent: the rows underneath show through
184
+ // the padding/border columns, so the transcript's own fills
185
+ // leak out beside each preview line (reported from a real
186
+ // session: one line leaked the message background, the next a
187
+ // terminal-default gap).
188
+ backgroundColor: "toolCardBackground", paddingX: 1,
181
189
  // The card floats LEFT of the rail over selectable
182
190
  // transcript text; fence its own rect so a drag that
183
191
  // happens under a dwell-popped preview never copies the
@@ -11,14 +11,23 @@ import { type WhaleLayerPose } from './whaleLayers.js';
11
11
  */
12
12
  type Rgb = readonly [number, number, number];
13
13
  /**
14
- * Render one frame to ANSI rows (one per sprite row pair) under its own
15
- * palette. Consecutive cells sharing one style are run-length encoded; every
16
- * row spans the full sprite width (transparent cells write plain spaces, so
17
- * the blank cells of a diff region are re-output and overwrite whatever the
18
- * previous frame painted there), and each row closes with an erase-to-EOL:
19
- * the text pipeline may trim trailing whitespace, and the erase guarantees
20
- * the terminal itself clears every cell past the row's last glyph — no
21
- * ghost pixels can survive a frame switch.
14
+ * Half-block row encoder for true-color letter-grid sprites (the pixel
15
+ * whale's frames): `pixel(x, y)` returns the color of sprite cell (x, y)
16
+ * or `undefined` for transparent.
17
+ *
18
+ * Render one sprite to ANSI rows (one per sprite row pair). Consecutive
19
+ * cells sharing one style are run-length encoded; every row spans the full
20
+ * sprite width (transparent cells write plain spaces, so the blank cells of
21
+ * a diff region are re-output and overwrite whatever the previous frame
22
+ * painted there), and each row closes with an erase-to-EOL: the text
23
+ * pipeline may trim trailing whitespace, and the erase guarantees the
24
+ * terminal itself clears every cell past the row's last glyph — no ghost
25
+ * pixels can survive a frame switch.
26
+ */
27
+ export declare function renderCellRows(width: number, height: number, pixel: (x: number, y: number) => Rgb | undefined): string[];
28
+ /**
29
+ * Render one letter-grid frame to ANSI rows under its own palette — the
30
+ * thin adapter over {@link renderCellRows} the whale frames use.
22
31
  */
23
32
  export declare function renderSpriteRows(sprite: readonly string[], palette: Record<string, Rgb | undefined>): string[];
24
33
  /** Render one composed pose (body + action layers) to ANSI rows, cached. */
@@ -1 +1 @@
1
- {"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjF;;;;;;;;GAQG;AAEH,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAoB5C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,EAAE,CA2C9G;AAWD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAO/D;AAGD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,EACvB,UAAiC,EACjC,IAAI,EACJ,KAAK,GACN,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CAWlB"}
1
+ {"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjF;;;;;;;;GAQG;AAEH,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAoB5C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,SAAS,GAC/C,MAAM,EAAE,CAyCV;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,EAAE,CAG9G;AAWD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAO/D;AAGD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,EACvB,UAAiC,EACjC,IAAI,EACJ,KAAK,GACN,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CAWlB"}
@@ -19,25 +19,27 @@ const ERASE_TO_EOL = '\x1b[K';
19
19
  /** Reset the background plane to the terminal default (fg keeps its SGR). */
20
20
  const BG_DEFAULT = '\x1b[49m';
21
21
  /**
22
- * Render one frame to ANSI rows (one per sprite row pair) under its own
23
- * palette. Consecutive cells sharing one style are run-length encoded; every
24
- * row spans the full sprite width (transparent cells write plain spaces, so
25
- * the blank cells of a diff region are re-output and overwrite whatever the
26
- * previous frame painted there), and each row closes with an erase-to-EOL:
27
- * the text pipeline may trim trailing whitespace, and the erase guarantees
28
- * the terminal itself clears every cell past the row's last glyph — no
29
- * ghost pixels can survive a frame switch.
22
+ * Half-block row encoder for true-color letter-grid sprites (the pixel
23
+ * whale's frames): `pixel(x, y)` returns the color of sprite cell (x, y)
24
+ * or `undefined` for transparent.
25
+ *
26
+ * Render one sprite to ANSI rows (one per sprite row pair). Consecutive
27
+ * cells sharing one style are run-length encoded; every row spans the full
28
+ * sprite width (transparent cells write plain spaces, so the blank cells of
29
+ * a diff region are re-output and overwrite whatever the previous frame
30
+ * painted there), and each row closes with an erase-to-EOL: the text
31
+ * pipeline may trim trailing whitespace, and the erase guarantees the
32
+ * terminal itself clears every cell past the row's last glyph — no ghost
33
+ * pixels can survive a frame switch.
30
34
  */
31
- export function renderSpriteRows(sprite, palette) {
35
+ export function renderCellRows(width, height, pixel) {
32
36
  const rows = [];
33
- for (let r = 0; r < sprite.length; r += 2) {
34
- const upper = sprite[r];
35
- const lower = sprite[r + 1] ?? '';
37
+ for (let y = 0; y < height; y += 2) {
36
38
  let out = '';
37
39
  let current = '';
38
- for (let x = 0; x < upper.length; x++) {
39
- const up = palette[upper[x]];
40
- const lo = palette[lower[x]];
40
+ for (let x = 0; x < width; x++) {
41
+ const up = pixel(x, y);
42
+ const lo = pixel(x, y + 1);
41
43
  let seq;
42
44
  let ch;
43
45
  if (up !== undefined && lo !== undefined) {
@@ -76,6 +78,14 @@ export function renderSpriteRows(sprite, palette) {
76
78
  }
77
79
  return rows;
78
80
  }
81
+ /**
82
+ * Render one letter-grid frame to ANSI rows under its own palette — the
83
+ * thin adapter over {@link renderCellRows} the whale frames use.
84
+ */
85
+ export function renderSpriteRows(sprite, palette) {
86
+ const width = sprite.reduce((max, row) => Math.max(max, row.length), 0);
87
+ return renderCellRows(width, sprite.length, (x, y) => palette[sprite[y]?.[x] ?? '']);
88
+ }
79
89
  /** Pre-rendered ANSI rows for every whale frame, computed once at module load. */
80
90
  const RENDERED = WHALE_FRAMES.map(frame => renderSpriteRows(frame.rows, PALETTE));
81
91
  /**
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ /**
3
+ * The maid portrait (鲸鱼娘) that can stand in for the header's pixel whale
4
+ * (settings `dsh-tui.whaleGirl`): the author-designed 30×30 true-color
5
+ * sprite in `whaleGirlSprite.ts`, rendered with the same half-block
6
+ * technique as the whale — one `▀`/`▄` cell packs two sprite rows, so the
7
+ * portrait shows at 30 columns × 15 rows. A static portrait by design: the
8
+ * whale's idle planner and click-hearts stay whale-only, so `dsh-tui.whaleIdle`
9
+ * has nothing to animate here (documented with the setting).
10
+ */
11
+ /** Pre-rendered ANSI rows, computed once at module load. */
12
+ export declare const WHALE_GIRL_ROWS: readonly string[];
13
+ /**
14
+ * The portrait's center column when it fills the whale's 40-column box
15
+ * (indented (40−30)/2 = 5, so the art spans columns 5..34 → center 19.5).
16
+ * The welcome tagline centers on this instead of `WHALE_CENTER` in maid
17
+ * mode, keeping the caption under the art it belongs to.
18
+ */
19
+ export declare const WHALE_GIRL_CENTER = 19.5;
20
+ /**
21
+ * The maid portrait as an Ink component: 15 rows × 30 columns. `width` pins
22
+ * the box (the header passes the whale's 40-column box so the neighbouring
23
+ * text column never shifts) and centers the portrait inside it; without it
24
+ * the component is exactly the portrait's own 30 columns (the star modal).
25
+ */
26
+ export declare function WhaleGirlArt({ width }: {
27
+ width?: number;
28
+ }): React.ReactNode;
29
+ //# sourceMappingURL=WhaleGirl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WhaleGirl.d.ts","sourceRoot":"","sources":["../../../src/components/WhaleGirl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB;;;;;;;;GAQG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAI5C,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAW3E"}
@@ -0,0 +1,32 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from '../ui.js';
3
+ import { renderCellRows } from './Whale.js';
4
+ import { WHALE_GIRL_COLS, WHALE_GIRL_SPRITE, WHALE_GIRL_SPRITE_ROWS } from './whaleGirlSprite.js';
5
+ /**
6
+ * The maid portrait (鲸鱼娘) that can stand in for the header's pixel whale
7
+ * (settings `dsh-tui.whaleGirl`): the author-designed 30×30 true-color
8
+ * sprite in `whaleGirlSprite.ts`, rendered with the same half-block
9
+ * technique as the whale — one `▀`/`▄` cell packs two sprite rows, so the
10
+ * portrait shows at 30 columns × 15 rows. A static portrait by design: the
11
+ * whale's idle planner and click-hearts stay whale-only, so `dsh-tui.whaleIdle`
12
+ * has nothing to animate here (documented with the setting).
13
+ */
14
+ /** Pre-rendered ANSI rows, computed once at module load. */
15
+ export const WHALE_GIRL_ROWS = renderCellRows(WHALE_GIRL_COLS, WHALE_GIRL_SPRITE_ROWS, (x, y) => WHALE_GIRL_SPRITE[y]?.[x] ?? undefined);
16
+ /**
17
+ * The portrait's center column when it fills the whale's 40-column box
18
+ * (indented (40−30)/2 = 5, so the art spans columns 5..34 → center 19.5).
19
+ * The welcome tagline centers on this instead of `WHALE_CENTER` in maid
20
+ * mode, keeping the caption under the art it belongs to.
21
+ */
22
+ export const WHALE_GIRL_CENTER = 19.5;
23
+ /**
24
+ * The maid portrait as an Ink component: 15 rows × 30 columns. `width` pins
25
+ * the box (the header passes the whale's 40-column box so the neighbouring
26
+ * text column never shifts) and centers the portrait inside it; without it
27
+ * the component is exactly the portrait's own 30 columns (the star modal).
28
+ */
29
+ export function WhaleGirlArt({ width }) {
30
+ const pad = width === undefined ? 0 : Math.max(0, Math.floor((width - WHALE_GIRL_COLS) / 2));
31
+ return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: width, children: WHALE_GIRL_ROWS.map((row, index) => (_jsxs(Text, { wrap: "truncate-end", children: [pad > 0 ? ' '.repeat(pad) : '', row] }, index))) }));
32
+ }
@@ -7,7 +7,7 @@ import type { SpinnerMode } from './Spinner/spinnerMode.js';
7
7
  *
8
8
  * Random verb is picked once per turn (per mount of the spinner).
9
9
  */
10
- export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, }: {
10
+ export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, suffix, }: {
11
11
  mode: SpinnerMode;
12
12
  hasActiveTools: boolean;
13
13
  responseLengthRef: React.RefObject<number>;
@@ -17,6 +17,9 @@ export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef
17
17
  totalPausedMsRef: React.RefObject<number>;
18
18
  pauseStartTimeRef: React.RefObject<number | null>;
19
19
  thinkingStatus: 'thinking' | number | null;
20
+ /** Extra leading field (e.g. the auto-compaction badge) shown before the
21
+ * timer/token counters; omitted for an ordinary turn. */
22
+ suffix?: string;
20
23
  }): React.ReactNode;
21
24
  /**
22
25
  * Tracks thinking status: 'thinking' while the model is streaming reasoning,
@@ -1 +1 @@
1
- {"version":3,"file":"WorkingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/WorkingSpinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAM3D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACf,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC1C,+EAA+E;IAC/E,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACxC,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5C,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACzC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACjD,cAAc,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAA;CAC3C,GAAG,KAAK,CAAC,SAAS,CA4BlB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,GAClB,UAAU,GAAG,MAAM,GAAG,IAAI,CA6C5B"}
1
+ {"version":3,"file":"WorkingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/WorkingSpinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAM3D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,MAAM,GACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC1C,+EAA+E;IAC/E,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACxC,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5C,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACzC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACjD,cAAc,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1C;8DAC0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,KAAK,CAAC,SAAS,CA4BlB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,GAClB,UAAU,GAAG,MAAM,GAAG,IAAI,CA6C5B"}
@@ -13,12 +13,12 @@ import { sample } from 'lodash-es';
13
13
  *
14
14
  * Random verb is picked once per turn (per mount of the spinner).
15
15
  */
16
- export function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, }) {
16
+ export function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, suffix, }) {
17
17
  const { columns } = useTerminalSize();
18
18
  // Pick a random verb once per spinner mount (per turn).
19
19
  const [randomVerb] = useState(() => sample(SPINNER_VERBS) ?? 'Working');
20
20
  const message = `${tOr(`spinner-verb-${randomVerb.toLowerCase()}`, randomVerb)}…`;
21
- return (_jsx(Box, { flexDirection: "column", width: "100%", alignItems: "flex-start", children: _jsx(SpinnerAnimationRow, { mode: mode, reducedMotion: false, hasActiveTools: hasActiveTools, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, message: message, messageColor: "accent", shimmerColor: "accentShimmer", loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, spinnerSuffix: null, verbose: true, columns: columns, thinkingStatus: thinkingStatus }) }));
21
+ return (_jsx(Box, { flexDirection: "column", width: "100%", alignItems: "flex-start", children: _jsx(SpinnerAnimationRow, { mode: mode, reducedMotion: false, hasActiveTools: hasActiveTools, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, message: message, messageColor: "accent", shimmerColor: "accentShimmer", loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, spinnerSuffix: suffix === undefined ? null : suffix, verbose: true, columns: columns, thinkingStatus: thinkingStatus }) }));
22
22
  }
23
23
  /**
24
24
  * Tracks thinking status: 'thinking' while the model is streaming reasoning,