@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,653 @@
1
+ /**
2
+ * Trajectory projection — folding the session event log into ledger nodes.
3
+ *
4
+ * ## What this is
5
+ *
6
+ * The DSH session log is an append-only stream of ~44 event types. This
7
+ * module folds it into the flat, turn-annotated node list the trajectory
8
+ * scene renders, pairing every bracket (`tool/call` ↔ `tool/result`,
9
+ * `step/start` ↔ `step/end`, `llm/retry` ↔ `llm/retry-started`,
10
+ * `approval/asked` ↔ `approval/decided`, `compaction/start` ↔
11
+ * `compaction/end`, `tool/code-dispatch-start` ↔ `tool/code-dispatch`) so a
12
+ * row can show its own wall-clock duration and outcome.
13
+ *
14
+ * ## Incrementality
15
+ *
16
+ * `agent.session.events` is an immutable snapshot whose element objects are
17
+ * frozen at append and REUSED until the next append. {@link extendTrajectory}
18
+ * exploits exactly that: when the incoming snapshot prefix-extends the one the
19
+ * previous build consumed — proven by *object identity* at the previous last
20
+ * index, never by `seq` arithmetic, which a fork can rewind — only the new
21
+ * tail is folded. Any other relationship (agent swap on `/resume`, `/rewind`,
22
+ * `/new`) rebuilds from scratch. A long session therefore never pays an O(n)
23
+ * refold per frame, and `verify-trace-projection` asserts that the incremental
24
+ * and from-scratch results are field-for-field identical at every split point.
25
+ *
26
+ * ## What it deliberately does not do
27
+ *
28
+ * No node holds derived text. `detail`/`outcome` are references into strings
29
+ * the log already owns, and the view flattens only the rows it paints (see
30
+ * {@link previewText}). Full content is not held at all — `seq`/`endSeq`
31
+ * address the owning events for the inspector to re-read on demand.
32
+ *
33
+ * Storage-level chunk packing (`text-chunks`, `reasoning-chunks`,
34
+ * `tool-call-chunks`) is a durable *encoding*, not an event vocabulary: the
35
+ * persistence reader expands those rows back into `assistant/chunk` events
36
+ * before they reach `Session.events`, so this fold only ever sees the
37
+ * expanded form.
38
+ */
39
+ import { asRawEvents, isApprovalDenied, readApprovalAsked, readApprovalDecided, readCommandRun, readCompaction, readDispatch, readHook, readModeValue, readRequestHeader, readRetry, readRetryStarted, readSubagent, readTodos, } from './guards.js';
40
+ import { BURST_MIN } from './types.js';
41
+ /** Fresh, empty fold state. */
42
+ function newState() {
43
+ return {
44
+ counts: { rows: 0, errors: 0, retries: 0 },
45
+ tools: new Map(),
46
+ subtools: new Map(),
47
+ steps: new Map(),
48
+ turns: new Map(),
49
+ retries: new Map(),
50
+ approvals: new Map(),
51
+ hooks: new Map(),
52
+ compactions: [],
53
+ turn: 0,
54
+ step: undefined,
55
+ seeding: true,
56
+ runKey: undefined,
57
+ runCount: 0,
58
+ runStart: -1,
59
+ runMembers: [],
60
+ };
61
+ }
62
+ /**
63
+ * Clone the fold state for a continuation.
64
+ *
65
+ * The bracket maps are copied so a continuation does not mutate its input's
66
+ * bookkeeping — but `runMembers` is deliberately SHARED, not copied: once a
67
+ * run reaches {@link BURST_MIN} the synthetic burst node holds that very
68
+ * array, and a run that spans an incremental boundary must keep growing the
69
+ * array the node already references. Copying it here would silently freeze
70
+ * every burst at the length it had when the append arrived.
71
+ *
72
+ * Like the node list itself, a build is consumed once — extending the same
73
+ * `previous` twice with different tails is not supported (and matches the
74
+ * pre-existing trace fold's contract).
75
+ */
76
+ function cloneState(previous) {
77
+ return {
78
+ // Counters are shared, not copied: like `nodes`, they belong to the build
79
+ // being extended, and a continuation must keep incrementing the same
80
+ // object the caller already holds.
81
+ counts: previous.counts,
82
+ tools: new Map(previous.tools),
83
+ subtools: new Map(previous.subtools),
84
+ steps: new Map(previous.steps),
85
+ turns: new Map(previous.turns),
86
+ retries: new Map(previous.retries),
87
+ approvals: new Map(previous.approvals),
88
+ hooks: new Map(previous.hooks),
89
+ compactions: [...previous.compactions],
90
+ turn: previous.turn,
91
+ step: previous.step,
92
+ seeding: previous.seeding,
93
+ runKey: previous.runKey,
94
+ runCount: previous.runCount,
95
+ runStart: previous.runStart,
96
+ runMembers: previous.runMembers,
97
+ };
98
+ }
99
+ /** Read the first text block of a model-message content array. */
100
+ function firstText(content) {
101
+ if (!Array.isArray(content))
102
+ return undefined;
103
+ for (const block of content) {
104
+ if (typeof block !== 'object' || block === null)
105
+ continue;
106
+ const record = block;
107
+ if (record.type === 'text' && typeof record.text === 'string')
108
+ return record.text;
109
+ }
110
+ return undefined;
111
+ }
112
+ /** Read token accounting off an `assistant/message` payload. */
113
+ function readTokens(usage) {
114
+ if (typeof usage !== 'object' || usage === null)
115
+ return undefined;
116
+ const record = usage;
117
+ const pick = (key) => {
118
+ const value = record[key];
119
+ return typeof value === 'number' && Number.isFinite(value) ? value : 0;
120
+ };
121
+ const tokens = {
122
+ input: pick('input'),
123
+ output: pick('output'),
124
+ // The reasoning-token field has varied by adapter generation; accept both
125
+ // spellings and fall back to zero rather than dropping the whole usage.
126
+ think: pick('think') || pick('reasoning'),
127
+ cacheRead: pick('cacheRead'),
128
+ cacheWrite: pick('cacheWrite'),
129
+ };
130
+ const total = tokens.input + tokens.output + tokens.think + tokens.cacheRead + tokens.cacheWrite;
131
+ return total > 0 ? tokens : undefined;
132
+ }
133
+ /** Close a bracket node with its own duration and outcome. */
134
+ function close(state, node, event, status, errorCode) {
135
+ if (node === undefined)
136
+ return;
137
+ if (status === 'error' && node.status !== 'error')
138
+ state.counts.errors += 1;
139
+ node.endSeq = event.seq;
140
+ node.durationMs = Math.max(0, event.time - node.time);
141
+ node.status = status;
142
+ if (errorCode !== undefined)
143
+ node.errorCode = errorCode;
144
+ }
145
+ /**
146
+ * Append a node, folding runs of >= {@link BURST_MIN} consecutive same-name
147
+ * tool/subtool calls into one synthetic burst row.
148
+ *
149
+ * The run's members stay live: the pairing maps still hold the very objects
150
+ * `close(state, )` mutates when their results land, and the burst reads its totals
151
+ * off them on demand. Nothing needs re-visiting when a folded member closes.
152
+ */
153
+ function push(state, nodes, node) {
154
+ const foldable = node.kind === 'tool' || node.kind === 'subtool';
155
+ const key = foldable ? `${node.kind}:${node.label}` : undefined;
156
+ if (key !== undefined && key === state.runKey) {
157
+ state.runCount += 1;
158
+ state.runMembers.push(node);
159
+ if (state.runCount < BURST_MIN) {
160
+ // Below the fold threshold the run is still shown call by call; the
161
+ // rows only merge once the run proves long enough to be noise.
162
+ nodes.push(node);
163
+ return;
164
+ }
165
+ if (state.runCount === BURST_MIN) {
166
+ // Replace the run's rows with one synthetic burst node. The head's
167
+ // position is reused so surrounding order is untouched; rows after it
168
+ // cannot exist, because a run is by definition the ledger's tail.
169
+ const head = state.runMembers[0];
170
+ nodes.length = state.runStart;
171
+ nodes.push({
172
+ seq: head.seq,
173
+ time: head.time,
174
+ kind: head.kind,
175
+ turn: head.turn,
176
+ step: head.step,
177
+ label: head.label,
178
+ callId: head.callId,
179
+ subCallId: head.subCallId,
180
+ seed: head.seed,
181
+ burst: { name: head.label, members: state.runMembers },
182
+ });
183
+ }
184
+ // Beyond BURST_MIN the burst node already references `runMembers`, which
185
+ // was appended to above — nothing further to do.
186
+ return;
187
+ }
188
+ state.runKey = key;
189
+ state.runCount = key === undefined ? 0 : 1;
190
+ state.runStart = nodes.length;
191
+ state.runMembers = key === undefined ? [] : [node];
192
+ nodes.push(node);
193
+ }
194
+ /** Row count after burst folding — the ledger's own length. */
195
+ function syncRowCount(state, nodes) {
196
+ state.counts.rows = nodes.length;
197
+ }
198
+ /** Fold one event into the working build. */
199
+ function consume(state, nodes, timing, event) {
200
+ const data = event.data;
201
+ const base = { seq: event.seq, time: event.time, seed: state.seeding || undefined };
202
+ switch (event.type) {
203
+ case 'session/end-seed': {
204
+ // Everything folded so far came from a replayed seed. Re-mark rather
205
+ // than trusting the first occurrence: a re-seeded log carries more than
206
+ // one, and only the LAST one bounds the inherited history.
207
+ for (const node of nodes)
208
+ node.seed = true;
209
+ state.seeding = false;
210
+ return;
211
+ }
212
+ case 'turn/start': {
213
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn + 1;
214
+ state.turn = turn;
215
+ state.step = undefined;
216
+ const node = { ...base, kind: 'turn', turn, label: `turn ${turn}`, status: 'running' };
217
+ state.turns.set(turn, node);
218
+ push(state, nodes, node);
219
+ return;
220
+ }
221
+ case 'turn/end': {
222
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
223
+ const open = state.turns.get(turn);
224
+ const reason = data?.reason;
225
+ const kind = typeof reason === 'object' && reason !== null
226
+ ? reason.kind
227
+ : undefined;
228
+ close(state, open, event, kind === 'completed' ? 'ok' : 'error', typeof kind === 'string' && kind !== 'completed' ? kind : undefined);
229
+ state.turns.delete(turn);
230
+ state.step = undefined;
231
+ return;
232
+ }
233
+ case 'step/start': {
234
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
235
+ const step = typeof data?.step === 'number' ? data.step : 0;
236
+ state.turn = turn;
237
+ state.step = step;
238
+ timing.set(`${turn}:${step}`, { startTime: event.time });
239
+ const node = { ...base, kind: 'step', turn, step, label: `step ${step}`, status: 'running' };
240
+ state.steps.set(`${turn}:${step}`, node);
241
+ push(state, nodes, node);
242
+ return;
243
+ }
244
+ case 'step/end': {
245
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
246
+ const step = typeof data?.step === 'number' ? data.step : (state.step ?? 0);
247
+ const key = `${turn}:${step}`;
248
+ close(state, state.steps.get(key), event, 'ok');
249
+ state.steps.delete(key);
250
+ const slot = timing.get(key);
251
+ if (slot !== undefined)
252
+ slot.endTime = event.time;
253
+ state.step = undefined;
254
+ return;
255
+ }
256
+ case 'assistant/chunk': {
257
+ // Chunks never become rows; they contribute only the two timestamps
258
+ // that separate time-to-first-token from decode throughput.
259
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
260
+ const step = typeof data?.step === 'number' ? data.step : (state.step ?? 0);
261
+ const slot = timing.get(`${turn}:${step}`);
262
+ if (slot === undefined)
263
+ return;
264
+ slot.firstChunk ??= event.time;
265
+ slot.lastChunk = event.time;
266
+ return;
267
+ }
268
+ case 'user/message': {
269
+ const source = data?.source;
270
+ const sourceKind = typeof source === 'object' && source !== null
271
+ ? source.kind
272
+ : undefined;
273
+ const text = firstText(data?.content);
274
+ if (text === undefined || text.trim() === '')
275
+ return;
276
+ // A direct human prompt is a USER row; everything else on the user-role
277
+ // surface (skill bodies, file-change notices, goal continuations) is an
278
+ // injected CONTEXT row — same distinction the official ledger draws.
279
+ const isHuman = sourceKind === 'user';
280
+ const sourceName = typeof source === 'object' && source !== null
281
+ ? source.name
282
+ : undefined;
283
+ push(state, nodes, {
284
+ ...base,
285
+ kind: isHuman ? 'user' : 'context',
286
+ turn: state.turn,
287
+ step: state.step,
288
+ label: isHuman ? '' : (sourceName ?? (typeof sourceKind === 'string' ? sourceKind : 'context')),
289
+ detail: text,
290
+ });
291
+ return;
292
+ }
293
+ case 'assistant/message': {
294
+ const turn = typeof data?.turn === 'number' ? data.turn : state.turn;
295
+ const step = typeof data?.step === 'number' ? data.step : state.step;
296
+ const message = data?.message;
297
+ const content = typeof message === 'object' && message !== null
298
+ ? message.content
299
+ : undefined;
300
+ const tokens = readTokens(data?.usage);
301
+ let first = true;
302
+ if (Array.isArray(content)) {
303
+ for (const block of content) {
304
+ if (typeof block !== 'object' || block === null)
305
+ continue;
306
+ const record = block;
307
+ const text = typeof record.text === 'string' ? record.text : '';
308
+ if (text.trim() === '')
309
+ continue;
310
+ const kind = record.type === 'reasoning' ? 'thinking' : record.type === 'text' ? 'assistant' : 'assistant';
311
+ if (record.type !== 'reasoning' && record.type !== 'text')
312
+ continue;
313
+ push(state, nodes, {
314
+ ...base,
315
+ kind,
316
+ turn,
317
+ step,
318
+ label: '',
319
+ detail: text,
320
+ // Usage belongs to the step, not to each block: attach it to the
321
+ // first row so the hotspot aggregate counts it exactly once.
322
+ tokens: first ? tokens : undefined,
323
+ });
324
+ first = false;
325
+ }
326
+ }
327
+ return;
328
+ }
329
+ case 'tool/call': {
330
+ const callId = typeof data?.callId === 'string' ? data.callId : undefined;
331
+ const name = typeof data?.name === 'string' ? data.name : 'tool';
332
+ const args = typeof data?.arguments === 'string' ? data.arguments : undefined;
333
+ const node = {
334
+ ...base,
335
+ kind: 'tool',
336
+ turn: typeof data?.turn === 'number' ? data.turn : state.turn,
337
+ step: typeof data?.step === 'number' ? data.step : state.step,
338
+ label: name,
339
+ detail: args,
340
+ callId,
341
+ status: 'running',
342
+ };
343
+ if (callId !== undefined)
344
+ state.tools.set(callId, node);
345
+ push(state, nodes, node);
346
+ return;
347
+ }
348
+ case 'tool/result': {
349
+ const message = data?.message;
350
+ const source = typeof message === 'object' && message !== null
351
+ ? message.source
352
+ : undefined;
353
+ const callId = typeof source === 'object' && source !== null
354
+ ? source.callId
355
+ : undefined;
356
+ if (callId === undefined)
357
+ return;
358
+ const open = state.tools.get(callId);
359
+ if (open === undefined)
360
+ return;
361
+ const error = data?.error;
362
+ const code = typeof error === 'object' && error !== null
363
+ ? error.code
364
+ : undefined;
365
+ open.outcome = firstText(typeof message === 'object' && message !== null
366
+ ? message.content
367
+ : undefined);
368
+ close(state, open, event, error === undefined ? 'ok' : 'error', code);
369
+ state.tools.delete(callId);
370
+ return;
371
+ }
372
+ case 'tool/code-dispatch-start': {
373
+ const payload = readDispatch(event.data);
374
+ if (payload === undefined)
375
+ return;
376
+ const node = {
377
+ ...base,
378
+ kind: 'subtool',
379
+ turn: state.turn,
380
+ step: state.step,
381
+ label: payload.name,
382
+ detail: payload.args,
383
+ callId: payload.rootCallId,
384
+ subCallId: payload.subCallId,
385
+ status: 'running',
386
+ };
387
+ state.subtools.set(payload.subCallId, node);
388
+ push(state, nodes, node);
389
+ return;
390
+ }
391
+ case 'tool/code-dispatch': {
392
+ const payload = readDispatch(event.data);
393
+ if (payload === undefined)
394
+ return;
395
+ const open = state.subtools.get(payload.subCallId);
396
+ if (open === undefined)
397
+ return;
398
+ close(state, open, event, payload.isError === true ? 'error' : 'ok');
399
+ state.subtools.delete(payload.subCallId);
400
+ return;
401
+ }
402
+ case 'llm/retry': {
403
+ const payload = readRetry(event.data);
404
+ if (payload === undefined)
405
+ return;
406
+ const existing = state.retries.get(payload.retryId);
407
+ if (existing !== undefined) {
408
+ // Same retry sequence, next attempt: keep one row and accumulate.
409
+ existing.attempts = (existing.attempts ?? 1) + 1;
410
+ existing.durationMs = (existing.durationMs ?? 0) + payload.delayMs;
411
+ state.counts.retries += 1;
412
+ return;
413
+ }
414
+ const node = {
415
+ ...base,
416
+ kind: 'retry',
417
+ turn: payload.turn ?? state.turn,
418
+ step: payload.step ?? state.step,
419
+ label: payload.code ?? 'retry',
420
+ detail: payload.message,
421
+ status: 'running',
422
+ errorCode: payload.code,
423
+ attempts: 1,
424
+ durationMs: payload.delayMs,
425
+ };
426
+ state.retries.set(payload.retryId, node);
427
+ state.counts.retries += 1;
428
+ state.counts.errors += 1;
429
+ push(state, nodes, node);
430
+ return;
431
+ }
432
+ case 'llm/retry-started': {
433
+ const retryId = readRetryStarted(event.data);
434
+ if (retryId === undefined)
435
+ return;
436
+ const open = state.retries.get(retryId);
437
+ if (open === undefined)
438
+ return;
439
+ // The bracket closes when the retried request starts; the accumulated
440
+ // backoff is the row's own duration, so `close(state, )` must not overwrite it.
441
+ open.endSeq = event.seq;
442
+ open.status = 'ok';
443
+ state.retries.delete(retryId);
444
+ return;
445
+ }
446
+ case 'approval/asked': {
447
+ const payload = readApprovalAsked(event.data);
448
+ if (payload === undefined)
449
+ return;
450
+ const node = {
451
+ ...base,
452
+ kind: 'approval',
453
+ turn: state.turn,
454
+ step: state.step,
455
+ label: payload.toolName ?? 'approval',
456
+ detail: payload.reason,
457
+ callId: payload.callId,
458
+ status: 'running',
459
+ };
460
+ state.approvals.set(payload.id, node);
461
+ push(state, nodes, node);
462
+ return;
463
+ }
464
+ case 'approval/decided': {
465
+ const payload = readApprovalDecided(event.data);
466
+ if (payload === undefined)
467
+ return;
468
+ const open = state.approvals.get(payload.id);
469
+ if (open === undefined)
470
+ return;
471
+ open.outcome = payload.outcome;
472
+ close(state, open, event, isApprovalDenied(payload.outcome) ? 'error' : 'ok');
473
+ state.approvals.delete(payload.id);
474
+ return;
475
+ }
476
+ case 'hook/invoked': {
477
+ const payload = readHook(event.data);
478
+ if (payload === undefined)
479
+ return;
480
+ const node = {
481
+ ...base,
482
+ kind: 'system',
483
+ turn: state.turn,
484
+ step: state.step,
485
+ label: `hook ${payload.name}`,
486
+ detail: payload.event,
487
+ status: 'running',
488
+ };
489
+ if (payload.id !== undefined)
490
+ state.hooks.set(payload.id, node);
491
+ push(state, nodes, node);
492
+ return;
493
+ }
494
+ case 'hook/result': {
495
+ const payload = readHook(event.data);
496
+ const open = payload?.id === undefined ? undefined : state.hooks.get(payload.id);
497
+ if (open === undefined)
498
+ return;
499
+ close(state, open, event, 'ok');
500
+ state.hooks.delete(payload.id);
501
+ return;
502
+ }
503
+ case 'compaction/start': {
504
+ const payload = readCompaction(event.data);
505
+ const node = {
506
+ ...base,
507
+ kind: 'compaction',
508
+ turn: state.turn,
509
+ step: state.step,
510
+ label: 'compaction',
511
+ detail: payload.reason,
512
+ status: 'running',
513
+ };
514
+ state.compactions.push(node);
515
+ push(state, nodes, node);
516
+ return;
517
+ }
518
+ case 'compaction/end': {
519
+ const open = state.compactions.pop();
520
+ const payload = readCompaction(event.data);
521
+ if (open !== undefined && payload.removed !== undefined) {
522
+ open.outcome = `-${payload.removed}`;
523
+ }
524
+ close(state, open, event, 'ok');
525
+ return;
526
+ }
527
+ case 'request/header': {
528
+ const payload = readRequestHeader(event.data);
529
+ // Only a *change* is a row: 'initial' and 'resume' restate the route
530
+ // the header line already shows, and would add one noise row per turn.
531
+ if (payload === undefined || payload.reason !== 'change')
532
+ return;
533
+ push(state, nodes, {
534
+ ...base,
535
+ kind: 'system',
536
+ turn: state.turn,
537
+ step: state.step,
538
+ label: payload.model ?? 'route',
539
+ detail: payload.effort === undefined ? undefined : `effort=${payload.effort}`,
540
+ });
541
+ return;
542
+ }
543
+ case 'subagent/descriptor': {
544
+ const payload = readSubagent(event.data);
545
+ if (payload === undefined)
546
+ return;
547
+ push(state, nodes, {
548
+ ...base,
549
+ kind: 'context',
550
+ turn: state.turn,
551
+ step: state.step,
552
+ label: 'subagent',
553
+ detail: [payload.label, payload.model].filter(Boolean).join(' · ') || undefined,
554
+ });
555
+ return;
556
+ }
557
+ case 'sandbox/mode':
558
+ case 'plan/mode':
559
+ case 'approval/policy':
560
+ case 'permission/preset':
561
+ case 'agent-preset/selected': {
562
+ const value = readModeValue(event.data);
563
+ if (value === undefined)
564
+ return;
565
+ push(state, nodes, {
566
+ ...base,
567
+ kind: 'system',
568
+ turn: state.turn,
569
+ step: state.step,
570
+ label: event.type.split('/')[1] ?? event.type,
571
+ detail: value,
572
+ });
573
+ return;
574
+ }
575
+ case 'command/run': {
576
+ const payload = readCommandRun(event.data);
577
+ if (payload === undefined)
578
+ return;
579
+ push(state, nodes, {
580
+ ...base,
581
+ kind: 'system',
582
+ turn: state.turn,
583
+ step: state.step,
584
+ label: `/${payload.name}`,
585
+ detail: payload.args?.trim() === '' ? undefined : payload.args,
586
+ });
587
+ return;
588
+ }
589
+ case 'todo/write': {
590
+ const payload = readTodos(event.data);
591
+ if (payload === undefined)
592
+ return;
593
+ push(state, nodes, {
594
+ ...base,
595
+ kind: 'todo',
596
+ turn: state.turn,
597
+ step: state.step,
598
+ label: `${payload.done}/${payload.total}`,
599
+ detail: payload.current,
600
+ });
601
+ return;
602
+ }
603
+ default:
604
+ // Unknown or deliberately silent (request/context, session/title,
605
+ // agent/inbox/spliced, command/done, …): no ledger row. Forward
606
+ // compatibility is the default, not an error path.
607
+ return;
608
+ }
609
+ }
610
+ /** An empty build, used as the identity element and for empty sessions. */
611
+ export function emptyTrajectory() {
612
+ const state = newState();
613
+ return { source: [], nodes: [], timing: new Map(), counts: state.counts, state };
614
+ }
615
+ /**
616
+ * Extend a previous projection with the session's current event snapshot.
617
+ *
618
+ * @param previous - The prior build, or `null` to fold from scratch.
619
+ * @param events - The session's current immutable event snapshot.
620
+ * @returns A build over `events`; `previous` itself when nothing was appended.
621
+ */
622
+ export function extendTrajectory(previous, events) {
623
+ const raw = asRawEvents(events);
624
+ if (previous !== null &&
625
+ raw.length >= previous.source.length &&
626
+ (previous.source.length === 0 ||
627
+ raw[previous.source.length - 1] === previous.source[previous.source.length - 1])) {
628
+ if (raw.length === previous.source.length)
629
+ return previous;
630
+ const nodes = previous.nodes;
631
+ const timing = previous.timing;
632
+ const state = cloneState(previous.state);
633
+ for (let index = previous.source.length; index < raw.length; index++) {
634
+ consume(state, nodes, timing, raw[index]);
635
+ }
636
+ syncRowCount(state, nodes);
637
+ return { source: raw, nodes, timing, counts: state.counts, state };
638
+ }
639
+ const nodes = [];
640
+ const timing = new Map();
641
+ const state = newState();
642
+ for (const event of raw)
643
+ consume(state, nodes, timing, event);
644
+ syncRowCount(state, nodes);
645
+ return { source: raw, nodes, timing, counts: state.counts, state };
646
+ }
647
+ /**
648
+ * Fold from scratch — the one-shot form used by tests and by consumers that
649
+ * hold no previous build.
650
+ */
651
+ export function buildTrajectory(events) {
652
+ return extendTrajectory(null, events);
653
+ }