@deepseek-harness-tui/dsh-tui 0.6.0 → 0.7.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 (379) hide show
  1. package/README.md +74 -21
  2. package/bin/dsh-tui.js +115 -25
  3. package/cordis.patch.yml +69 -17
  4. package/cordis.yml +50 -12
  5. package/lib/types/activityPrefs.d.ts +1 -1
  6. package/lib/types/activityPrefs.js +3 -3
  7. package/lib/types/cc/figures.d.ts +27 -20
  8. package/lib/types/cc/figures.d.ts.map +1 -1
  9. package/lib/types/cc/figures.js +43 -34
  10. package/lib/types/cc/format.d.ts +18 -9
  11. package/lib/types/cc/format.d.ts.map +1 -1
  12. package/lib/types/cc/format.js +26 -18
  13. package/lib/types/cc/markdown.d.ts +31 -16
  14. package/lib/types/cc/markdown.d.ts.map +1 -1
  15. package/lib/types/cc/markdown.js +283 -260
  16. package/lib/types/cc/terminal.d.ts +10 -7
  17. package/lib/types/cc/terminal.d.ts.map +1 -1
  18. package/lib/types/cc/terminal.js +62 -50
  19. package/lib/types/command-trees.d.ts +3 -0
  20. package/lib/types/command-trees.d.ts.map +1 -0
  21. package/lib/types/command-trees.js +4 -0
  22. package/lib/types/commands.d.ts +37 -1
  23. package/lib/types/commands.d.ts.map +1 -1
  24. package/lib/types/commands.js +68 -3
  25. package/lib/types/components/ActivityLine.d.ts +1 -1
  26. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  27. package/lib/types/components/ActivityPicker.d.ts.map +1 -1
  28. package/lib/types/components/ActivityPicker.js +3 -4
  29. package/lib/types/components/BtwPanel.d.ts +16 -0
  30. package/lib/types/components/BtwPanel.d.ts.map +1 -0
  31. package/lib/types/components/BtwPanel.js +47 -0
  32. package/lib/types/components/CommandSuggestions.d.ts +4 -2
  33. package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
  34. package/lib/types/components/CommandSuggestions.js +2 -2
  35. package/lib/types/components/EffortSlider.d.ts +15 -0
  36. package/lib/types/components/EffortSlider.d.ts.map +1 -0
  37. package/lib/types/components/EffortSlider.js +17 -0
  38. package/lib/types/components/GoalTodoPanel.d.ts +1 -1
  39. package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
  40. package/lib/types/components/HelpMenu.d.ts +5 -2
  41. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  42. package/lib/types/components/HelpMenu.js +8 -3
  43. package/lib/types/components/HistorySearchDialog.d.ts +1 -1
  44. package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
  45. package/lib/types/components/HistorySearchDialog.js +21 -10
  46. package/lib/types/components/InterruptedByUser.d.ts +2 -2
  47. package/lib/types/components/InterruptedByUser.d.ts.map +1 -1
  48. package/lib/types/components/InterruptedByUser.js +4 -3
  49. package/lib/types/components/LoadedContextPanel.d.ts +1 -1
  50. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  51. package/lib/types/components/LogoV2.d.ts.map +1 -1
  52. package/lib/types/components/LogoV2.js +2 -1
  53. package/lib/types/components/Markdown.d.ts +11 -11
  54. package/lib/types/components/Markdown.d.ts.map +1 -1
  55. package/lib/types/components/Markdown.js +63 -57
  56. package/lib/types/components/MarkdownTable.d.ts +1 -1
  57. package/lib/types/components/MarkdownTable.js +2 -2
  58. package/lib/types/components/MessageList.d.ts +10 -2
  59. package/lib/types/components/MessageList.d.ts.map +1 -1
  60. package/lib/types/components/MessageList.js +17 -10
  61. package/lib/types/components/ModelPicker.d.ts +4 -1
  62. package/lib/types/components/ModelPicker.d.ts.map +1 -1
  63. package/lib/types/components/ModelPicker.js +16 -4
  64. package/lib/types/components/OverlayAbove.d.ts +20 -0
  65. package/lib/types/components/OverlayAbove.d.ts.map +1 -0
  66. package/lib/types/components/OverlayAbove.js +18 -0
  67. package/lib/types/components/PresetPicker.d.ts +1 -1
  68. package/lib/types/components/PresetPicker.d.ts.map +1 -1
  69. package/lib/types/components/PresetPicker.js +2 -3
  70. package/lib/types/components/PromptInput.d.ts +5 -4
  71. package/lib/types/components/PromptInput.d.ts.map +1 -1
  72. package/lib/types/components/PromptInput.js +186 -39
  73. package/lib/types/components/ResumePicker.d.ts +15 -4
  74. package/lib/types/components/ResumePicker.d.ts.map +1 -1
  75. package/lib/types/components/ResumePicker.js +25 -9
  76. package/lib/types/components/RewindPicker.d.ts +1 -1
  77. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  78. package/lib/types/components/RewindPicker.js +14 -5
  79. package/lib/types/components/SearchBox.d.ts +1 -1
  80. package/lib/types/components/SearchBox.js +1 -1
  81. package/lib/types/components/Spinner/GlimmerMessage.d.ts +1 -2
  82. package/lib/types/components/Spinner/GlimmerMessage.d.ts.map +1 -1
  83. package/lib/types/components/Spinner/GlimmerMessage.js +1 -2
  84. package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +1 -1
  85. package/lib/types/components/Spinner/SpinnerAnimationRow.js +2 -2
  86. package/lib/types/components/Spinner/SpinnerGlyph.d.ts +1 -1
  87. package/lib/types/components/Spinner/SpinnerGlyph.js +1 -1
  88. package/lib/types/components/Spinner/spinnerUtils.d.ts +13 -18
  89. package/lib/types/components/Spinner/spinnerUtils.d.ts.map +1 -1
  90. package/lib/types/components/Spinner/spinnerUtils.js +67 -71
  91. package/lib/types/components/Spinner/useStalledAnimation.d.ts +1 -2
  92. package/lib/types/components/Spinner/useStalledAnimation.d.ts.map +1 -1
  93. package/lib/types/components/Spinner/useStalledAnimation.js +1 -2
  94. package/lib/types/components/StreamingMarkdown.d.ts +1 -1
  95. package/lib/types/components/StreamingMarkdown.js +1 -1
  96. package/lib/types/components/ThemePicker.d.ts +13 -9
  97. package/lib/types/components/ThemePicker.d.ts.map +1 -1
  98. package/lib/types/components/ThemePicker.js +21 -15
  99. package/lib/types/components/ThinkingToggle.d.ts +1 -1
  100. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  101. package/lib/types/components/ThinkingToggle.js +8 -8
  102. package/lib/types/components/ToolUseLoader.d.ts +1 -1
  103. package/lib/types/components/ToolUseLoader.js +1 -1
  104. package/lib/types/components/WorkingSpinner.d.ts +2 -2
  105. package/lib/types/components/WorkingSpinner.js +2 -2
  106. package/lib/types/components/WorkspaceFlowPicker.d.ts +15 -0
  107. package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -0
  108. package/lib/types/components/WorkspaceFlowPicker.js +19 -0
  109. package/lib/types/components/WorkspacePicker.d.ts +9 -0
  110. package/lib/types/components/WorkspacePicker.d.ts.map +1 -0
  111. package/lib/types/components/WorkspacePicker.js +13 -0
  112. package/lib/types/components/approvals/ApprovalPanel.d.ts +1 -1
  113. package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
  114. package/lib/types/components/approvals/ApprovalPanel.js +2 -1
  115. package/lib/types/components/design-system/Byline.d.ts +1 -1
  116. package/lib/types/components/design-system/Byline.js +1 -1
  117. package/lib/types/components/design-system/Divider.d.ts +1 -1
  118. package/lib/types/components/design-system/Divider.js +1 -1
  119. package/lib/types/components/design-system/HintLine.d.ts +12 -0
  120. package/lib/types/components/design-system/HintLine.d.ts.map +1 -0
  121. package/lib/types/components/design-system/HintLine.js +15 -0
  122. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +1 -1
  123. package/lib/types/components/design-system/KeyboardShortcutHint.js +1 -1
  124. package/lib/types/components/design-system/ListItem.d.ts +2 -2
  125. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  126. package/lib/types/components/design-system/ListItem.js +35 -3
  127. package/lib/types/components/design-system/LoadingState.d.ts +1 -2
  128. package/lib/types/components/design-system/LoadingState.d.ts.map +1 -1
  129. package/lib/types/components/design-system/LoadingState.js +1 -2
  130. package/lib/types/components/design-system/Pane.d.ts +2 -2
  131. package/lib/types/components/design-system/Pane.js +2 -2
  132. package/lib/types/components/design-system/ProgressBar.d.ts +1 -2
  133. package/lib/types/components/design-system/ProgressBar.d.ts.map +1 -1
  134. package/lib/types/components/design-system/ProgressBar.js +1 -2
  135. package/lib/types/components/design-system/StatusIcon.d.ts +2 -2
  136. package/lib/types/components/design-system/StatusIcon.js +2 -2
  137. package/lib/types/components/design-system/ThemeProvider.d.ts +1 -1
  138. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  139. package/lib/types/components/design-system/ThemeProvider.js +87 -26
  140. package/lib/types/components/design-system/ThemedBox.d.ts +1 -1
  141. package/lib/types/components/design-system/ThemedBox.js +1 -1
  142. package/lib/types/components/design-system/ThemedText.d.ts +2 -2
  143. package/lib/types/components/design-system/ThemedText.js +2 -2
  144. package/lib/types/components/listWindow.d.ts +26 -0
  145. package/lib/types/components/listWindow.d.ts.map +1 -0
  146. package/lib/types/components/listWindow.js +47 -0
  147. package/lib/types/components/messages/AssistantTextMessage.d.ts +1 -2
  148. package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
  149. package/lib/types/components/messages/AssistantTextMessage.js +1 -2
  150. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -2
  151. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  152. package/lib/types/components/messages/AssistantThinkingMessage.js +6 -6
  153. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +12 -4
  154. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  155. package/lib/types/components/messages/AssistantToolUseMessage.js +9 -5
  156. package/lib/types/components/messages/MessageMetadata.d.ts +1 -1
  157. package/lib/types/components/messages/MessageMetadata.js +1 -1
  158. package/lib/types/components/messages/UserPromptMessage.d.ts +1 -1
  159. package/lib/types/components/messages/UserPromptMessage.js +1 -1
  160. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +5 -1
  161. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  162. package/lib/types/components/questions/AskUserQuestionPanel.js +11 -9
  163. package/lib/types/components/questions/PlanReviewPanel.d.ts +1 -1
  164. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  165. package/lib/types/components/questions/PlanReviewPanel.js +3 -2
  166. package/lib/types/components/trajectory/HotspotView.d.ts +14 -0
  167. package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -0
  168. package/lib/types/components/trajectory/HotspotView.js +83 -0
  169. package/lib/types/components/trajectory/Inspector.d.ts +31 -0
  170. package/lib/types/components/trajectory/Inspector.d.ts.map +1 -0
  171. package/lib/types/components/trajectory/Inspector.js +67 -0
  172. package/lib/types/components/trajectory/Ledger.d.ts +20 -0
  173. package/lib/types/components/trajectory/Ledger.d.ts.map +1 -0
  174. package/lib/types/components/trajectory/Ledger.js +112 -0
  175. package/lib/types/components/trajectory/MiniWake.d.ts +24 -0
  176. package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -0
  177. package/lib/types/components/trajectory/MiniWake.js +99 -0
  178. package/lib/types/components/trajectory/WaveBand.d.ts +33 -0
  179. package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -0
  180. package/lib/types/components/trajectory/WaveBand.js +145 -0
  181. package/lib/types/customTheme.d.ts +6 -6
  182. package/lib/types/customTheme.d.ts.map +1 -1
  183. package/lib/types/customTheme.js +15 -12
  184. package/lib/types/dsh-adapter/approvals.d.ts.map +1 -0
  185. package/lib/types/{channel.d.ts → dsh-adapter/channel.d.ts} +184 -43
  186. package/lib/types/dsh-adapter/channel.d.ts.map +1 -0
  187. package/lib/types/{channel.js → dsh-adapter/channel.js} +972 -201
  188. package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -0
  189. package/lib/types/{childStderr.js → dsh-adapter/childStderr.js} +1 -1
  190. package/lib/types/dsh-adapter/command-trees.d.ts +27 -0
  191. package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -0
  192. package/lib/types/dsh-adapter/command-trees.js +42 -0
  193. package/lib/types/dsh-adapter/compat/index.d.ts +22 -0
  194. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -0
  195. package/lib/types/{compat → dsh-adapter/compat}/index.js +7 -4
  196. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +86 -0
  197. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -0
  198. package/lib/types/dsh-adapter/compat/sessionLog.js +347 -0
  199. package/lib/types/dsh-adapter/contract.d.ts +20 -0
  200. package/lib/types/dsh-adapter/contract.d.ts.map +1 -0
  201. package/lib/types/dsh-adapter/contract.js +109 -0
  202. package/lib/types/dsh-adapter/index.d.ts +80 -0
  203. package/lib/types/dsh-adapter/index.d.ts.map +1 -0
  204. package/lib/types/dsh-adapter/index.js +45 -0
  205. package/lib/types/dsh-adapter/invariant.d.ts.map +1 -0
  206. package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -0
  207. package/lib/types/{plugin.d.ts → dsh-adapter/plugin.d.ts} +17 -0
  208. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -0
  209. package/lib/types/{plugin.js → dsh-adapter/plugin.js} +280 -80
  210. package/lib/types/dsh-adapter/presets.d.ts.map +1 -0
  211. package/lib/types/dsh-adapter/providerWizard.d.ts +91 -0
  212. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -0
  213. package/lib/types/dsh-adapter/providerWizard.js +332 -0
  214. package/lib/types/{questions.d.ts → dsh-adapter/questions.d.ts} +7 -2
  215. package/lib/types/dsh-adapter/questions.d.ts.map +1 -0
  216. package/lib/types/{questions.js → dsh-adapter/questions.js} +15 -7
  217. package/lib/types/dsh-adapter/sideQuestion.d.ts +38 -0
  218. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -0
  219. package/lib/types/dsh-adapter/sideQuestion.js +69 -0
  220. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts +46 -0
  221. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts.map +1 -0
  222. package/lib/types/dsh-adapter/trajectory/aggregate.js +207 -0
  223. package/lib/types/dsh-adapter/trajectory/guards.d.ts +177 -0
  224. package/lib/types/dsh-adapter/trajectory/guards.d.ts.map +1 -0
  225. package/lib/types/dsh-adapter/trajectory/guards.js +235 -0
  226. package/lib/types/dsh-adapter/trajectory/index.d.ts +16 -0
  227. package/lib/types/dsh-adapter/trajectory/index.d.ts.map +1 -0
  228. package/lib/types/dsh-adapter/trajectory/index.js +15 -0
  229. package/lib/types/dsh-adapter/trajectory/inspect.d.ts +40 -0
  230. package/lib/types/dsh-adapter/trajectory/inspect.d.ts.map +1 -0
  231. package/lib/types/dsh-adapter/trajectory/inspect.js +160 -0
  232. package/lib/types/dsh-adapter/trajectory/projection.d.ts +128 -0
  233. package/lib/types/dsh-adapter/trajectory/projection.d.ts.map +1 -0
  234. package/lib/types/dsh-adapter/trajectory/projection.js +653 -0
  235. package/lib/types/dsh-adapter/trajectory/types.d.ts +232 -0
  236. package/lib/types/dsh-adapter/trajectory/types.d.ts.map +1 -0
  237. package/lib/types/dsh-adapter/trajectory/types.js +70 -0
  238. package/lib/types/dsh-adapter/trajectory/wave.d.ts +45 -0
  239. package/lib/types/dsh-adapter/trajectory/wave.d.ts.map +1 -0
  240. package/lib/types/dsh-adapter/trajectory/wave.js +210 -0
  241. package/lib/types/dsh-adapter/types.d.ts +23 -0
  242. package/lib/types/dsh-adapter/types.d.ts.map +1 -0
  243. package/lib/types/dsh-adapter/types.js +1 -0
  244. package/lib/types/dsh-adapter/workspace.d.ts +22 -0
  245. package/lib/types/dsh-adapter/workspace.d.ts.map +1 -0
  246. package/lib/types/dsh-adapter/workspace.js +16 -0
  247. package/lib/types/dsh-adapter/workspaces.d.ts +118 -0
  248. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -0
  249. package/lib/types/dsh-adapter/workspaces.js +290 -0
  250. package/lib/types/effortPrefs.d.ts +1 -1
  251. package/lib/types/effortPrefs.js +3 -3
  252. package/lib/types/history.js +2 -2
  253. package/lib/types/hooks/useBlink.d.ts +1 -1
  254. package/lib/types/hooks/useBlink.js +1 -1
  255. package/lib/types/i18n.d.ts +977 -36
  256. package/lib/types/i18n.d.ts.map +1 -1
  257. package/lib/types/i18n.js +307 -30
  258. package/lib/types/index.d.ts +1 -69
  259. package/lib/types/index.d.ts.map +1 -1
  260. package/lib/types/index.js +3 -31
  261. package/lib/types/ink/components/App.d.ts.map +1 -1
  262. package/lib/types/ink/components/App.js +33 -19
  263. package/lib/types/ink/dom.d.ts +15 -0
  264. package/lib/types/ink/dom.d.ts.map +1 -1
  265. package/lib/types/ink/dom.js +32 -0
  266. package/lib/types/ink/hooks/use-input.d.ts.map +1 -1
  267. package/lib/types/ink/hooks/use-input.js +8 -0
  268. package/lib/types/ink/hooks/use-terminal-size.d.ts +1 -1
  269. package/lib/types/ink/hooks/use-terminal-size.js +1 -1
  270. package/lib/types/ink/ink.d.ts.map +1 -1
  271. package/lib/types/ink/ink.js +109 -28
  272. package/lib/types/ink/input-suppression.d.ts +20 -0
  273. package/lib/types/ink/input-suppression.d.ts.map +1 -0
  274. package/lib/types/ink/input-suppression.js +26 -0
  275. package/lib/types/ink/log-update.js +21 -6
  276. package/lib/types/ink/parse-keypress.d.ts +31 -0
  277. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  278. package/lib/types/ink/parse-keypress.js +442 -8
  279. package/lib/types/ink/terminal-querier.d.ts +5 -1
  280. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  281. package/lib/types/ink/terminal-querier.js +27 -3
  282. package/lib/types/ink/terminal.d.ts +18 -0
  283. package/lib/types/ink/terminal.d.ts.map +1 -1
  284. package/lib/types/ink/terminal.js +32 -4
  285. package/lib/types/ink/termio/csi.d.ts +10 -0
  286. package/lib/types/ink/termio/csi.d.ts.map +1 -1
  287. package/lib/types/ink/termio/csi.js +20 -0
  288. package/lib/types/ink/termio/tokenize.js +10 -0
  289. package/lib/types/modelPrefs.d.ts +1 -1
  290. package/lib/types/modelPrefs.js +3 -3
  291. package/lib/types/presetPrefs.d.ts +1 -1
  292. package/lib/types/presetPrefs.js +3 -3
  293. package/lib/types/screens/Chat.d.ts +20 -4
  294. package/lib/types/screens/Chat.d.ts.map +1 -1
  295. package/lib/types/screens/Chat.js +655 -55
  296. package/lib/types/screens/StatusLine.d.ts +17 -2
  297. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  298. package/lib/types/screens/StatusLine.js +12 -4
  299. package/lib/types/screens/TrajectoryScene.d.ts +16 -0
  300. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -0
  301. package/lib/types/screens/TrajectoryScene.js +305 -0
  302. package/lib/types/sessionHistory.d.ts +9 -1
  303. package/lib/types/sessionHistory.d.ts.map +1 -1
  304. package/lib/types/sessionHistory.js +56 -16
  305. package/lib/types/sessionModes.d.ts +29 -0
  306. package/lib/types/sessionModes.d.ts.map +1 -0
  307. package/lib/types/sessionModes.js +45 -0
  308. package/lib/types/theme.d.ts +27 -3
  309. package/lib/types/theme.d.ts.map +1 -1
  310. package/lib/types/theme.js +48 -4
  311. package/lib/types/themePrefs.d.ts +3 -3
  312. package/lib/types/themePrefs.js +5 -5
  313. package/lib/types/trajectory/format.d.ts +100 -0
  314. package/lib/types/trajectory/format.d.ts.map +1 -0
  315. package/lib/types/trajectory/format.js +213 -0
  316. package/lib/types/trajectory/motion.d.ts +99 -0
  317. package/lib/types/trajectory/motion.d.ts.map +1 -0
  318. package/lib/types/trajectory/motion.js +143 -0
  319. package/lib/types/trajectory/query.d.ts +83 -0
  320. package/lib/types/trajectory/query.d.ts.map +1 -0
  321. package/lib/types/trajectory/query.js +187 -0
  322. package/lib/types/trajectoryPrefs.d.ts +36 -0
  323. package/lib/types/trajectoryPrefs.d.ts.map +1 -0
  324. package/lib/types/trajectoryPrefs.js +65 -0
  325. package/lib/types/update.d.ts +3 -3
  326. package/lib/types/update.d.ts.map +1 -1
  327. package/lib/types/update.js +18 -7
  328. package/lib/types/utils/clipboard.d.ts +101 -29
  329. package/lib/types/utils/clipboard.d.ts.map +1 -1
  330. package/lib/types/utils/clipboard.js +533 -55
  331. package/lib/types/utils/debug.d.ts +1 -1
  332. package/lib/types/utils/debug.js +2 -2
  333. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  334. package/lib/types/utils/execFileNoThrow.js +16 -6
  335. package/lib/types/utils/externalEditor.d.ts +115 -0
  336. package/lib/types/utils/externalEditor.d.ts.map +1 -0
  337. package/lib/types/utils/externalEditor.js +270 -0
  338. package/lib/types/utils/fullscreen.d.ts +2 -2
  339. package/lib/types/utils/fullscreen.js +3 -3
  340. package/lib/types/utils/loaded-context.d.ts +1 -1
  341. package/lib/types/utils/loaded-context.d.ts.map +1 -1
  342. package/lib/types/utils/modifiers.d.ts +24 -0
  343. package/lib/types/utils/modifiers.d.ts.map +1 -1
  344. package/lib/types/utils/modifiers.js +27 -0
  345. package/lib/types/utils/paths.d.ts +45 -0
  346. package/lib/types/utils/paths.d.ts.map +1 -0
  347. package/lib/types/utils/paths.js +69 -0
  348. package/lib/types/utils/shellQuote.d.ts +14 -0
  349. package/lib/types/utils/shellQuote.d.ts.map +1 -0
  350. package/lib/types/utils/shellQuote.js +39 -0
  351. package/lib/types/utils/workspaceRoot.d.ts +21 -0
  352. package/lib/types/utils/workspaceRoot.d.ts.map +1 -0
  353. package/lib/types/utils/workspaceRoot.js +47 -0
  354. package/lib/types/workspaces.d.ts +3 -0
  355. package/lib/types/workspaces.d.ts.map +1 -0
  356. package/lib/types/workspaces.js +4 -0
  357. package/package.json +26 -8
  358. package/lib/types/approvals.d.ts.map +0 -1
  359. package/lib/types/channel.d.ts.map +0 -1
  360. package/lib/types/childStderr.d.ts.map +0 -1
  361. package/lib/types/compat/index.d.ts +0 -20
  362. package/lib/types/compat/index.d.ts.map +0 -1
  363. package/lib/types/compat/sessionLog.d.ts +0 -40
  364. package/lib/types/compat/sessionLog.d.ts.map +0 -1
  365. package/lib/types/compat/sessionLog.js +0 -226
  366. package/lib/types/invariant.d.ts.map +0 -1
  367. package/lib/types/packaged-skills.d.ts.map +0 -1
  368. package/lib/types/plugin.d.ts.map +0 -1
  369. package/lib/types/presets.d.ts.map +0 -1
  370. package/lib/types/questions.d.ts.map +0 -1
  371. /package/lib/types/{approvals.d.ts → dsh-adapter/approvals.d.ts} +0 -0
  372. /package/lib/types/{approvals.js → dsh-adapter/approvals.js} +0 -0
  373. /package/lib/types/{childStderr.d.ts → dsh-adapter/childStderr.d.ts} +0 -0
  374. /package/lib/types/{invariant.d.ts → dsh-adapter/invariant.d.ts} +0 -0
  375. /package/lib/types/{invariant.js → dsh-adapter/invariant.js} +0 -0
  376. /package/lib/types/{packaged-skills.d.ts → dsh-adapter/packaged-skills.d.ts} +0 -0
  377. /package/lib/types/{packaged-skills.js → dsh-adapter/packaged-skills.js} +0 -0
  378. /package/lib/types/{presets.d.ts → dsh-adapter/presets.d.ts} +0 -0
  379. /package/lib/types/{presets.js → dsh-adapter/presets.js} +0 -0
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import type { InspectDetail } from '../../dsh-adapter/trajectory/index.js';
3
+ import type { TrajNode } from '../../dsh-adapter/types.js';
4
+ /**
5
+ * The inspector — full detail for the focused row, in a fixed-height slot.
6
+ *
7
+ * Two properties matter more than what it shows:
8
+ *
9
+ * **It follows the cursor with no keystroke.** Moving down updates it; there
10
+ * is no "open" step. That is one decision removed from the most common action
11
+ * in the view, and it is the reason a run of rows can be triaged by holding
12
+ * ↓ rather than by opening and closing each one.
13
+ *
14
+ * **Its height never changes.** A pane that grew with its content would resize
15
+ * the frame on every cursor move — the exact motion that takes inline
16
+ * rendering down the shrink-frame path. Fixed geometry means moving the cursor
17
+ * emits style bytes and nothing else. `Enter` opens the same content as a
18
+ * full-height page, which is a deliberate, once-per-inspection resize.
19
+ */
20
+ export declare function Inspector({ node, detail, height, width, expanded, scroll, }: {
21
+ node: TrajNode | undefined;
22
+ detail: InspectDetail | undefined;
23
+ /** Rows this pane occupies, borders included. Never varies with content. */
24
+ height: number;
25
+ width: number;
26
+ /** True when `Enter` has promoted the pane to a full-height reading page. */
27
+ expanded: boolean;
28
+ /** First body line to show, for paging an expanded pane. */
29
+ scroll: number;
30
+ }): React.ReactNode;
31
+ //# sourceMappingURL=Inspector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/Inspector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAE1D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,GACP,EAAE;IACD,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;IACjC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,CAAA;IACjB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CAiGlB"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from '../../ui.js';
3
+ import { formatDuration } from '../../trajectory/format.js';
4
+ /**
5
+ * The inspector — full detail for the focused row, in a fixed-height slot.
6
+ *
7
+ * Two properties matter more than what it shows:
8
+ *
9
+ * **It follows the cursor with no keystroke.** Moving down updates it; there
10
+ * is no "open" step. That is one decision removed from the most common action
11
+ * in the view, and it is the reason a run of rows can be triaged by holding
12
+ * ↓ rather than by opening and closing each one.
13
+ *
14
+ * **Its height never changes.** A pane that grew with its content would resize
15
+ * the frame on every cursor move — the exact motion that takes inline
16
+ * rendering down the shrink-frame path. Fixed geometry means moving the cursor
17
+ * emits style bytes and nothing else. `Enter` opens the same content as a
18
+ * full-height page, which is a deliberate, once-per-inspection resize.
19
+ */
20
+ export function Inspector({ node, detail, height, width, expanded, scroll, }) {
21
+ const bodyHeight = Math.max(1, height - 1);
22
+ if (node === undefined || detail === undefined) {
23
+ return (_jsx(Box, { flexDirection: "column", height: height, flexShrink: 0, children: _jsx(Text, { color: "subtle", children: "\u2014" }) }));
24
+ }
25
+ // Flatten every section into display lines up front, so paging and
26
+ // clipping operate on one uniform list.
27
+ const lines = [];
28
+ for (const section of detail.sections) {
29
+ // A lone section whose heading repeats the pane title (a message row's
30
+ // `assistant` under `assistant`) spends a line saying nothing.
31
+ const redundant = detail.sections.length === 1 && section.title.toLowerCase() === detail.title.toLowerCase();
32
+ if (!redundant)
33
+ lines.push({ text: section.title, tone: section.tone, head: true });
34
+ for (const raw of section.body.split('\n')) {
35
+ // Tabs would break column alignment inside the pane.
36
+ lines.push({ text: raw.replace(/\t/g, ' '), tone: section.tone });
37
+ }
38
+ }
39
+ // The pane always paints exactly `height` rows: one header plus bodyHeight
40
+ // body rows, the last of which becomes the overflow marker when content
41
+ // runs past the slot, and blank padding when it does not. Anything that
42
+ // varied the row count here would resize the frame on every cursor move.
43
+ const overflow = lines.length - scroll > bodyHeight;
44
+ const visibleCount = overflow ? bodyHeight - 1 : bodyHeight;
45
+ const clipped = lines.slice(scroll, scroll + visibleCount);
46
+ const hidden = lines.length - scroll - visibleCount;
47
+ const body = Array.from({ length: bodyHeight }, (_, index) => clipped[index] ?? null);
48
+ const status = node.status === 'error' ? 'error' : node.status === 'running' ? 'success' : 'inactive';
49
+ return (_jsxs(Box, { flexDirection: "column", height: height, flexShrink: 0, children: [_jsxs(Box, { flexDirection: "row", gap: 1, width: "100%", children: [_jsxs(Text, { color: status, bold: true, children: ['▎', detail.title] }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { wrap: "truncate", color: "subtle", children: detail.facts.join(' · ') }) }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: status, children: node.durationMs === undefined ? '' : formatDuration(node.durationMs) }) })] }), body.map((line, index) => {
50
+ const isMarker = overflow && index === bodyHeight - 1;
51
+ if (isMarker) {
52
+ return (_jsx(Box, { width: "100%", overflow: "hidden", children: _jsx(Text, { color: "subtle", wrap: "truncate", children: ` …${hidden} more · ${expanded ? 'j/k' : 'enter'}` }) }, "more"));
53
+ }
54
+ if (line === null) {
55
+ return (_jsx(Box, { width: "100%", children: _jsx(Text, { children: " " }) }, index));
56
+ }
57
+ return (_jsx(Box, { width: "100%", overflow: "hidden", children: _jsx(Text, { wrap: "truncate", bold: line.head, color: line.head
58
+ ? line.tone === 'error'
59
+ ? 'error'
60
+ : 'permission'
61
+ : line.tone === 'error'
62
+ ? 'error'
63
+ : line.tone === 'dim'
64
+ ? 'subtle'
65
+ : 'inactiveShimmer', children: line.head ? ` ${line.text}` : ` ${line.text.slice(0, Math.max(0, width - 6))}` }) }, index));
66
+ })] }));
67
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { TrajNode } from '../../dsh-adapter/types.js';
3
+ export declare function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, }: {
4
+ /** The (possibly filtered) ledger. */
5
+ rows: readonly TrajNode[];
6
+ /** Index of the first visible row. */
7
+ start: number;
8
+ /** Visible row count. */
9
+ height: number;
10
+ /** Focused row index into `rows`. */
11
+ cursor: number;
12
+ /** Terminal width in cells. */
13
+ width: number;
14
+ tick: number;
15
+ /** Tick at which the most recent rows arrived. */
16
+ arrivalTick: number;
17
+ /** Rows at or after this index are the ones that just arrived. */
18
+ arrivalFrom: number;
19
+ }): React.ReactNode;
20
+ //# sourceMappingURL=Ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ledger.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/Ledger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAiBzB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AA6C1D,wBAAgB,MAAM,CAAC,EACrB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,KAAK,EACL,IAAI,EACJ,WAAW,EACX,WAAW,GACZ,EAAE;IACD,sCAAsC;IACtC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;IACzB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAoJlB"}
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text, useTheme } from '../../ui.js';
3
+ import { burstDurationMs, burstErrors, previewText } from '../../dsh-adapter/trajectory/index.js';
4
+ import { costGlyph, formatDuration, formatClock, heatColor, KIND_BADGE, KIND_BADGE_BG, KIND_FG, KIND_GLYPH, ledgerLayout, } from '../../trajectory/format.js';
5
+ import { arrive, mix } from '../../trajectory/motion.js';
6
+ import { stringWidth } from '../../ink/stringWidth.js';
7
+ import { getTheme } from '../../theme.js';
8
+ /**
9
+ * The ledger — one line per event, columns aligned across every row.
10
+ *
11
+ * Four decisions carry most of the readability:
12
+ *
13
+ * **Flat rows, spined turns.** Indenting by turn would break the column
14
+ * alignment that makes forty rows scannable at a glance, so rows stay flush
15
+ * and a two-cell spine on the left (`╭ │ ╰`, the git-graph idiom) carries the
16
+ * grouping instead. The spine is itself information: it turns red for a turn
17
+ * that failed and green for the turn still running.
18
+ *
19
+ * **Turn boundaries are rules, not rows.** A turn is a chapter heading, and a
20
+ * heading that looks like a body row makes the ledger read as one undifferentiated
21
+ * list. Rendering it as a full-width rule chunks a five-hundred-row session
22
+ * into things the eye can count.
23
+ *
24
+ * **Cost before number.** Every row carries a one-cell bar on an absolute
25
+ * scale, so "which of these was slow" is answered by silhouette rather than by
26
+ * reading a column of durations.
27
+ *
28
+ * **Call and result on one line.** `name {args} → result` — the same shape the
29
+ * official web ledger uses, and the reason a screenful answers "what did it do
30
+ * and what came back" without a single expansion.
31
+ *
32
+ * Rows are windowed by the caller; this component paints only what it is
33
+ * given, and calls {@link previewText} exactly once per visible cell.
34
+ */
35
+ /** Idle shorter than this is noise, not a pause worth naming. */
36
+ const IDLE_FLOOR_MS = 20_000;
37
+ /** Spine glyphs by position within a turn. */
38
+ const SPINE = { open: '╭', mid: '│', close: '╰', none: ' ' };
39
+ /** Which spine glyph a row gets, given its neighbours' turns. */
40
+ function spineGlyph(rows, index) {
41
+ const node = rows[index];
42
+ if (node.kind === 'turn')
43
+ return SPINE.open;
44
+ const next = rows[index + 1];
45
+ if (next === undefined || next.turn !== node.turn || next.kind === 'turn')
46
+ return SPINE.close;
47
+ return SPINE.mid;
48
+ }
49
+ export function Ledger({ rows, start, height, cursor, width, tick, arrivalTick, arrivalFrom, }) {
50
+ const [themeName] = useTheme();
51
+ const theme = getTheme(themeName);
52
+ const layout = ledgerLayout(width);
53
+ const visible = rows.slice(start, start + height);
54
+ const arriving = arrive(tick, arrivalTick);
55
+ // The ledger is the scene's only elastic region: the chrome above and the
56
+ // inspector below have fixed heights, so `flexGrow` here absorbs whatever
57
+ // the viewport actually offers.
58
+ if (visible.length === 0) {
59
+ return (_jsx(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { color: "subtle", children: "\u2014" }) }));
60
+ }
61
+ return (_jsx(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflow: "hidden", children: visible.map((node, offset) => {
62
+ const index = start + offset;
63
+ const focused = index === cursor;
64
+ const failed = node.status === 'error' || (node.burst !== undefined && burstErrors(node.burst) > 0);
65
+ const running = node.status === 'running';
66
+ const isNew = index >= arrivalFrom && arriving > 0;
67
+ const duration = node.burst === undefined ? node.durationMs : burstDurationMs(node.burst);
68
+ // ── structural rows are RULES, not rows ────────────────────────────
69
+ //
70
+ // A ledger with five hundred entries needs chapters. Turn and step
71
+ // are the session's own headings, and a heading that looks like a body
72
+ // row makes the whole list read as one undifferentiated stream. Two
73
+ // rule weights give the hierarchy the eye needs: heavy for a turn,
74
+ // hairline for a step, everything else a normal row. It also removes a
75
+ // redundancy — a `STEP` badge next to the label `step 2` said the same
76
+ // thing twice.
77
+ if (node.kind === 'turn' || node.kind === 'step') {
78
+ const isTurn = node.kind === 'turn';
79
+ const right = `${duration === undefined ? '' : formatDuration(duration)}${failed ? ' ✗' : ''}`;
80
+ // A step is a quiet row, not a rule. Steps are frequent — three or
81
+ // four per screen — and a full-width dashed line each drew more
82
+ // attention than the work between them. Only the turn, which is the
83
+ // session's actual chapter break, gets a rule.
84
+ if (!isTurn) {
85
+ return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: "subtle", children: `${focused ? '▸' : ' '}╵` }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { color: focused ? 'suggestion' : 'subtle', wrap: "truncate", children: node.label }) }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: heatColor(duration), children: costGlyph(duration) }) }), _jsx(Box, { flexShrink: 0, justifyContent: "flex-end", width: 7, children: _jsx(Text, { color: heatColor(duration), children: right }) })] }, `${node.seq}:step`));
86
+ }
87
+ const tone = failed ? 'error' : running ? 'success' : 'inactiveShimmer';
88
+ // Idle before a turn is wall-clock the session spent waiting on the
89
+ // human, and it is invisible everywhere else — every duration only
90
+ // ever accounts for work. Surfacing it here is what makes the clock
91
+ // column add up.
92
+ const previous = rows[index - 1];
93
+ const idle = previous === undefined ? 0 : node.time - (previous.time + (previous.durationMs ?? 0));
94
+ const idleText = idle >= IDLE_FLOOR_MS ? ` ⋯ ${formatDuration(idle)}` : '';
95
+ const head = `${focused ? '▸' : ' '}━━ ${node.label}${idleText} `;
96
+ const fill = Math.max(2, width - stringWidth(head) - stringWidth(right) - 2);
97
+ return (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { color: tone, bold: true, children: [`${focused ? '▸' : ' '}━━ ${node.label}`, _jsx(Text, { color: "subtle", children: idleText }), _jsx(Text, { color: "inactive", children: ` ${'━'.repeat(fill)} ` }), _jsx(Text, { color: failed ? 'error' : heatColor(duration), children: right })] }) }, `${node.seq}:turn`));
98
+ }
99
+ const spineColor = failed ? 'error' : running ? 'success' : node.seed === true ? 'subtle' : 'inactive';
100
+ const badgeBg = KIND_BADGE_BG[node.kind];
101
+ const badge = layout.badge === 6 ? KIND_BADGE[node.kind] : KIND_GLYPH[node.kind];
102
+ // Label and detail share one budget so a long tool name never pushes
103
+ // the duration column off the row.
104
+ const label = node.burst !== undefined ? `${node.label} ×${node.burst.members.length}` : node.label;
105
+ const detailBudget = Math.max(0, layout.detail - label.length - 1);
106
+ const detail = node.detail === undefined ? '' : previewText(node.detail, detailBudget);
107
+ const outcome = layout.outcome && node.outcome !== undefined && node.outcome !== ''
108
+ ? previewText(node.outcome, Math.max(8, Math.floor(layout.detail * 0.3)))
109
+ : '';
110
+ return (_jsxs(Box, { flexDirection: "row", width: "100%", height: 1, flexShrink: 0, gap: 1, children: [_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { color: spineColor, children: [focused ? '▸' : ' ', spineGlyph(rows, index)] }) }), layout.index && (_jsx(Box, { flexShrink: 0, width: 8, children: _jsx(Text, { color: "subtle", children: formatClock(node.time) }) })), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: isNew ? mix(theme[KIND_FG[node.kind]], theme.text, arriving) : KIND_FG[node.kind], backgroundColor: badgeBg, bold: true, children: badge }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsxs(Text, { wrap: "truncate", color: focused ? 'suggestion' : node.seed === true ? 'subtle' : undefined, children: [label, detail === '' ? '' : ' ', _jsx(Text, { color: focused ? 'suggestion' : 'inactive', children: detail }), outcome === '' ? '' : _jsx(Text, { color: "subtle", children: ` → ${outcome}` })] }) }), _jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: running ? 'success' : heatColor(duration), children: costGlyph(duration) }) }), _jsx(Box, { flexShrink: 0, justifyContent: "flex-end", width: 7, children: _jsx(Text, { color: running ? 'success' : heatColor(duration), children: running ? '…' : duration === undefined ? '' : formatDuration(duration) }) })] }, `${node.seq}:${node.kind}`));
111
+ }) }));
112
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { WaveBand } from '../../dsh-adapter/types.js';
3
+ /**
4
+ * Column budget for the mini wake at a given terminal width.
5
+ *
6
+ * It is the first thing to go on a narrow terminal: the status line's own
7
+ * fields (model, tps, branch, cwd) are what a user reads constantly, and a
8
+ * decoration that squeezes them is a decoration that has overstayed.
9
+ *
10
+ * @param columns - Terminal width in cells.
11
+ * @returns Glyph count, or 0 when the strip should not render at all.
12
+ */
13
+ export declare function miniWakeWidth(columns: number): number;
14
+ export declare function MiniWake({ band, hint, tick, }: {
15
+ /** The session projected onto {@link miniWakeWidth} columns. */
16
+ band: WaveBand;
17
+ /**
18
+ * Key hint shown once beside the strip, until the trajectory has been
19
+ * opened for the first time. Absent afterwards.
20
+ */
21
+ hint?: string;
22
+ tick: number;
23
+ }): React.ReactNode;
24
+ //# sourceMappingURL=MiniWake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MiniWake.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/MiniWake.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,4BAA4B,CAAA;AAwCvE;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,IAAI,GACL,EAAE;IACD,gEAAgE;IAChE,IAAI,EAAE,QAAQ,CAAA;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,KAAK,CAAC,SAAS,CAqClB"}
@@ -0,0 +1,99 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import chalk from 'chalk';
3
+ import { Box, Text, useTheme } from '../../ui.js';
4
+ import { getTheme } from '../../theme.js';
5
+ import { alive, mix } from '../../trajectory/motion.js';
6
+ import { parseRGB } from '../Spinner/spinnerUtils.js';
7
+ import { dominantChannel } from '../../dsh-adapter/trajectory/index.js';
8
+ /**
9
+ * The mini wake — the whole session as a dozen glyphs in the status line.
10
+ *
11
+ * This is the conversation's only permanent mention that a second view of the
12
+ * session exists, and it is deliberately not a label. A chip that says
13
+ * `trajectory · ctrl+t` is read once and then becomes furniture; a strip that
14
+ * *shows the session's shape* keeps earning its columns, because the shape
15
+ * changes. Density says how hard the session is working, colour says at what,
16
+ * a red column says something broke, and the breathing edge says it is still
17
+ * going. Wanting to zoom in on that is a more reliable motivation than being
18
+ * told a key exists.
19
+ *
20
+ * It also subsumes the unread-failure badge it replaces: a failure is already
21
+ * a red column here, in the position where it happened, which is strictly more
22
+ * information than a count in the corner.
23
+ *
24
+ * Cost is one row of nothing (it shares the hint row) and, at the default
25
+ * width, sixteen columns. The band itself is memoized by the caller against
26
+ * the row count, so a frame that only ticks the animation clock re-colours
27
+ * these cells and computes nothing.
28
+ */
29
+ /** Eight fill levels, same ramp as the full-scene wake. */
30
+ const BLOCKS = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
31
+ const FULL = '█';
32
+ const IDLE = '·';
33
+ const RUNNING = '▶';
34
+ /** Lane colour per channel. */
35
+ function channelColor(channel, theme) {
36
+ switch (channel) {
37
+ case 'input': return theme.professionalBlue;
38
+ case 'tool': return theme.chromeYellow;
39
+ case 'model': return theme.autoAccept;
40
+ default: return theme.subtle;
41
+ }
42
+ }
43
+ /**
44
+ * Column budget for the mini wake at a given terminal width.
45
+ *
46
+ * It is the first thing to go on a narrow terminal: the status line's own
47
+ * fields (model, tps, branch, cwd) are what a user reads constantly, and a
48
+ * decoration that squeezes them is a decoration that has overstayed.
49
+ *
50
+ * @param columns - Terminal width in cells.
51
+ * @returns Glyph count, or 0 when the strip should not render at all.
52
+ */
53
+ export function miniWakeWidth(columns) {
54
+ if (columns >= 120)
55
+ return 16;
56
+ if (columns >= 100)
57
+ return 12;
58
+ if (columns >= 84)
59
+ return 8;
60
+ return 0;
61
+ }
62
+ export function MiniWake({ band, hint, tick, }) {
63
+ const [themeName] = useTheme();
64
+ const theme = getTheme(themeName);
65
+ if (band.buckets.length === 0)
66
+ return null;
67
+ const logFloor = Math.log1p(Math.max(0, band.floor));
68
+ const logSpan = Math.max(1e-6, Math.log1p(Math.max(1, band.peak)) - logFloor);
69
+ const breath = alive(tick);
70
+ let strip = '';
71
+ for (const bucket of band.buckets) {
72
+ if (bucket.count === 0) {
73
+ strip += chalk.hex(toHex(theme.subtle))(IDLE);
74
+ continue;
75
+ }
76
+ if (bucket.running) {
77
+ strip += chalk.hex(toHex(mix(theme.success, theme.planMode, breath)))(RUNNING);
78
+ continue;
79
+ }
80
+ const level = Math.min(BLOCKS.length, Math.max(1, Math.round(((Math.log1p(bucket.weight) - logFloor) / logSpan) * (BLOCKS.length - 1)) + 1));
81
+ const failed = bucket.error || bucket.retry;
82
+ // A failure is raised to at least half height: at this size a one-level
83
+ // red cell is easy to miss, and missing it defeats the point.
84
+ const shown = failed ? Math.max(level, 4) : level;
85
+ const colour = failed ? theme.error : channelColor(dominantChannel(bucket), theme);
86
+ strip += chalk.hex(toHex(colour))(shown >= BLOCKS.length ? FULL : BLOCKS[shown - 1]);
87
+ }
88
+ return (_jsxs(Box, { flexShrink: 0, flexDirection: "row", gap: 1, children: [_jsx(Text, { children: strip }), hint !== undefined ? _jsx(Text, { color: "subtle", children: hint }) : null] }));
89
+ }
90
+ /** Theme colour → `#rrggbb`, the form chalk needs. */
91
+ function toHex(colour) {
92
+ if (colour.startsWith('#'))
93
+ return colour;
94
+ const parsed = parseRGB(colour);
95
+ if (parsed === null)
96
+ return '#8D95A6';
97
+ const hex = (value) => value.toString(16).padStart(2, '0');
98
+ return `#${hex(parsed.r)}${hex(parsed.g)}${hex(parsed.b)}`;
99
+ }
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import type { WaveBand as Band } from '../../dsh-adapter/types.js';
3
+ export declare function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, }: {
4
+ band: Band;
5
+ /** Rendered width in cells; equals `band.buckets.length`. */
6
+ width: number;
7
+ /** Column the ledger cursor currently sits in. */
8
+ cursorColumn: number;
9
+ /** First and last column covered by the visible ledger window. */
10
+ viewportStart: number;
11
+ viewportEnd: number;
12
+ /**
13
+ * Columns containing a query match, or `undefined` when no query is active.
14
+ * Non-matching columns drop to grey so the match distribution across the
15
+ * whole session is visible at a glance; the silhouette never changes.
16
+ */
17
+ matches?: ReadonlySet<number>;
18
+ /** Scene clock tick. */
19
+ tick: number;
20
+ /** Tick the most recent alert was triggered on. */
21
+ alertTick: number;
22
+ }): React.ReactNode;
23
+ /**
24
+ * Convert a theme colour to the `#rrggbb` form chalk needs.
25
+ *
26
+ * Theme values are `rgb(r,g,b)` strings; a custom theme may instead carry an
27
+ * ANSI name, which cannot be blended — those fall back to a neutral grey
28
+ * rather than crashing chalk's hex parser.
29
+ */
30
+ declare function toHex(colour: string): string;
31
+ /** Shared by the scene so every chalk colour goes through one conversion. */
32
+ export { toHex as waveHex };
33
+ //# sourceMappingURL=WaveBand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WaveBand.d.ts","sourceRoot":"","sources":["../../../../src/components/trajectory/WaveBand.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,QAAQ,IAAI,IAAI,EAAe,MAAM,4BAA4B,CAAA;AAmD/E,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EACX,OAAO,EACP,IAAI,EACJ,SAAS,GACV,EAAE;IACD,IAAI,EAAE,IAAI,CAAA;IACV,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC7B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,KAAK,CAAC,SAAS,CAgGlB;AAED;;;;;;GAMG;AACH,iBAAS,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrC;AAED,6EAA6E;AAC7E,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAA"}
@@ -0,0 +1,145 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import chalk from 'chalk';
3
+ import { Box, Text, useTheme } from '../../ui.js';
4
+ import { getTheme } from '../../theme.js';
5
+ import { alert, alive, mix } from '../../trajectory/motion.js';
6
+ import { parseRGB } from '../Spinner/spinnerUtils.js';
7
+ import { dominantChannel } from '../../dsh-adapter/trajectory/index.js';
8
+ /**
9
+ * The wake — the whole session drawn as one row of glyphs.
10
+ *
11
+ * A session is a shape before it is a list: dense here, idle there, one red
12
+ * mark where it broke. Three lanes of coloured blocks (the form the official
13
+ * web overview uses, where vertical space is free) collapse badly into a
14
+ * terminal, so they are composed into a single band whose **height** carries
15
+ * cost and whose **colour** carries what kind of work it was.
16
+ *
17
+ * ## One row, two rows deep in information
18
+ *
19
+ * A two-row stack was tried for the extra eight levels of resolution and read
20
+ * WORSE: with a log scale anchored at the smallest column, a typical column
21
+ * lands near 55%, which in a two-row bar means "lower row solid, upper row a
22
+ * sliver" — the band turns into a slab. One row of eight levels, over weights
23
+ * that now carry real cost, produces the varied silhouette the band is for.
24
+ * The rows saved go to the ledger, which always wants more.
25
+ *
26
+ * ## Failures ride in the band, not above it
27
+ *
28
+ * A dedicated marker row spends a whole line to show three glyphs. A failed
29
+ * column is simply drawn in the failure colour instead: red among amber and
30
+ * violet is unmissable, and the failure becomes *part of* the session's shape
31
+ * rather than an annotation over it.
32
+ *
33
+ * Every animated cell changes colour only — never a glyph count, never a row
34
+ * count (see `trajectory/motion.ts`).
35
+ */
36
+ /** Eight fill levels. */
37
+ const BLOCKS = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
38
+ const FULL = '█';
39
+ /** A column with no activity at all. */
40
+ const IDLE = '·';
41
+ /** The live edge. */
42
+ const RUNNING = '▶';
43
+ const LEVELS = BLOCKS.length;
44
+ /** Lane colour per channel, resolved from the active theme. */
45
+ function channelColor(channel, theme) {
46
+ switch (channel) {
47
+ case 'input': return theme.professionalBlue;
48
+ case 'tool': return theme.chromeYellow;
49
+ case 'model': return theme.autoAccept;
50
+ default: return theme.subtle;
51
+ }
52
+ }
53
+ export function WaveBand({ band, width, cursorColumn, viewportStart, viewportEnd, matches, tick, alertTick, }) {
54
+ const [themeName] = useTheme();
55
+ const theme = getTheme(themeName);
56
+ if (band.buckets.length === 0) {
57
+ return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Text, { color: "subtle", children: IDLE.repeat(Math.max(0, width)) }), _jsx(Text, { color: "subtle", children: ' '.repeat(Math.max(0, width)) })] }));
58
+ }
59
+ // Normalize between the smallest non-empty column and the p95 column, both
60
+ // in log space: the smallest real activity is one level, the busiest tops
61
+ // out, and four orders of magnitude in between stay distinguishable.
62
+ const logFloor = Math.log1p(Math.max(0, band.floor));
63
+ const logSpan = Math.max(1e-6, Math.log1p(Math.max(1, band.peak)) - logFloor);
64
+ const alertPhase = alert(tick, alertTick);
65
+ const breath = alive(tick);
66
+ let wave = '';
67
+ for (let column = 0; column < band.buckets.length; column++) {
68
+ const bucket = band.buckets[column];
69
+ const dimmed = matches !== undefined && !matches.has(column);
70
+ const isCursor = column === cursorColumn;
71
+ if (bucket.count === 0) {
72
+ wave += chalk.hex(toHex(theme.subtle))(IDLE);
73
+ continue;
74
+ }
75
+ if (bucket.running) {
76
+ wave += chalk.hex(toHex(mix(theme.success, theme.planMode, breath)))(RUNNING);
77
+ continue;
78
+ }
79
+ // 1..LEVELS — a non-empty column is never invisible.
80
+ const level = Math.min(LEVELS, Math.max(1, Math.round(((Math.log1p(bucket.weight) - logFloor) / logSpan) * (LEVELS - 1)) + 1));
81
+ const failed = bucket.error || bucket.retry;
82
+ const base = failed
83
+ ? mix(theme.error, theme.warningShimmer, alertPhase)
84
+ : channelColor(dominantChannel(bucket), theme);
85
+ const colour = dimmed
86
+ ? theme.subtle
87
+ : isCursor
88
+ ? mix(base, theme.permissionShimmer, 0.55)
89
+ : base;
90
+ const hex = toHex(colour);
91
+ // A failed column is never allowed to be one pixel tall: it is raised to
92
+ // at least half height so the red is visible at a glance, which is the
93
+ // whole point of colouring it.
94
+ const shown = failed ? Math.max(level, Math.ceil(LEVELS / 2)) : level;
95
+ wave += chalk.hex(hex)(shown >= LEVELS ? FULL : BLOCKS[shown - 1]);
96
+ }
97
+ // ── ruler: turn numbers plus the viewport bracket ─────────────────────────
98
+ const ruler = Array.from({ length: band.buckets.length }, () => ' ');
99
+ // Turn numbers, not anonymous ticks: the ruler is how `{ }` navigation is
100
+ // aimed. A label that would collide with the previous one degrades to a
101
+ // tick rather than overwriting digits into nonsense.
102
+ let lastLabelEnd = -Infinity;
103
+ for (const [turn, column] of band.turns) {
104
+ if (column >= ruler.length)
105
+ continue;
106
+ const label = String(turn);
107
+ if (column - 1 <= lastLabelEnd) {
108
+ ruler[column] = '╵';
109
+ continue;
110
+ }
111
+ for (let offset = 0; offset < label.length && column + offset < ruler.length; offset++) {
112
+ ruler[column + offset] = label[offset];
113
+ }
114
+ lastLabelEnd = column + label.length;
115
+ }
116
+ const from = Math.max(0, Math.min(band.buckets.length - 1, viewportStart));
117
+ const to = Math.max(from, Math.min(band.buckets.length - 1, viewportEnd));
118
+ let rulerText = '';
119
+ for (let column = 0; column < ruler.length; column++) {
120
+ const inViewport = column >= from && column <= to;
121
+ const glyph = inViewport ? (column === from ? '▐' : column === to ? '▌' : '▀') : ruler[column];
122
+ rulerText += inViewport
123
+ ? chalk.hex(toHex(theme.permission))(glyph)
124
+ : chalk.hex(toHex(theme.subtle))(glyph);
125
+ }
126
+ return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Text, { children: wave }), _jsx(Text, { children: rulerText })] }));
127
+ }
128
+ /**
129
+ * Convert a theme colour to the `#rrggbb` form chalk needs.
130
+ *
131
+ * Theme values are `rgb(r,g,b)` strings; a custom theme may instead carry an
132
+ * ANSI name, which cannot be blended — those fall back to a neutral grey
133
+ * rather than crashing chalk's hex parser.
134
+ */
135
+ function toHex(colour) {
136
+ if (colour.startsWith('#'))
137
+ return colour;
138
+ const parsed = parseRGB(colour);
139
+ if (parsed === null)
140
+ return '#8D95A6';
141
+ const hex = (value) => value.toString(16).padStart(2, '0');
142
+ return `#${hex(parsed.r)}${hex(parsed.g)}${hex(parsed.b)}`;
143
+ }
144
+ /** Shared by the scene so every chalk colour goes through one conversion. */
145
+ export { toHex as waveHex };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * User-defined color themes for dsh-tui.
3
3
  *
4
- * A theme is a JSON file in `~/.dsh-cc/themes/<name>.json`:
4
+ * A theme is a JSON file in `~/.dsh-tui/themes/<name>.json`:
5
5
  *
6
6
  * ```json
7
7
  * { "name": "sakura", "displayName": "Sakura Pink", "base": "dark",
@@ -23,7 +23,7 @@ import { type Theme } from './theme.js';
23
23
  /** The base palettes a user theme may overlay. */
24
24
  export declare const THEME_BASE_NAMES: readonly ["light", "dark", "dark-ansi"];
25
25
  export type ThemeBase = (typeof THEME_BASE_NAMES)[number];
26
- /** The directory user theme files live in (~/.dsh-cc/themes). */
26
+ /** The directory user theme files live in (~/.dsh-tui/themes). */
27
27
  export declare const CUSTOM_THEME_DIR: string;
28
28
  /** A validated user theme file. `colors` only carries accepted overrides. */
29
29
  export type CustomThemeSpec = {
@@ -40,7 +40,7 @@ export type CustomThemeSpec = {
40
40
  };
41
41
  /**
42
42
  * Whether a name is safe to use as a file name (no path separators or dot
43
- * traversal). Theme names are user input from CC_TUI_THEME and /theme, so
43
+ * traversal). Theme names are user input from DSH_TUI_THEME and /theme, so
44
44
  * they must never escape the themes directory.
45
45
  */
46
46
  export declare function isSafeThemeName(name: string): boolean;
@@ -92,9 +92,9 @@ export declare function buildTheme(spec: CustomThemeSpec): Theme;
92
92
  */
93
93
  export declare function resolveCustomTheme(name: string): Theme | undefined;
94
94
  /**
95
- * Whether a name selects a usable theme: a built-in palette or a valid user
96
- * theme file. Used for CC_TUI_THEME / persisted-preference validation and
97
- * the runtime /theme switch.
95
+ * Whether a name selects a usable theme: a built-in palette, the `auto`
96
+ * pseudo-theme, or a valid user theme file. Used for DSH_TUI_THEME /
97
+ * persisted-preference validation and the runtime /theme switch.
98
98
  * @param name - Candidate theme name.
99
99
  * @returns True when the theme resolves.
100
100
  */
@@ -1 +1 @@
1
- {"version":3,"file":"customTheme.d.ts","sourceRoot":"","sources":["../../src/customTheme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,EAAyB,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAE9D,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,yCAA0C,CAAA;AACvE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzD,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,QAAuC,CAAA;AAEpE,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAA;IACZ,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,IAAI,EAAE,SAAS,CAAA;IACf,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IACtB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA2CD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAUjE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,eAAe,GAAG,SAAS,CAkE7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAyB,GAC7B,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAyB,GAAG,eAAe,EAAE,CAclF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAWlE;AAcD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGtD;AAED,4FAA4F;AAC5F,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C"}
1
+ {"version":3,"file":"customTheme.d.ts","sourceRoot":"","sources":["../../src/customTheme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EAA0C,KAAK,KAAK,EAAE,MAAM,YAAY,CAAA;AAG/E,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,yCAA0C,CAAA;AACvE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzD,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,QAA2B,CAAA;AAExD,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAA;IACZ,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,IAAI,EAAE,SAAS,CAAA;IACf,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IACtB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA2CD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAUjE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,eAAe,GAAG,SAAS,CAqE7B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAyB,GAC7B,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAyB,GAAG,eAAe,EAAE,CAclF;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAWlE;AAcD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGtD;AAED,4FAA4F;AAC5F,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C"}