@deepseek-harness-tui/dsh-tui 0.11.1 → 0.12.0

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 (531) hide show
  1. package/README.md +70 -24
  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 +93 -6
  6. package/cordis.patch.yml +63 -22
  7. package/cordis.yml +3 -2
  8. package/guide/dsh-tui-guide/SKILL.md +37 -0
  9. package/guide/dsh-tui-guide/configuration.en.md +410 -0
  10. package/guide/dsh-tui-guide/configuration.md +349 -0
  11. package/guide/dsh-tui-guide/getting-started.en.md +398 -0
  12. package/guide/dsh-tui-guide/getting-started.md +397 -0
  13. package/guide/dsh-tui-guide/interaction.en.md +674 -0
  14. package/guide/dsh-tui-guide/interaction.md +747 -0
  15. package/guide/dsh-tui-guide/migrate.en.md +166 -0
  16. package/guide/dsh-tui-guide/migrate.md +132 -0
  17. package/guide/dsh-tui-guide/plugins.en.md +68 -0
  18. package/guide/dsh-tui-guide/plugins.md +56 -0
  19. package/guide/dsh-tui-guide/themes.en.md +192 -0
  20. package/guide/dsh-tui-guide/themes.md +185 -0
  21. package/guide/dsh-tui-guide/user-guide.en.md +608 -0
  22. package/guide/dsh-tui-guide/user-guide.md +586 -0
  23. package/guide/dsh-tui-guide/vscode.en.md +301 -0
  24. package/guide/dsh-tui-guide/vscode.md +272 -0
  25. package/lib/settings.json +1272 -0
  26. package/lib/types/adapter/channel/ui-policy.d.ts +10 -2
  27. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  28. package/lib/types/adapter/channel/ui-policy.js +17 -0
  29. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  30. package/lib/types/adapter/kernel/replay.js +2 -0
  31. package/lib/types/adapter/ports/channel-display.d.ts +12 -0
  32. package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
  33. package/lib/types/adapter/ports/channel-session.d.ts +38 -0
  34. package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
  35. package/lib/types/adapter/ports/channel-settings.d.ts +14 -1
  36. package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
  37. package/lib/types/adapter/ports/channel-ui.d.ts +75 -6
  38. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  39. package/lib/types/adapter/ports/channel-view.d.ts +86 -9
  40. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  41. package/lib/types/commands.d.ts.map +1 -1
  42. package/lib/types/commands.js +2 -0
  43. package/lib/types/components/BalanceReportRow.d.ts +10 -2
  44. package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
  45. package/lib/types/components/BalanceReportRow.js +18 -4
  46. package/lib/types/components/Chat/JobCard.d.ts +9 -0
  47. package/lib/types/components/Chat/JobCard.d.ts.map +1 -1
  48. package/lib/types/components/Chat/JobCard.js +42 -15
  49. package/lib/types/components/Chat/SubagentMessage.js +6 -6
  50. package/lib/types/components/CompactionStatusRow.d.ts +24 -0
  51. package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
  52. package/lib/types/components/CompactionStatusRow.js +72 -0
  53. package/lib/types/components/GoalTodoPanel.js +2 -2
  54. package/lib/types/components/HelpMenu.d.ts +2 -2
  55. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  56. package/lib/types/components/HelpMenu.js +5 -4
  57. package/lib/types/components/InlineMathParagraph.d.ts +22 -0
  58. package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
  59. package/lib/types/components/InlineMathParagraph.js +178 -0
  60. package/lib/types/components/JobsPanel.d.ts.map +1 -1
  61. package/lib/types/components/JobsPanel.js +80 -33
  62. package/lib/types/components/LogoV2.d.ts +41 -3
  63. package/lib/types/components/LogoV2.d.ts.map +1 -1
  64. package/lib/types/components/LogoV2.js +148 -24
  65. package/lib/types/components/Markdown.d.ts +10 -3
  66. package/lib/types/components/Markdown.d.ts.map +1 -1
  67. package/lib/types/components/Markdown.js +47 -14
  68. package/lib/types/components/MathBlock.d.ts +13 -0
  69. package/lib/types/components/MathBlock.d.ts.map +1 -0
  70. package/lib/types/components/MathBlock.js +136 -0
  71. package/lib/types/components/MessageList.d.ts +10 -1
  72. package/lib/types/components/MessageList.d.ts.map +1 -1
  73. package/lib/types/components/MessageList.js +16 -7
  74. package/lib/types/components/MigratePicker.d.ts +30 -0
  75. package/lib/types/components/MigratePicker.d.ts.map +1 -0
  76. package/lib/types/components/MigratePicker.js +38 -0
  77. package/lib/types/components/PresetPicker.d.ts +4 -0
  78. package/lib/types/components/PresetPicker.d.ts.map +1 -1
  79. package/lib/types/components/PresetPicker.js +5 -1
  80. package/lib/types/components/PromptInput.d.ts +17 -0
  81. package/lib/types/components/PromptInput.d.ts.map +1 -1
  82. package/lib/types/components/PromptInput.js +60 -8
  83. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  84. package/lib/types/components/SplitDiffView.js +2 -1
  85. package/lib/types/components/StarPrompt.d.ts +59 -0
  86. package/lib/types/components/StarPrompt.d.ts.map +1 -0
  87. package/lib/types/components/StarPrompt.js +326 -0
  88. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  89. package/lib/types/components/StreamingMarkdown.js +20 -3
  90. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  91. package/lib/types/components/SubagentCard.js +8 -8
  92. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
  93. package/lib/types/components/SubagentDetailScene.js +108 -10
  94. package/lib/types/components/TimelineRail.d.ts.map +1 -1
  95. package/lib/types/components/TimelineRail.js +9 -1
  96. package/lib/types/components/Whale.d.ts +17 -8
  97. package/lib/types/components/Whale.d.ts.map +1 -1
  98. package/lib/types/components/Whale.js +25 -15
  99. package/lib/types/components/WhaleGirl.d.ts +35 -0
  100. package/lib/types/components/WhaleGirl.d.ts.map +1 -0
  101. package/lib/types/components/WhaleGirl.js +50 -0
  102. package/lib/types/components/WorkingSpinner.d.ts +4 -1
  103. package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
  104. package/lib/types/components/WorkingSpinner.js +2 -2
  105. package/lib/types/components/bigfont.d.ts +47 -18
  106. package/lib/types/components/bigfont.d.ts.map +1 -1
  107. package/lib/types/components/bigfont.js +55 -40
  108. package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
  109. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  110. package/lib/types/components/design-system/ThemeProvider.js +40 -1
  111. package/lib/types/components/maidPortrait.d.ts +44 -0
  112. package/lib/types/components/maidPortrait.d.ts.map +1 -0
  113. package/lib/types/components/maidPortrait.js +178 -0
  114. package/lib/types/components/mathPreview.d.ts +25 -0
  115. package/lib/types/components/mathPreview.d.ts.map +1 -0
  116. package/lib/types/components/mathPreview.js +48 -0
  117. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  118. package/lib/types/components/messages/AssistantThinkingMessage.js +6 -5
  119. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  120. package/lib/types/components/messages/AssistantToolUseMessage.js +3 -2
  121. package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
  122. package/lib/types/components/messages/TranscriptImages.js +11 -1
  123. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
  124. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  125. package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
  126. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  127. package/lib/types/components/questions/PlanReviewPanel.js +3 -3
  128. package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
  129. package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
  130. package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
  131. package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
  132. package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
  133. package/lib/types/components/sessions/SourceTabs.js +70 -0
  134. package/lib/types/components/splashEggs.d.ts +56 -0
  135. package/lib/types/components/splashEggs.d.ts.map +1 -0
  136. package/lib/types/components/splashEggs.js +67 -0
  137. package/lib/types/components/splashFonts.d.ts +119 -0
  138. package/lib/types/components/splashFonts.d.ts.map +1 -0
  139. package/lib/types/components/splashFonts.js +267 -0
  140. package/lib/types/components/splashLayout.d.ts +41 -0
  141. package/lib/types/components/splashLayout.d.ts.map +1 -0
  142. package/lib/types/components/splashLayout.js +40 -0
  143. package/lib/types/components/trajectory/MiniWake.d.ts +11 -1
  144. package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -1
  145. package/lib/types/components/trajectory/MiniWake.js +9 -3
  146. package/lib/types/components/whaleGirlSprite.d.ts +17 -0
  147. package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
  148. package/lib/types/components/whaleGirlSprite.js +47 -0
  149. package/lib/types/deepseekPricing.d.ts +74 -0
  150. package/lib/types/deepseekPricing.d.ts.map +1 -1
  151. package/lib/types/deepseekPricing.js +110 -11
  152. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  153. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  154. package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
  155. package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -0
  156. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  157. package/lib/types/dsh-adapter/channel/background-action.js +1 -0
  158. package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -9
  159. package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
  160. package/lib/types/dsh-adapter/channel/binding-events.js +69 -21
  161. package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -1
  162. package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
  163. package/lib/types/dsh-adapter/channel/compaction.js +35 -2
  164. package/lib/types/dsh-adapter/channel/external-commands.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/channel/external-commands.js +8 -2
  166. package/lib/types/dsh-adapter/channel/job-projection.d.ts +1 -0
  167. package/lib/types/dsh-adapter/channel/job-projection.d.ts.map +1 -1
  168. package/lib/types/dsh-adapter/channel/job-projection.js +88 -3
  169. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  170. package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
  171. package/lib/types/dsh-adapter/channel/mode-actions.d.ts +13 -0
  172. package/lib/types/dsh-adapter/channel/mode-actions.d.ts.map +1 -1
  173. package/lib/types/dsh-adapter/channel/mode-actions.js +48 -7
  174. package/lib/types/dsh-adapter/channel/mode-permission-actions.d.ts.map +1 -1
  175. package/lib/types/dsh-adapter/channel/mode-permission-actions.js +25 -9
  176. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  177. package/lib/types/dsh-adapter/channel/model-switch.js +5 -1
  178. package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
  179. package/lib/types/dsh-adapter/channel/paths.js +7 -1
  180. package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
  181. package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
  182. package/lib/types/dsh-adapter/channel/preferences.js +31 -5
  183. package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
  184. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  185. package/lib/types/dsh-adapter/channel/projection.js +127 -17
  186. package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
  187. package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
  188. package/lib/types/dsh-adapter/channel/question-record.js +107 -0
  189. package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
  190. package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
  191. package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
  192. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +2 -0
  193. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  194. package/lib/types/dsh-adapter/channel/session-live-adoption.js +9 -3
  195. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
  196. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  197. package/lib/types/dsh-adapter/channel/session-metadata.js +39 -7
  198. package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
  199. package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
  200. package/lib/types/dsh-adapter/channel/session-reset.js +7 -0
  201. package/lib/types/dsh-adapter/channel/session-resume.d.ts +1 -0
  202. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  203. package/lib/types/dsh-adapter/channel/session-resume.js +4 -2
  204. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  205. package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
  206. package/lib/types/dsh-adapter/channel/state.d.ts +17 -2
  207. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  208. package/lib/types/dsh-adapter/channel/state.js +6 -1
  209. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +30 -35
  210. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
  211. package/lib/types/dsh-adapter/channel/subagent-projection.js +143 -4
  212. package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
  213. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  214. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  215. package/lib/types/dsh-adapter/channel.js +35 -5
  216. package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
  217. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
  218. package/lib/types/dsh-adapter/compat/messages.js +9 -0
  219. package/lib/types/dsh-adapter/contract.d.ts +6 -5
  220. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  221. package/lib/types/dsh-adapter/contract.js +14 -6
  222. package/lib/types/dsh-adapter/index.d.ts +36 -1
  223. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  224. package/lib/types/dsh-adapter/index.js +22 -6
  225. package/lib/types/dsh-adapter/jobs.d.ts +82 -16
  226. package/lib/types/dsh-adapter/jobs.d.ts.map +1 -1
  227. package/lib/types/dsh-adapter/jobs.js +104 -9
  228. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
  229. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
  230. package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
  231. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
  232. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
  233. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
  234. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
  235. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
  236. package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
  237. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
  238. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
  239. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
  240. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
  241. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
  242. package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
  243. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
  244. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
  245. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
  246. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
  247. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
  248. package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
  249. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
  250. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
  251. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
  252. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
  253. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
  254. package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
  255. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
  256. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
  257. package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
  258. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
  259. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
  260. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
  261. package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
  262. package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
  263. package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
  264. package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
  265. package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
  266. package/lib/types/dsh-adapter/migrate/browse.js +90 -0
  267. package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
  268. package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
  269. package/lib/types/dsh-adapter/migrate/cli.js +106 -0
  270. package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
  271. package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
  272. package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
  273. package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
  274. package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
  275. package/lib/types/dsh-adapter/migrate/index.js +107 -0
  276. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
  277. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
  278. package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
  279. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
  280. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
  281. package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
  282. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
  283. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
  284. package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
  285. package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
  286. package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
  287. package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
  288. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
  289. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
  290. package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
  291. package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
  292. package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
  293. package/lib/types/dsh-adapter/migrate/picker.js +86 -0
  294. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
  295. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
  296. package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
  297. package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
  298. package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
  299. package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
  300. package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
  301. package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
  302. package/lib/types/dsh-adapter/migrate/types.js +11 -0
  303. package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
  304. package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
  305. package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
  306. package/lib/types/dsh-adapter/oauth/bonus.d.ts +27 -0
  307. package/lib/types/dsh-adapter/oauth/bonus.d.ts.map +1 -0
  308. package/lib/types/dsh-adapter/oauth/bonus.js +69 -0
  309. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.d.ts +2 -1
  310. package/lib/types/dsh-adapter/oauth/command.d.ts.map +1 -0
  311. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.js +7 -4
  312. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.d.ts +13 -10
  313. package/lib/types/dsh-adapter/oauth/credentials.d.ts.map +1 -0
  314. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.js +61 -23
  315. package/lib/types/dsh-adapter/oauth/deepseek.d.ts +39 -0
  316. package/lib/types/dsh-adapter/oauth/deepseek.d.ts.map +1 -0
  317. package/lib/types/dsh-adapter/oauth/deepseek.js +189 -0
  318. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.d.ts +24 -16
  319. package/lib/types/dsh-adapter/oauth/index.d.ts.map +1 -0
  320. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.js +34 -20
  321. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/interaction.d.ts +14 -12
  322. package/lib/types/dsh-adapter/oauth/interaction.d.ts.map +1 -0
  323. package/lib/types/dsh-adapter/oauth/interaction.js +283 -0
  324. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.d.ts +2 -1
  325. package/lib/types/dsh-adapter/oauth/opener.d.ts.map +1 -0
  326. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.js +1 -1
  327. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.d.ts +10 -3
  328. package/lib/types/dsh-adapter/oauth/pi-ai.d.ts.map +1 -0
  329. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.js +8 -3
  330. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.d.ts +6 -3
  331. package/lib/types/dsh-adapter/oauth/profiles.d.ts.map +1 -0
  332. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.js +11 -3
  333. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.d.ts +14 -7
  334. package/lib/types/dsh-adapter/oauth/service.d.ts.map +1 -0
  335. package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.js +82 -17
  336. package/lib/types/dsh-adapter/plugin.d.ts +12 -3
  337. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  338. package/lib/types/dsh-adapter/plugin.js +215 -376
  339. package/lib/types/dsh-adapter/presets.d.ts +6 -4
  340. package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
  341. package/lib/types/dsh-adapter/presets.js +6 -4
  342. package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
  343. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  344. package/lib/types/dsh-adapter/providerWizard.js +260 -68
  345. package/lib/types/dsh-adapter/questions.d.ts +22 -15
  346. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  347. package/lib/types/dsh-adapter/questions.js +47 -45
  348. package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
  349. package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
  350. package/lib/types/dsh-adapter/sessions/digest.js +20 -13
  351. package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
  352. package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
  353. package/lib/types/dsh-adapter/sessions/frames.js +5 -4
  354. package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
  355. package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
  356. package/lib/types/dsh-adapter/sessions/list.js +188 -164
  357. package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
  358. package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
  359. package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
  360. package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
  361. package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
  362. package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
  363. package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
  364. package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
  365. package/lib/types/dsh-adapter/sessions/store.js +62 -25
  366. package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
  367. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
  368. package/lib/types/dsh-adapter/sideQuestion.js +98 -2
  369. package/lib/types/dsh-adapter/subagents.d.ts +29 -3
  370. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  371. package/lib/types/dsh-adapter/subagents.js +87 -3
  372. package/lib/types/herdr.d.ts +2 -0
  373. package/lib/types/herdr.d.ts.map +1 -1
  374. package/lib/types/herdr.js +9 -3
  375. package/lib/types/i18n.d.ts +598 -60
  376. package/lib/types/i18n.d.ts.map +1 -1
  377. package/lib/types/i18n.js +198 -31
  378. package/lib/types/ink/components/App.d.ts +2 -2
  379. package/lib/types/ink/components/App.d.ts.map +1 -1
  380. package/lib/types/ink/components/App.js +15 -2
  381. package/lib/types/ink/components/Image.d.ts +14 -1
  382. package/lib/types/ink/components/Image.d.ts.map +1 -1
  383. package/lib/types/ink/components/Image.js +2 -2
  384. package/lib/types/ink/events/input-event.js +3 -3
  385. package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
  386. package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
  387. package/lib/types/ink/hooks/use-terminal-images.js +13 -0
  388. package/lib/types/ink/ink.d.ts +6 -0
  389. package/lib/types/ink/ink.d.ts.map +1 -1
  390. package/lib/types/ink/ink.js +16 -1
  391. package/lib/types/ink/kitty-graphics.d.ts +44 -3
  392. package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
  393. package/lib/types/ink/kitty-graphics.js +184 -23
  394. package/lib/types/ink/output.d.ts +24 -2
  395. package/lib/types/ink/output.d.ts.map +1 -1
  396. package/lib/types/ink/output.js +83 -5
  397. package/lib/types/ink/parse-keypress.d.ts +61 -1
  398. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  399. package/lib/types/ink/parse-keypress.js +764 -93
  400. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  401. package/lib/types/ink/render-node-to-output.js +8 -1
  402. package/lib/types/ink/screen.d.ts +24 -0
  403. package/lib/types/ink/screen.d.ts.map +1 -1
  404. package/lib/types/ink/screen.js +89 -0
  405. package/lib/types/ink/selection.d.ts +40 -18
  406. package/lib/types/ink/selection.d.ts.map +1 -1
  407. package/lib/types/ink/selection.js +142 -30
  408. package/lib/types/ink/sixel-codec.d.ts +12 -1
  409. package/lib/types/ink/sixel-codec.d.ts.map +1 -1
  410. package/lib/types/ink/sixel-codec.js +29 -5
  411. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  412. package/lib/types/ink/sixel-graphics.js +5 -3
  413. package/lib/types/ink/styles.d.ts +9 -0
  414. package/lib/types/ink/styles.d.ts.map +1 -1
  415. package/lib/types/ink/terminal-image.d.ts +8 -0
  416. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  417. package/lib/types/ink/terminal-querier.d.ts +32 -1
  418. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  419. package/lib/types/ink/terminal-querier.js +54 -2
  420. package/lib/types/ink/timeline-rail.d.ts +5 -0
  421. package/lib/types/ink/timeline-rail.d.ts.map +1 -1
  422. package/lib/types/ink/update-overflow-guard.d.ts +24 -0
  423. package/lib/types/ink/update-overflow-guard.d.ts.map +1 -1
  424. package/lib/types/ink/update-overflow-guard.js +25 -3
  425. package/lib/types/math/inline-layout.d.ts +29 -0
  426. package/lib/types/math/inline-layout.d.ts.map +1 -0
  427. package/lib/types/math/inline-layout.js +106 -0
  428. package/lib/types/math/layout.d.ts +58 -0
  429. package/lib/types/math/layout.d.ts.map +1 -0
  430. package/lib/types/math/layout.js +59 -0
  431. package/lib/types/math/renderer.d.ts +64 -0
  432. package/lib/types/math/renderer.d.ts.map +1 -0
  433. package/lib/types/math/renderer.js +256 -0
  434. package/lib/types/minimalUiMode.d.ts +19 -0
  435. package/lib/types/minimalUiMode.d.ts.map +1 -0
  436. package/lib/types/minimalUiMode.js +23 -0
  437. package/lib/types/oauth.d.ts +5 -10
  438. package/lib/types/oauth.d.ts.map +1 -1
  439. package/lib/types/oauth.js +5 -10
  440. package/lib/types/screens/Chat.d.ts +17 -1
  441. package/lib/types/screens/Chat.d.ts.map +1 -1
  442. package/lib/types/screens/Chat.js +627 -54
  443. package/lib/types/screens/SessionSupervisor.d.ts +2 -1
  444. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
  445. package/lib/types/screens/SessionSupervisor.js +156 -19
  446. package/lib/types/screens/Settings.d.ts.map +1 -1
  447. package/lib/types/screens/Settings.js +49 -11
  448. package/lib/types/screens/StatusLine.d.ts +4 -0
  449. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  450. package/lib/types/screens/StatusLine.js +57 -27
  451. package/lib/types/screens/chatOverlay.d.ts +5 -0
  452. package/lib/types/screens/chatOverlay.d.ts.map +1 -1
  453. package/lib/types/screens/chatOverlay.js +1 -0
  454. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
  455. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
  456. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
  457. package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
  458. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
  459. package/lib/types/screens/sessionSupervisor/model.js +26 -0
  460. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
  461. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
  462. package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
  463. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
  464. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
  465. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
  466. package/lib/types/sessionHistory.d.ts +2 -2
  467. package/lib/types/sessionHistory.d.ts.map +1 -1
  468. package/lib/types/sessionHistory.js +31 -5
  469. package/lib/types/settings/definitions.d.ts +681 -0
  470. package/lib/types/settings/definitions.d.ts.map +1 -0
  471. package/lib/types/settings/definitions.js +511 -0
  472. package/lib/types/starAction.d.ts +44 -0
  473. package/lib/types/starAction.d.ts.map +1 -0
  474. package/lib/types/starAction.js +52 -0
  475. package/lib/types/terminal-utils/latex.d.ts +10 -0
  476. package/lib/types/terminal-utils/latex.d.ts.map +1 -0
  477. package/lib/types/terminal-utils/latex.js +1417 -0
  478. package/lib/types/terminal-utils/markdown.d.ts +3 -1
  479. package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
  480. package/lib/types/terminal-utils/markdown.js +26 -1
  481. package/lib/types/terminal-utils/math.d.ts +66 -0
  482. package/lib/types/terminal-utils/math.d.ts.map +1 -0
  483. package/lib/types/terminal-utils/math.js +337 -0
  484. package/lib/types/tips.d.ts.map +1 -1
  485. package/lib/types/tips.js +16 -4
  486. package/lib/types/tuiDisplayPrefs.d.ts +67 -0
  487. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  488. package/lib/types/tuiDisplayPrefs.js +59 -0
  489. package/lib/types/ui.d.ts +1 -1
  490. package/lib/types/ui.d.ts.map +1 -1
  491. package/lib/types/ui.js +1 -1
  492. package/lib/types/update.js +2 -2
  493. package/lib/types/usageStats.d.ts +98 -0
  494. package/lib/types/usageStats.d.ts.map +1 -0
  495. package/lib/types/usageStats.js +169 -0
  496. package/lib/types/utils/bmp.d.ts +17 -0
  497. package/lib/types/utils/bmp.d.ts.map +1 -0
  498. package/lib/types/utils/bmp.js +154 -0
  499. package/lib/types/utils/clipboard.d.ts +14 -2
  500. package/lib/types/utils/clipboard.d.ts.map +1 -1
  501. package/lib/types/utils/clipboard.js +143 -8
  502. package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
  503. package/lib/types/utils/fold-long-lines.js +2 -1
  504. package/lib/types/utils/keymap.d.ts +4 -1
  505. package/lib/types/utils/keymap.d.ts.map +1 -1
  506. package/lib/types/utils/keymap.js +8 -0
  507. package/lib/types/utils/modifiers.d.ts +4 -3
  508. package/lib/types/utils/modifiers.d.ts.map +1 -1
  509. package/lib/types/utils/modifiers.js +4 -3
  510. package/lib/types/utils/pastedImagePath.d.ts +8 -0
  511. package/lib/types/utils/pastedImagePath.d.ts.map +1 -1
  512. package/lib/types/utils/pastedImagePath.js +29 -5
  513. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
  514. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
  515. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
  516. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
  517. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
  518. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
  519. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
  520. package/package.json +127 -102
  521. package/presets/liangshen/agent.cordis.yml +4 -1
  522. package/presets/liangshen/preset.yml +1 -1
  523. package/lib/types/minimalMode.d.ts +0 -13
  524. package/lib/types/minimalMode.d.ts.map +0 -1
  525. package/lib/types/minimalMode.js +0 -17
  526. package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +0 -21
  527. package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +0 -143
  528. package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +0 -11
  529. package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +0 -44
  530. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +0 -193
  531. package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +0 -69
@@ -35,7 +35,7 @@ import { readHomePrefs } from '../homePrefs.js';
35
35
  import { resolveSessionCwd } from '../utils/workspaceRoot.js';
36
36
  import { beginRestartAttempt, checkForTuiUpdate, installedTuiVersion, isBootDeadlockTarget, isStandaloneRuntime, isVersionNewer, logRestartEvent, resolveDshProfileName, resolveTuiUpdateTarget, restartTui, updateTuiAndRestart, writeHandoffNotice } from '../update.js';
37
37
  import { getLang, isLang, resolveStartupLang, setLang, t, writeLangPref } from '../i18n.js';
38
- import { DEFAULT_PAGE_MARGIN, DEFAULT_STATUS_BAR, applyMermaidDiagrams, applyPageMargin, isPageMarginMode, normalizePageMargin, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground, parsePageMarginSpec } from '../tuiDisplayPrefs.js';
38
+ import { DEFAULT_PAGE_MARGIN, DEFAULT_STATUS_BAR, applyImageBacking, applyMathImageBacking, applyMathImageScale, applyMathRendering, applyMermaidDiagrams, applyPageMargin, isPageMarginMode, normalizePageMargin, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground, parsePageMarginSpec, resolveMathRendering } from '../tuiDisplayPrefs.js';
39
39
  import { draftComboConflicts, effectiveComboString, parseComboDraft, setKeymapOverrides, SHORTCUT_ACTIONS, } from '../utils/keymap.js';
40
40
  import { attachHerdrIntegration } from '../herdr.js';
41
41
  import { logMouseDebug } from '../utils/debug.js';
@@ -55,10 +55,13 @@ import { getHostSettingsSections, getLocalSettingsSectionsHost } from './setting
55
55
  import { compositionRoot, withHostRootCapability } from './host-access.js';
56
56
  import { render, ThemeProvider, AlternateScreen } from '../ui.js';
57
57
  import { PageMargin } from '../components/PageMargin.js';
58
+ import { normalizeSplashFont } from '../components/splashFonts.js';
59
+ import { SETTING_GROUPS, SHORTCUT_FIELD_META, settingField } from '../settings/definitions.js';
58
60
  import instances from '../ink/instances.js';
59
61
  import { cursorMove, DISABLE_KITTY_KEYBOARD, DISABLE_MODIFY_OTHER_KEYS, DISABLE_WIN32_INPUT_MODE } from '../ink/termio/csi.js';
60
62
  import { DBP, DFE, DISABLE_MOUSE_TRACKING, EXIT_ALT_SCREEN, SHOW_CURSOR } from '../ink/termio/dec.js';
61
63
  import { CLEAR_ITERM2_PROGRESS, CLEAR_TAB_STATUS, supportsTabStatus, wrapForMultiplexer } from '../ink/termio/osc.js';
64
+ import { fatalReasonForExit, registerProcessGuardFatalSink } from '../ink/update-overflow-guard.js';
62
65
  /**
63
66
  * Interactive TUI front door for DeepSeek Harness agents.
64
67
  *
@@ -84,8 +87,10 @@ let lastBootedFullscreen;
84
87
  // Image preferences also stay fixed across host recomposes until /restart.
85
88
  let lastBootedTerminalImages;
86
89
  /**
87
- * Extract the startup prompt from raw app argv. `--resume <session>` selects
88
- * a persisted session and must not leak its id into the conversation.
90
+ * Extract the startup prompt from raw app argv, excluding session selectors
91
+ * and Web startup flag values. `--trusted-host` consumes multiple authorities
92
+ * up to the next flag; none of them are prompt text (issue #882). An app-level
93
+ * `--` ends flag parsing; all following tokens are literal prompt text.
89
94
  */
90
95
  export function initialPromptFromCmdlineArgs(args) {
91
96
  if (args === undefined)
@@ -93,11 +98,20 @@ export function initialPromptFromCmdlineArgs(args) {
93
98
  const promptArgs = [];
94
99
  for (let i = 0; i < args.length; i += 1) {
95
100
  const arg = args[i];
96
- if (arg === '--resume') {
101
+ if (arg === '--') {
102
+ promptArgs.push(...args.slice(i + 1));
103
+ break;
104
+ }
105
+ if (arg === '--resume' || arg === '--host' || arg === '--port') {
97
106
  if (args[i + 1] !== undefined && !args[i + 1].startsWith('-'))
98
107
  i += 1;
99
108
  continue;
100
109
  }
110
+ if (arg === '--trusted-host') {
111
+ while (args[i + 1] !== undefined && !args[i + 1].startsWith('-'))
112
+ i += 1;
113
+ continue;
114
+ }
101
115
  if (arg.startsWith('--resume='))
102
116
  continue;
103
117
  if (arg.startsWith('-'))
@@ -261,10 +275,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
261
275
  const userQuestions = ctx.get('userQuestions') ?? new UserQuestionService(ctx);
262
276
  ctx.plugin(toolAskUser);
263
277
  // The host-level tool mount above is intentional for the TUI and for user
264
- // presets, but the official Minimal preset is a strict two-tool trajectory
265
- // (persistent bash + str_replace_editor). Filter only that preset at the
266
- // final assembly boundary. Reading the session on every assembly also makes
267
- // blank-session /preset switches and resumed sessions behave correctly.
278
+ // presets, but the official Minimal preset is a single-tool trajectory (one
279
+ // persistent shell: bash on POSIX, pwsh on Windows). Filter only that preset
280
+ // at the final assembly boundary. Reading the session on every assembly also
281
+ // makes blank-session /preset switches and resumed sessions behave correctly.
268
282
  ctx.on('system-prompt/assemble', async (_assembly, context, next) => {
269
283
  const assembled = await next();
270
284
  const presetId = context.agent === undefined ? undefined : runningPresetOf(context.agent.session);
@@ -400,8 +414,11 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
400
414
  const meta = { cwd: sessionCwd };
401
415
  // Launch-time resume target: the env handoff (launchers like naive-dsh) wins;
402
416
  // `dsh --profile tui` forwards `--resume` verbatim instead, so fall back to
403
- // parsing the forwarded app args (matching the standalone bin).
404
- const launchSessionId = config.sessionId ?? resumeTargetFromArgv(process.argv.slice(2));
417
+ // the same app-argv snapshot as the initial prompt. Raw process.argv also
418
+ // contains the DSH launcher's own -- and is only a legacy embedder fallback.
419
+ const cmdline = ctx.cmdlineArgs;
420
+ const cmdlineArgs = cmdline?.get?.() ?? cmdline?.args;
421
+ const launchSessionId = config.sessionId ?? resumeTargetFromArgv(cmdlineArgs ?? process.argv.slice(2));
405
422
  const { agent, handle, agentPreset, route: createdRoute } = await resolveAgent(ctx, launchSessionId, configuredRoute, startupRoute, meta, config.preset);
406
423
  try {
407
424
  // Opening a persisted TUI session is an explicit ownership action too.
@@ -415,7 +432,20 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
415
432
  // reads the same records. There is deliberately no rail-side "add a
416
433
  // workspace" control any more: a terminal's launch directory is the whole
417
434
  // registration story.
418
- const attached = await attachSessionToWorkspace(ctx, meta.cwd, agent.session.id);
435
+ //
436
+ // A RESUMED session is accounted where its OWN header cwd lives, never
437
+ // where this terminal was launched. The launch directory can be an
438
+ // ANCESTOR of the resumed session's: launching in `~/projects` and
439
+ // resuming a session recorded in `~/projects/app` accounts the same
440
+ // session in both workspaces, and the next boot dies inside
441
+ // `validateStoredState` ("session ... is accounted by both workspace
442
+ // ..."), which leaves `workspaceRegistry` unactivated and the whole TUI
443
+ // pending forever. Ownership must therefore agree with the `cwd:` handed
444
+ // to `createChannel` below, which already prefers the persisted header.
445
+ // Fresh sessions record `meta.cwd` at creation, so the launch directory
446
+ // still registers through them.
447
+ const ownershipCwd = agent.session.header.cwd ?? meta.cwd;
448
+ const attached = await attachSessionToWorkspace(ctx, ownershipCwd, agent.session.id);
419
449
  if (!attached) {
420
450
  ctx.logger.warn(`dsh-tui: session "${agent.session.id}" has no workspace ownership because workspaceRegistry is not mounted`);
421
451
  }
@@ -442,6 +472,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
442
472
  // line attaches nothing at all — no feed, no 500ms tick.
443
473
  const activityStore = createActivityStore(ctx, config.activity !== false);
444
474
  const rawChannel = createChannel(ctx, agent, {
475
+ // The namespace this boot actually registered the settings section under
476
+ // (the Config owner's Loader id; custom ids are supported). Chat and the
477
+ // channel's own settings reads look the section up by it.
478
+ settingsNs: tuiSettingsNs,
445
479
  model: displayRoute.model,
446
480
  // The activity projection only pushes on change; read the current value as
447
481
  // soon as this session binds so a resumed or reattached session renders its
@@ -489,6 +523,12 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
489
523
  expandEditor: config.expandEditor,
490
524
  smoothStreaming: config.smoothStreaming,
491
525
  statusBar: config.statusBar,
526
+ // 启动种子:与上面各显示偏好同款(设置服务的 boot apply 会再对一次
527
+ // 值,setWhaleGirl 对同值是 no-op,不会多通知)。
528
+ whaleGirl: config.whaleGirl,
529
+ // 开屏大字字体:cordis.yml 这一层的值(未设置时 undefined → 通道归一化成
530
+ // `daily`);/settings 的改动由 applySplashFont 实时接上。
531
+ splashFont: config.splashFont,
492
532
  handle,
493
533
  });
494
534
  // Register the live Channel for the adapter Kernel. The Channel driver
@@ -521,10 +561,14 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
521
561
  // the channel version bump (which re-renders everything below Chat)
522
562
  // cannot drive it. Seed the store from config before the tree mounts;
523
563
  // applyDisplay below mirrors every settings change into it live. The
524
- // mermaid switch rides the same kind of store (Markdown is memoized by
525
- // content, so no prop reaches the diagram component).
564
+ // mermaid and LaTeX switches ride the same kind of store (Markdown is
565
+ // memoized by content, so no prop reaches the diagram/formula nodes).
526
566
  applyPageMargin(config.pageMargin);
527
567
  applyMermaidDiagrams(config.mermaidDiagrams);
568
+ applyMathRendering(resolveMathRendering({}, config));
569
+ applyMathImageScale(config.mathImageScale ?? 'auto');
570
+ applyMathImageBacking(config.mathImageBacking ?? 'transparent');
571
+ applyImageBacking(config.imageBacking ?? 'transparent');
528
572
  // Plugin toasts ride the channel's own notification surface: the runtime
529
573
  // already sanitized/rate-limited the delivery, the sink only forwards.
530
574
  // Without the extensions row (tuiToast absent) plugin toasts are dropped
@@ -591,6 +635,16 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
591
635
  smoothStreaming: Schema.boolean(),
592
636
  // Same no-default rule: applyDisplay resolves `?? config.mermaidDiagrams ?? true`.
593
637
  mermaidDiagrams: Schema.boolean(),
638
+ // Same no-default rule: resolveMathRendering falls back to cordis.yml.
639
+ mathRendering: Schema.union(['auto', 'image', 'unicode', 'source']),
640
+ // Display-formula image size; unset keeps the base (text) scale.
641
+ mathImageScale: Schema.union(['auto', 'large', 'xlarge']),
642
+ // Formula-image backing; unset keeps the transparent default.
643
+ mathImageBacking: Schema.union(['transparent', 'terminal']),
644
+ // Transcript-image backing (photos); unset keeps the transparent default.
645
+ imageBacking: Schema.union(['transparent', 'terminal']),
646
+ // Pre-`mathRendering` user layers; `false` still resolves to `source`.
647
+ latexMath: Schema.boolean(),
594
648
  // No default on purpose: unset keeps the boot chain decisive
595
649
  // (applyEffortDefault hands `undefined` to channel.setDefaultEffort,
596
650
  // which resolves cordis.yml `effort` → effort.json → adapter default).
@@ -620,8 +674,19 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
620
674
  // the idle-wakeup gate stays: an explicit `false` keeps the settled
621
675
  // header timer-free.
622
676
  whaleIdle: Schema.boolean().default(true),
623
- // Minimal mode: strips the header splash, emoji glyphs, and
624
- // decorative colors; code highlight and tool colors stay.
677
+ // Maid portrait instead of the pixel whale in the header splash;
678
+ // off by default — the portrait is static (no idle animation).
679
+ whaleGirl: Schema.boolean().default(false),
680
+ // No schema default (same rule as foldTerminalCommand below): a
681
+ // default here would come back from scope.get()/watch() and shadow an
682
+ // explicit cordis.yml `splashFont` while the user layer is unset.
683
+ // applySplashFont resolves `?? config.splashFont` and normalizes it
684
+ // (undefined → daily), so cordis.yml stays decisive and junk lands on
685
+ // daily.
686
+ splashFont: Schema.string(),
687
+ // Minimal UI (极简界面, settings key `minimal` — never renamed): strips
688
+ // the header splash, emoji glyphs, and decorative colors; code highlight
689
+ // and tool colors stay. Unrelated to the kernel agent preset `minimal`.
625
690
  minimal: Schema.boolean().default(false),
626
691
  // No default on purpose: an unset `lang` keeps the field showing
627
692
  // the effective language (see the section's format below) and lets
@@ -653,10 +718,23 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
653
718
  const applyWhaleIdle = (value) => {
654
719
  channel.setWhaleIdle(value.whaleIdle ?? true);
655
720
  };
656
- const applyMinimal = (value) => {
721
+ /** Apply the maid-portrait setting: live-swap the header art. */
722
+ const applyWhaleGirl = (value) => {
723
+ channel.setWhaleGirl(value.whaleGirl ?? false);
724
+ };
725
+ /** 开屏大字字体(`dsh-tui.splashFont`):`daily` 按本地日期轮换,其余 pin
726
+ * 住一款;设置用户层优先于 cordis.yml,非法值回落 `daily`。 */
727
+ const applySplashFont = (value) => {
728
+ if (shadow)
729
+ return;
730
+ channel.setSplashFont(normalizeSplashFont(value.splashFont ?? config.splashFont));
731
+ };
732
+ const applyMinimalUi = (value) => {
657
733
  if (shadow)
658
734
  return;
659
- channel.setMinimal(value.minimal ?? false);
735
+ // `value.minimal` is the persisted settings key (never renamed); the
736
+ // channel member is the minimal-UI flag, NOT the kernel preset.
737
+ channel.setMinimalUi(value.minimal ?? false);
660
738
  };
661
739
  // Renderer settings are resolved before mount; later edits wait for restart.
662
740
  const applyRendererSettings = (value) => {
@@ -697,6 +775,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
697
775
  channel.setExpandEditor(value.expandEditor ?? config.expandEditor ?? true);
698
776
  channel.setSmoothStreaming(value.smoothStreaming ?? config.smoothStreaming ?? true);
699
777
  applyMermaidDiagrams(value.mermaidDiagrams ?? config.mermaidDiagrams);
778
+ applyMathRendering(resolveMathRendering(value, config));
779
+ applyMathImageScale(value.mathImageScale ?? config.mathImageScale ?? 'auto');
780
+ applyMathImageBacking(value.mathImageBacking ?? config.mathImageBacking ?? 'transparent');
781
+ applyImageBacking(value.imageBacking ?? config.imageBacking ?? 'transparent');
700
782
  channel.setStatusBar(normalizeStatusBar(value.statusBar ?? config.statusBar));
701
783
  };
702
784
  // Legacy user scopes layer over cordis.yml. Modern Config is already
@@ -735,7 +817,9 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
735
817
  applyLayout(next);
736
818
  applyWhale(next);
737
819
  applyWhaleIdle(next);
738
- applyMinimal(next);
820
+ applyWhaleGirl(next);
821
+ applySplashFont(next);
822
+ applyMinimalUi(next);
739
823
  applyLang(next);
740
824
  applyDisplay(next);
741
825
  applyEffortDefault(next);
@@ -789,80 +873,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
789
873
  // one or more ctrl+/alt+ combos (comma-separated); blank restores the
790
874
  // default, and a combo another action or a fixed editor binding already
791
875
  // owns is refused as invalid so remaps can never silently shadow.
792
- const shortcutFieldMeta = {
793
- paste: {
794
- label: 'Paste shortcut',
795
- zh: '粘贴快捷键',
796
- hintEn: d => `Clipboard paste (text, file paths, images). Default: ${d}. Alt+V works where the terminal eats Ctrl+V.`,
797
- hintZh: d => `剪贴板粘贴(文本、文件路径、图片)。默认 ${d}。终端吞掉 Ctrl+V 时可用 Alt+V。`,
798
- },
799
- history: {
800
- label: 'History search shortcut',
801
- zh: '历史搜索快捷键',
802
- hintEn: d => `Open the prompt-history search. Default: ${d}.`,
803
- hintZh: d => `打开输入历史搜索。默认 ${d}。`,
804
- },
805
- editor: {
806
- label: 'External editor shortcut',
807
- zh: '外部编辑器快捷键',
808
- hintEn: d => `Edit the draft in $VISUAL/$EDITOR. Default: ${d}.`,
809
- hintZh: d => `在 $VISUAL/$EDITOR 外部编辑器中编辑草稿。默认 ${d}。`,
810
- },
811
- transcript: {
812
- label: 'Transcript mode shortcut',
813
- zh: '转录模式快捷键',
814
- hintEn: d => `Toggle expanded transcript mode. Default: ${d}.`,
815
- hintZh: d => `切换展开转录模式。默认 ${d}。`,
816
- },
817
- trajectory: {
818
- label: 'Trajectory scene shortcut',
819
- zh: '轨迹场景快捷键',
820
- hintEn: d => `Open the trajectory scene. Default: ${d}.`,
821
- hintZh: d => `打开轨迹场景。默认 ${d}。`,
822
- },
823
- dashboard: {
824
- label: 'Subagent dashboard shortcut',
825
- zh: '子代理面板快捷键',
826
- hintEn: d => `Open the subagent dashboard. Default: ${d}.`,
827
- hintZh: d => `打开子代理面板。默认 ${d}。`,
828
- },
829
- contextPanel: {
830
- label: 'Loaded-context panel shortcut',
831
- zh: '加载上下文面板快捷键',
832
- hintEn: d => `Toggle the startup loaded-context panel. Default: ${d}.`,
833
- hintZh: d => `切换启动时的已加载上下文面板。默认 ${d}。`,
834
- },
835
- showAll: {
836
- label: 'Show-all shortcut',
837
- zh: '显示全部消息快捷键',
838
- hintEn: d => `Toggle show-all-messages. Default: ${d}.`,
839
- hintZh: d => `切换显示全部消息。默认 ${d}。`,
840
- },
841
- redraw: {
842
- label: 'Redraw shortcut',
843
- zh: '终端重绘快捷键',
844
- hintEn: d => `Clear and repaint the terminal. Default: ${d}.`,
845
- hintZh: d => `清空并重绘终端。默认 ${d}。`,
846
- },
847
- todoFold: {
848
- label: 'Todo fold shortcut',
849
- zh: '待办折叠快捷键',
850
- hintEn: d => `Fold/unfold the goal/todo panel. Default: ${d}.`,
851
- hintZh: d => `折叠/展开目标与待办面板。默认 ${d}。`,
852
- },
853
- questionFold: {
854
- label: 'Question panel fold shortcut',
855
- zh: '提问面板折叠快捷键',
856
- hintEn: d => `Fold/unfold the pending question panel. Default: ${d}.`,
857
- hintZh: d => `折叠/展开等待回答的提问面板。默认 ${d}。`,
858
- },
859
- expandEditor: {
860
- label: 'Fullscreen editor shortcut',
861
- zh: '全屏草稿编辑快捷键',
862
- hintEn: d => `Toggle the fullscreen draft editor (Enter inserts a newline, Ctrl+Enter sends). Default: ${d}.`,
863
- hintZh: d => `切换全屏草稿编辑器(Enter 换行、Ctrl+Enter 发送)。默认 ${d}。`,
864
- },
865
- };
876
+ const shortcutFieldMeta = SHORTCUT_FIELD_META;
866
877
  const shortcutFields = SHORTCUT_ACTIONS.map(action => {
867
878
  const meta = shortcutFieldMeta[action.id];
868
879
  const defaults = action.defaults.join(', ');
@@ -900,23 +911,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
900
911
  const unregister = settingsSections.register({
901
912
  ns: tuiSettingsNs,
902
913
  title: 'dsh-tui',
903
- groups: [
904
- { id: 'status-bar', title: 'Status bar', descriptions: { zh: '底栏设置' } },
905
- { id: 'shortcuts', title: 'Shortcuts', descriptions: { zh: '快捷键' } },
906
- { id: 'session', title: 'Session', descriptions: { zh: '会话' } },
907
- ],
914
+ groups: [...SETTING_GROUPS],
908
915
  fields: [
909
916
  {
910
- path: ['lang'],
911
- label: 'Language',
912
- descriptions: { zh: '界面语言' },
913
- hint: 'UI language for the whole interface — applies immediately and is saved.',
914
- hintDescriptions: { zh: '整个界面的显示语言——立即生效并保存。' },
915
- kind: 'select',
916
- options: [
917
- { value: 'zh', label: '中文', descriptions: { zh: '中文' } },
918
- { value: 'en', label: 'English', descriptions: { zh: '英文' } },
919
- ],
917
+ ...settingField('lang'),
920
918
  format(value) {
921
919
  // Unset in settings.yaml: show the effective UI language
922
920
  // (env / cordis.yml / lang.json resolution) instead of a
@@ -925,15 +923,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
925
923
  },
926
924
  },
927
925
  {
928
- path: ['fullscreen'],
929
- label: 'Fullscreen mode',
930
- descriptions: { zh: '全屏模式' },
931
- // 故意不用 "alt-screen" 这类终端术语:读者要的是行为差异。鼠标
932
- // 两种模式都可用(整屏页面自带鼠标跟踪),别让描述暗示关掉就
933
- // 没有鼠标——最常见的误解。长度对齐既有最长 hint(单行假设)。
934
- hint: 'On: app takes the whole screen (vim/less style), in-app mouse. Off: native scrollback; full-page screens keep the mouse. Restart to apply.',
935
- hintDescriptions: { zh: '开启:接管整个终端(同 vim/less),应用内鼠标;关闭:终端原生滚动选择;整屏页两种模式都有鼠标。重启生效。' },
936
- kind: 'boolean',
926
+ ...settingField('fullscreen'),
937
927
  format(value) {
938
928
  // Unset in settings.yaml: show what THIS session booted with
939
929
  // (the cordis.yml resolution) instead of a misleading false.
@@ -941,7 +931,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
941
931
  },
942
932
  },
943
933
  {
944
- path: ['terminalImages'],
934
+ ...settingField('terminalImages'),
945
935
  label: terminalImagesDisabledByEnv ? 'Image previews (forced off)' : 'Terminal image previews',
946
936
  descriptions: { zh: terminalImagesDisabledByEnv ? '图片预览(环境强制关闭)' : '终端图片预览' },
947
937
  hint: terminalImagesDisabledByEnv
@@ -952,77 +942,26 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
952
942
  ? '勾选框保存预览偏好;移除 DSH_TUI_DISABLE_TERMINAL_IMAGES 后重新启动才能显示图片。'
953
943
  : '在支持的终端中预览图片。修改后用 /restart 生效;不影响向模型发送图片。',
954
944
  },
955
- kind: 'boolean',
956
945
  format(value) {
957
946
  // The editor toggles this value; runtime overrides must not replace the preference.
958
947
  return String(value ?? config.terminalImages ?? true);
959
948
  },
960
949
  },
961
950
  {
962
- path: ['diffLayout'],
963
- label: 'Diff layout',
964
- descriptions: { zh: 'diff 布局' },
965
- hint: 'Edit/Write tool cards: auto picks by terminal width, or force one layout.',
966
- hintDescriptions: { zh: 'Edit/Write 工具卡的 diff 呈现:auto 按终端宽度选择,或强制一种布局。' },
967
- kind: 'select',
968
- options: [
969
- { value: 'auto', label: 'Auto (by width)', descriptions: { zh: '自动(按宽度)' } },
970
- { value: 'split', label: 'Side-by-side', descriptions: { zh: '双栏对照' } },
971
- { value: 'unified', label: 'Unified', descriptions: { zh: '统一式' } },
972
- ],
951
+ ...settingField('diffLayout'),
973
952
  },
974
953
  {
975
- path: ['thinkingFold'],
976
- label: 'Thinking display',
977
- descriptions: { zh: '思考块展示' },
978
- hint: 'Preview shows 2-3 live lines; Full stays expanded until turn end. Click a streaming block to switch between preview and full.',
979
- hintDescriptions: { zh: '预览模式显示 2-3 行动态思考;展开模式保持至轮末。点击流式思考块可在预览与全文间切换。' },
980
- kind: 'select',
981
- options: [
982
- { value: 'preview', label: 'Preview (2-3 lines)', descriptions: { zh: '预览(2-3 行)' } },
983
- { value: 'full', label: 'Full until turn end', descriptions: { zh: '展开至轮末' } },
984
- ],
954
+ ...settingField('thinkingFold'),
985
955
  },
986
956
  {
987
- path: ['toolBackground'],
988
- label: 'Tool background',
989
- descriptions: { zh: '工具卡背景' },
990
- hint: 'Choose whether tool-call cards add no, subtle, or strong background emphasis.',
991
- hintDescriptions: { zh: '选择工具调用卡片不添加、轻微或明显的背景强调。' },
992
- kind: 'select',
993
- options: [
994
- { value: 'none', label: 'None', descriptions: { zh: '无' } },
995
- { value: 'subtle', label: 'Subtle', descriptions: { zh: '轻微' } },
996
- { value: 'strong', label: 'Strong', descriptions: { zh: '明显' } },
997
- ],
957
+ ...settingField('toolBackground'),
998
958
  },
999
959
  {
1000
- path: ['scrollGutter'],
1001
- label: 'Transcript gutter',
1002
- descriptions: { zh: '转录边栏' },
1003
- hint: 'Right gutter of the fullscreen transcript: per-turn timeline ticks, a proportional scrollbar, or nothing.',
1004
- hintDescriptions: { zh: '全屏转录区右侧边栏:按轮次的时间线节点、比例滚动条,或留空。' },
1005
- kind: 'select',
1006
- options: [
1007
- { value: 'timeline', label: 'Turn timeline', descriptions: { zh: '轮次时间线' } },
1008
- { value: 'scrollbar', label: 'Scrollbar', descriptions: { zh: '滚动条' } },
1009
- { value: 'hidden', label: 'Hidden', descriptions: { zh: '隐藏' } },
1010
- ],
960
+ ...settingField('scrollGutter'),
1011
961
  },
1012
962
  {
1013
- path: ['pageMargin'],
1014
- label: 'Page margin',
1015
- descriptions: { zh: '页边距' },
1016
- hint: 'Inset the whole UI from the terminal edges. ←/→ cycles presets (none / slim / normal / roomy); Enter types a custom spec `NxM`: N columns per side, M rows top/bottom (e.g. 3x1, max 8x4; a bare `N` keeps rows at 1). Empty resets to the default `normal`. Applies immediately.',
1017
- hintDescriptions: { zh: '让整个界面相对终端四边内缩。←/→ 循环预设(none / slim / normal / roomy);Enter 输入自定义 `NxM`:左右各 N 列、上下各 M 行(如 3x1,上限 8x4;只填 N 则上下保持 1 行)。清空恢复默认 normal。立即生效。' },
1018
- kind: 'text',
963
+ ...settingField('pageMargin'),
1019
964
  placeholder: 'normal',
1020
- options: [
1021
- { value: 'none', label: 'None', descriptions: { zh: '无' } },
1022
- { value: 'slim', label: 'Slim', descriptions: { zh: '窄' } },
1023
- { value: 'normal', label: 'Normal', descriptions: { zh: '常规' } },
1024
- { value: 'roomy', label: 'Roomy', descriptions: { zh: '宽' } },
1025
- ],
1026
965
  format(value) {
1027
966
  return String(value ?? config.pageMargin ?? DEFAULT_PAGE_MARGIN);
1028
967
  },
@@ -1037,12 +976,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1037
976
  },
1038
977
  },
1039
978
  {
1040
- path: ['foldTerminalCommand'],
1041
- label: 'Fold terminal command',
1042
- descriptions: { zh: '折叠终端命令' },
1043
- hint: 'Terminal cards (Bash/PowerShell): collapse a multi-line command header to its first line + count; Ctrl+O or a click expands it.',
1044
- hintDescriptions: { zh: '终端卡(Bash/PowerShell):多行命令头部折叠为首行 + 计数;Ctrl+O 或点击卡片展开。' },
1045
- kind: 'boolean',
979
+ ...settingField('foldTerminalCommand'),
1046
980
  format(value) {
1047
981
  // Unset in settings.yaml: show the effective resolution (cordis.yml
1048
982
  // → off) instead of a blank — same rule as `fullscreen`'s field.
@@ -1050,75 +984,50 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1050
984
  },
1051
985
  },
1052
986
  {
1053
- path: ['promptSessionLabel'],
1054
- label: 'Session name chip',
1055
- descriptions: { zh: '会话名标签' },
1056
- hint: 'Show the session name on the prompt top border, right corner. Off by default.',
1057
- hintDescriptions: { zh: '在输入框顶边框右上角显示会话名。默认关闭。' },
1058
- kind: 'boolean',
987
+ ...settingField('promptSessionLabel'),
1059
988
  },
1060
989
  {
1061
- path: ['expandEditor'],
1062
- label: 'Fullscreen draft editor',
1063
- descriptions: { zh: '全屏草稿编辑' },
1064
- hint: 'On: the ⛶ affordance in the input row and the expand-editor shortcut (default Ctrl+Shift+E) expand the draft into a whole-screen editor (Enter = newline, Ctrl+Enter = send). Off: both entry points disappear. On by default.',
1065
- hintDescriptions: { zh: '开启:输入行尾 ⛶ 按钮与全屏编辑快捷键(默认 Ctrl+Shift+E)把草稿展开成整屏编辑器(Enter 换行、Ctrl+Enter 发送)。关闭:两个入口都不显示。默认开启。' },
1066
- kind: 'boolean',
990
+ ...settingField('expandEditor'),
1067
991
  format(value) {
1068
992
  // Unset in settings.yaml: the effective default is on.
1069
993
  return String(typeof value === 'boolean' ? value : config.expandEditor !== false);
1070
994
  },
1071
995
  },
1072
996
  {
1073
- path: ['smoothStreaming'],
1074
- label: 'Smooth streaming',
1075
- descriptions: { zh: '流式平滑输出' },
1076
- hint: 'Reveal live replies, expanded thinking, and tool-call bodies through an even ~30fps flow instead of per-burst jumps; one-shot non-streaming replies paint as a flow too. Replay/history always paints complete. On by default.',
1077
- hintDescriptions: { zh: '把实时回复、展开的思考与工具卡正文按 ~30fps 匀速揭示,不再随供应商突发一跳一跳;一次性到达的非流式回复也会平滑打出。回放/历史内容始终完整直出。默认开启。' },
1078
- kind: 'boolean',
997
+ ...settingField('smoothStreaming'),
1079
998
  format(value) {
1080
999
  // Unset in settings.yaml: the effective default is on.
1081
1000
  return String(typeof value === 'boolean' ? value : config.smoothStreaming !== false);
1082
1001
  },
1083
1002
  },
1084
1003
  {
1085
- path: ['mermaidDiagrams'],
1086
- label: 'Mermaid diagrams',
1087
- descriptions: { zh: 'Mermaid 图表' },
1088
- hint: 'Render ```mermaid fences in replies as box-drawing diagrams (flowchart, sequence, state, class, ER, pie, mindmap, timeline, gitGraph). Diagrams wider than the terminal, or of an unsupported type, keep the fenced source. Applies immediately. On by default.',
1089
- hintDescriptions: { zh: '把回复中的 ```mermaid 代码块画成字符图(flowchart、sequence、state、class、ER、pie、mindmap、timeline、gitGraph)。比终端宽或类型不支持的图保留源码。立即生效。默认开启。' },
1090
- kind: 'boolean',
1004
+ ...settingField('mermaidDiagrams'),
1091
1005
  format(value) {
1092
1006
  // Unset in settings.yaml: the effective default is on.
1093
1007
  return String(typeof value === 'boolean' ? value : config.mermaidDiagrams !== false);
1094
1008
  },
1095
1009
  },
1096
1010
  {
1097
- path: ['recapOnOpen'],
1098
- label: 'Auto recap on open',
1099
- descriptions: { zh: '打开会话时自动总结' },
1100
- hint: 'On: opening/resuming a session automatically summarizes its recent activity into a dim line at the bottom of the transcript (hover/click to view or apply the suggested title). Off: use /recap manually.',
1101
- hintDescriptions: { zh: '开启:打开/恢复会话时自动把最近活动总结成一行灰字显示在会话底部(可悬停/点击查看或应用建议标题);关闭:手动使用 /recap。' },
1102
- kind: 'boolean',
1011
+ ...settingField('mathRendering'),
1012
+ },
1013
+ {
1014
+ ...settingField('mathImageScale'),
1015
+ },
1016
+ {
1017
+ ...settingField('mathImageBacking'),
1018
+ },
1019
+ {
1020
+ ...settingField('imageBacking'),
1021
+ },
1022
+ {
1023
+ ...settingField('recapOnOpen'),
1103
1024
  format(value) {
1104
1025
  // Unset in settings.yaml: the default is on.
1105
1026
  return value === undefined || value === null ? 'true' : String(value);
1106
1027
  },
1107
1028
  },
1108
1029
  {
1109
- path: ['effortDefault'],
1110
- label: 'Default reasoning effort',
1111
- descriptions: { zh: '默认推理强度' },
1112
- hint: 'Reasoning-effort level new sessions start on; the current session applies it to its next request too, when the model offers the tier (an unlisted level falls back to the model default). Auto = follow the cordis.yml `effort` pin, then the persisted /effort choice, then the model default.',
1113
- hintDescriptions: { zh: '新会话起始的推理强度档位;模型提供该档位时,当前会话的下一请求也会应用(模型不提供的档位会静默回落到模型默认)。自动 = 依次跟随 cordis.yml 的 effort 配置、持久化的 /effort 选择、模型默认档。' },
1114
- kind: 'select',
1115
- options: [
1116
- { value: 'auto', label: 'Auto (model default)', descriptions: { zh: '自动(模型默认)' } },
1117
- { value: 'off', label: 'Off', descriptions: { zh: '关闭' } },
1118
- { value: 'low', label: 'Low', descriptions: { zh: '低' } },
1119
- { value: 'high', label: 'High', descriptions: { zh: '高' } },
1120
- { value: 'max', label: 'Max', descriptions: { zh: '最高' } },
1121
- ],
1030
+ ...settingField('effortDefault'),
1122
1031
  format(value) {
1123
1032
  // Unset in settings.yaml: show what a boot would actually start
1124
1033
  // on (the cordis effort pin → the persisted /effort choice)
@@ -1131,190 +1040,79 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1131
1040
  },
1132
1041
  ...shortcutFields,
1133
1042
  {
1134
- path: ['statusBar', 'compact'],
1135
- label: 'Compact status bar',
1136
- descriptions: { zh: '紧凑状态栏' },
1137
- hint: 'Prefer the compact status presentation when terminal space allows.',
1138
- hintDescriptions: { zh: '终端空间允许时优先使用紧凑状态栏布局。' },
1139
- group: 'status-bar',
1140
- kind: 'boolean',
1043
+ ...settingField('statusBar.compact'),
1044
+ },
1045
+ {
1046
+ ...settingField('statusBar.model'),
1047
+ },
1048
+ {
1049
+ ...settingField('statusBar.thinking'),
1141
1050
  },
1142
1051
  {
1143
- path: ['statusBar', 'model'],
1144
- label: 'Show model',
1145
- descriptions: { zh: '显示模型' },
1146
- hint: 'Show the live model id in the status bar.',
1147
- hintDescriptions: { zh: '在状态栏显示当前模型标识。' },
1148
- group: 'status-bar',
1149
- kind: 'boolean',
1052
+ ...settingField('statusBar.cwd'),
1150
1053
  },
1151
1054
  {
1152
- path: ['statusBar', 'thinking'],
1153
- label: 'Show thinking',
1154
- descriptions: { zh: '显示思考' },
1155
- hint: 'Show the live reasoning effort or thinking mode.',
1156
- hintDescriptions: { zh: '显示当前推理强度或思考模式。' },
1157
- group: 'status-bar',
1158
- kind: 'boolean',
1055
+ ...settingField('statusBar.contextUsage'),
1159
1056
  },
1160
1057
  {
1161
- path: ['statusBar', 'cwd'],
1162
- label: 'Show working directory',
1163
- descriptions: { zh: '显示工作目录' },
1164
- hint: 'Show the session working directory.',
1165
- hintDescriptions: { zh: '显示当前会话的工作目录。' },
1166
- group: 'status-bar',
1167
- kind: 'boolean',
1058
+ ...settingField('statusBar.cache'),
1168
1059
  },
1169
1060
  {
1170
- path: ['statusBar', 'contextUsage'],
1171
- label: 'Show context usage',
1172
- descriptions: { zh: '显示上下文用量' },
1173
- hint: 'Show current context-window consumption.',
1174
- hintDescriptions: { zh: '显示当前上下文窗口占用情况。' },
1175
- group: 'status-bar',
1176
- kind: 'boolean',
1061
+ ...settingField('statusBar.tokens'),
1177
1062
  },
1178
1063
  {
1179
- path: ['statusBar', 'cache'],
1180
- label: 'Show cache',
1181
- descriptions: { zh: '显示缓存' },
1182
- hint: 'Show prompt-cache hit information.',
1183
- hintDescriptions: { zh: '显示提示词缓存命中信息。' },
1184
- group: 'status-bar',
1185
- kind: 'boolean',
1064
+ ...settingField('statusBar.cost'),
1186
1065
  },
1187
1066
  {
1188
- path: ['statusBar', 'tokens'],
1189
- label: 'Show token totals',
1190
- descriptions: { zh: '显示 Token 总量' },
1191
- hint: 'Show running input and output token totals.',
1192
- hintDescriptions: { zh: '显示累计输入与输出 Token。' },
1193
- group: 'status-bar',
1194
- kind: 'boolean',
1067
+ ...settingField('statusBar.tps'),
1195
1068
  },
1196
1069
  {
1197
- path: ['statusBar', 'cost'],
1198
- label: 'Show session cost estimate',
1199
- descriptions: { zh: '显示本会话花费估算' },
1200
- hint: 'Show the estimated session spend (≈¥) next to the token totals. Only appears for official DeepSeek providers whose model has a known price; the estimate follows the official per-million-token rates (peak/idle hours) and is not a bill.',
1201
- hintDescriptions: { zh: '在 Token 总量旁显示本会话花费估算(≈¥)。仅在使用 DeepSeek 官方 API key 且模型有已知单价时显示;按官方每百万 token 单价(高峰/空闲时段)估算,非账单。' },
1202
- group: 'status-bar',
1203
- kind: 'boolean',
1070
+ ...settingField('statusBar.gitBranch'),
1204
1071
  },
1205
1072
  {
1206
- path: ['statusBar', 'tps'],
1207
- label: 'Show output speed',
1208
- descriptions: { zh: '显示输出速度' },
1209
- hint: 'Show live and recent tokens-per-second metrics.',
1210
- hintDescriptions: { zh: '显示实时及近期每秒 Token 指标。' },
1211
- group: 'status-bar',
1212
- kind: 'boolean',
1073
+ ...settingField('statusBar.sessionTitle'),
1213
1074
  },
1214
1075
  {
1215
- path: ['statusBar', 'gitBranch'],
1216
- label: 'Show git branch',
1217
- descriptions: { zh: '显示 Git 分支' },
1218
- hint: 'Show the current git branch when available.',
1219
- hintDescriptions: { zh: '可用时显示当前 Git 分支。' },
1220
- group: 'status-bar',
1221
- kind: 'boolean',
1076
+ ...settingField('statusBar.sessionId'),
1222
1077
  },
1223
1078
  {
1224
- path: ['statusBar', 'sessionTitle'],
1225
- label: 'Show session title',
1226
- descriptions: { zh: '显示会话标题' },
1227
- hint: 'Show the current session title.',
1228
- hintDescriptions: { zh: '显示当前会话标题。' },
1229
- group: 'status-bar',
1230
- kind: 'boolean',
1079
+ ...settingField('statusBar.goal'),
1231
1080
  },
1232
1081
  {
1233
- path: ['statusBar', 'sessionId'],
1234
- label: 'Show session id',
1235
- descriptions: { zh: '显示会话 ID' },
1236
- hint: 'Show the short session id (# + first 8 chars) — it matches the session log filename for --resume.',
1237
- hintDescriptions: { zh: '显示短会话 ID(# + 前 8 位)——与日志文件名对应,方便 --resume 定位。' },
1238
- group: 'status-bar',
1239
- kind: 'boolean',
1082
+ ...settingField('statusBar.mode'),
1240
1083
  },
1241
1084
  {
1242
- path: ['statusBar', 'goal'],
1243
- label: 'Show goal status',
1244
- descriptions: { zh: '显示 Goal 状态' },
1245
- hint: 'Show a compact goal chip (phase glyph + rounds) in the status footer while a goal exists.',
1246
- hintDescriptions: { zh: '存在 Goal 时,在底部状态栏显示紧凑的 Goal 状态(阶段符号与轮次)。' },
1247
- group: 'status-bar',
1248
- kind: 'boolean',
1085
+ ...settingField('statusBar.contextBar'),
1249
1086
  },
1250
1087
  {
1251
- path: ['statusBar', 'mode'],
1252
- label: 'Show session mode',
1253
- descriptions: { zh: '显示会话模式' },
1254
- hint: 'Show the active non-default session mode.',
1255
- hintDescriptions: { zh: '显示当前启用的非默认会话模式。' },
1256
- group: 'status-bar',
1257
- kind: 'boolean',
1088
+ ...settingField('statusBar.activity'),
1258
1089
  },
1259
1090
  {
1260
- path: ['statusBar', 'contextBar'],
1261
- label: 'Show context progress bar',
1262
- descriptions: { zh: '显示上下文进度条' },
1263
- hint: 'Show the segmented context progress bar on its own footer row.',
1264
- hintDescriptions: { zh: '在底部单独一行显示分段上下文进度条。' },
1265
- group: 'status-bar',
1266
- kind: 'boolean',
1091
+ ...settingField('statusBar.trajectory'),
1267
1092
  },
1268
1093
  {
1269
- path: ['statusBar', 'activity'],
1270
- label: 'Show activity summary',
1271
- descriptions: { zh: '显示活动摘要' },
1272
- hint: 'Show the idle working-activity summary.',
1273
- hintDescriptions: { zh: '显示空闲时的工作活动摘要。' },
1274
- group: 'status-bar',
1275
- kind: 'boolean',
1094
+ ...settingField('statusBar.shortcutHint'),
1276
1095
  },
1277
1096
  {
1278
- path: ['statusBar', 'trajectory'],
1279
- label: 'Show trajectory strip',
1280
- descriptions: { zh: '显示轨迹条' },
1281
- hint: 'Show the animated mini trajectory strip at the footer edge.',
1282
- hintDescriptions: { zh: '在状态栏边缘显示动态迷你轨迹条。' },
1283
- group: 'status-bar',
1284
- kind: 'boolean',
1097
+ ...settingField('whale'),
1285
1098
  },
1286
1099
  {
1287
- path: ['statusBar', 'shortcutHint'],
1288
- label: 'Show shortcut reminder',
1289
- descriptions: { zh: '显示快捷键提示' },
1290
- hint: 'Control only the idle `? for shortcuts` reminder; pressing ? and the Esc shortcut hints are unaffected.',
1291
- hintDescriptions: { zh: '仅控制空闲时的 `? for shortcuts` 提示;按 ? 打开快捷键以及 Esc 快捷提示均不受影响。' },
1292
- group: 'status-bar',
1293
- kind: 'boolean',
1100
+ ...settingField('whaleIdle'),
1294
1101
  },
1295
1102
  {
1296
- path: ['whale'],
1297
- label: 'Whale art',
1298
- descriptions: { zh: '鲸鱼娘' },
1299
- hint: 'Show the pixel whale in the header splash.',
1300
- hintDescriptions: { zh: '开屏头部显示像素鲸鱼娘。' },
1301
- kind: 'boolean',
1103
+ ...settingField('whaleGirl'),
1302
1104
  },
1303
1105
  {
1304
- path: ['whaleIdle'],
1305
- label: 'Welcome whale idle',
1306
- descriptions: { zh: '鲸鱼娘闲置动画(欢迎期)' },
1307
- hint: 'Welcome-phase idle behaviors: after the intro the whale flutters its fins, thumps its tail, and dozes off when idle; clicking wakes a dozing whale and pops a heart. The first agent turn freezes it to the static standard frame.',
1308
- hintDescriptions: { zh: '欢迎期闲置行为:开屏后鲸鱼娘摆鱼鳍、偶尔拍尾巴,空闲会睡着冒 Z;点击唤醒睡着的鲸鱼娘并冒爱心。开始第一个任务后定格为静态标准帧。' },
1309
- kind: 'boolean',
1106
+ ...settingField('splashFont'),
1107
+ format(value) {
1108
+ // Unset in settings.yaml: show the effective resolution
1109
+ // (cordis.yml → daily) instead of a blank — same rule as the
1110
+ // `fullscreen` field.
1111
+ return normalizeSplashFont(value ?? config.splashFont);
1112
+ },
1310
1113
  },
1311
1114
  {
1312
- path: ['minimal'],
1313
- label: 'Minimal mode',
1314
- descriptions: { zh: '极简模式' },
1315
- hint: 'Hide the header splash, emoji glyphs, and decorative colors; code highlight and tool colors stay. Trims the status bar to model + cwd.',
1316
- hintDescriptions: { zh: '隐藏开屏头部、emoji 状态符与装饰性配色;代码高亮与工具配色保留,底栏只留模型与目录。' },
1317
- kind: 'boolean',
1115
+ ...settingField('minimal'),
1318
1116
  },
1319
1117
  ],
1320
1118
  });
@@ -1355,13 +1153,11 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1355
1153
  }
1356
1154
  // Positional command-line arguments are the initial prompt (issue #53):
1357
1155
  // `dsh-tui "run the tests"` forwards positionals through the dsh CLI,
1358
- // which mounts them as ctx.cmdlineArgs. The service shape drifted across
1359
- // dsh-cmdline builds — `{ get() }` is the current contract, older builds
1360
- // exposed `{ args }` — so read both. Submit once the channel exists;
1361
- // delivery goes through the normal pending/inbox chain, so no special
1362
- // timing is needed; flag-shaped leftovers are not prompt text.
1363
- const cmdline = ctx.cmdlineArgs;
1364
- const cmdlineArgs = cmdline?.get?.() ?? cmdline?.args;
1156
+ // which mounts them as ctx.cmdlineArgs. Reuse the snapshot read for resume
1157
+ // selection above, supporting both `{ get() }` and legacy `{ args }` hosts.
1158
+ // Submit once the channel exists; delivery goes through the normal pending/inbox
1159
+ // chain, so no special timing is needed. The parser separates startup flags
1160
+ // from literal prompt text.
1365
1161
  const initialPrompt = initialPromptFromCmdlineArgs(cmdlineArgs);
1366
1162
  if (initialPrompt)
1367
1163
  submitChannel(initialPrompt);
@@ -1411,6 +1207,24 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1411
1207
  if (error !== undefined) {
1412
1208
  const message = error instanceof Error ? error.message : String(error);
1413
1209
  ctx.logger.error(`dsh-tui: exit after error: ${message}`);
1210
+ // A crash must leave the resume marker a clean exit would leave: the
1211
+ // launcher's next start (and its safe-mode retry) then reopens the
1212
+ // session the user was actually in instead of a blank one. Only the
1213
+ // resumable case writes — unlike the clean-exit branch below, a crash
1214
+ // never CLEARS a marker, so a session the user still has cannot be
1215
+ // dropped by a failure that happened before the first message landed.
1216
+ try {
1217
+ if (isExitResumable({
1218
+ pendingCount: channel.pending.length,
1219
+ liveAgent: ctx.agents.get(SessionId(channel.agentId)),
1220
+ startupAgent: agent,
1221
+ })) {
1222
+ writeResumeTarget(channel.agentId);
1223
+ }
1224
+ }
1225
+ catch {
1226
+ // Resume persistence is best effort and must never block the exit.
1227
+ }
1414
1228
  void finishExit(ctx, instance, bootedFullscreen, undefined, `dsh-tui crashed: ${message}`, () => disposeRootAndExit(ctx, 1));
1415
1229
  return;
1416
1230
  }
@@ -1471,6 +1285,25 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1471
1285
  },
1472
1286
  });
1473
1287
  const handleExit = funnel.handleExit;
1288
+ // Process-level crash backstop (see installNestedUpdateOverflowProcessGuard):
1289
+ // an uncaught exception or unhandled rejection that is NOT the React #185
1290
+ // overflow would otherwise take Node's default path and kill the process
1291
+ // before this funnel runs — no resume marker, no terminal restore, and the
1292
+ // launcher's "entered safe mode" prompt on what looks like a lost session.
1293
+ // Route it through the same teardown a fatal RENDER error uses: unmount,
1294
+ // `dsh-tui crashed: …`, dispose, exit 1. Fail loud stays intact — the funnel
1295
+ // returns false when it has already settled or the tree is being torn down
1296
+ // (host recompose), and the guard then rethrows to Node's default crash.
1297
+ // DSH_TUI_NO_185_PROCESS_GUARD=1 skips the guard entirely, leaving process
1298
+ // error policy to the host exactly as before.
1299
+ registerProcessGuardFatalSink((error, origin) => {
1300
+ // An undefined reason (`Promise.reject()`, `throw undefined`) must not reach
1301
+ // the funnel as-is: `error !== undefined` is what selects the crash path, so
1302
+ // a bare undefined would exit 0 while this sink claims the process.
1303
+ const fatal = fatalReasonForExit(error, origin);
1304
+ ctx.logger.error(`dsh-tui: fatal ${origin}: ${fatal instanceof Error ? fatal.message : String(fatal)}`);
1305
+ return handleExit(fatal);
1306
+ });
1474
1307
  // External injection controller: Chat fills it with `{ append, submit }`
1475
1308
  // every render; the injection socket (opened below) drives it. A ref rather
1476
1309
  // than a prop callback so the socket handler always reaches the live Chat.
@@ -1498,7 +1331,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1498
1331
  const openHomeOnBoot = !homeSeen
1499
1332
  && launchSessionId === undefined
1500
1333
  && requestedWorkspace === undefined
1501
- && initialPromptFromCmdlineArgs(process.argv.slice(2)) === '';
1334
+ && initialPrompt === '';
1502
1335
  const chat = React.createElement(Chat, {
1503
1336
  channel,
1504
1337
  renderScene: createChannelSceneOutlet(() => rawChannel.pluginScene),
@@ -1510,6 +1343,7 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1510
1343
  // shortcuts). Soft-consumed: absent the row (stale patch, bare embed),
1511
1344
  // Chat falls back to inert stores and no shortcut registry.
1512
1345
  extensionDialogs: getHostDialogStore(ctx.get('tuiDialogs')),
1346
+ bonusNotices: ctx.get('dshAuth')?.coupons,
1513
1347
  extensionStatus: getHostStatusStore(ctx.get('tuiStatus')),
1514
1348
  // The working line's semantics belong to the dsh-working-activity plugin's
1515
1349
  // session projection; this store is the read side of that seam, so the TUI
@@ -1666,6 +1500,10 @@ export async function apply(ctx, runtimeConfig, configOwner = ctx) {
1666
1500
  ctx.effect(() => () => {
1667
1501
  logMouseDebug('apply teardown');
1668
1502
  funnel.markTeardown();
1503
+ // Drop the crash backstop with this mount: a torn-down funnel cannot own
1504
+ // the process, so a later fatal error falls back to Node's default crash
1505
+ // instead of reaching a disposed ctx.
1506
+ registerProcessGuardFatalSink(undefined);
1669
1507
  rawChannel.releaseContributions();
1670
1508
  instance?.unmount();
1671
1509
  });
@@ -1869,11 +1707,12 @@ export function createExitFunnel(deps) {
1869
1707
  },
1870
1708
  handleExit: (error) => {
1871
1709
  if (teardown)
1872
- return;
1710
+ return false;
1873
1711
  if (exited)
1874
- return;
1712
+ return false;
1875
1713
  exited = true;
1876
1714
  deps.onUserExit(error);
1715
+ return true;
1877
1716
  },
1878
1717
  };
1879
1718
  }