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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/README.md +55 -20
  2. package/assets/whale-girl/whale-girl-dark.png +0 -0
  3. package/assets/whale-girl/whale-girl-happy.png +0 -0
  4. package/assets/whale-girl/whale-girl.png +0 -0
  5. package/bin/dsh-tui.js +63 -3
  6. package/cordis.patch.yml +43 -20
  7. package/cordis.yml +6 -4
  8. package/lib/settings.json +1272 -0
  9. package/lib/types/activityPrefs.d.ts +24 -0
  10. package/lib/types/activityPrefs.d.ts.map +1 -1
  11. package/lib/types/activityPrefs.js +50 -1
  12. package/lib/types/adapter/channel/state.d.ts.map +1 -1
  13. package/lib/types/adapter/channel/state.js +3 -1
  14. package/lib/types/adapter/channel/ui-policy.d.ts +9 -2
  15. package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
  16. package/lib/types/adapter/channel/ui-policy.js +14 -1
  17. package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
  18. package/lib/types/adapter/kernel/replay.js +2 -0
  19. package/lib/types/adapter/ports/channel-display.d.ts +12 -0
  20. package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
  21. package/lib/types/adapter/ports/channel-session.d.ts +38 -0
  22. package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
  23. package/lib/types/adapter/ports/channel-settings.d.ts +12 -0
  24. package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
  25. package/lib/types/adapter/ports/channel-ui.d.ts +53 -7
  26. package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
  27. package/lib/types/adapter/ports/channel-view.d.ts +43 -12
  28. package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
  29. package/lib/types/adapter/ports/channel.d.ts +4 -1
  30. package/lib/types/adapter/ports/channel.d.ts.map +1 -1
  31. package/lib/types/commands.d.ts.map +1 -1
  32. package/lib/types/commands.js +2 -0
  33. package/lib/types/components/ActivityLine.d.ts +7 -2
  34. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  35. package/lib/types/components/ActivityLine.js +0 -8
  36. package/lib/types/components/BalanceReportRow.d.ts +10 -2
  37. package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
  38. package/lib/types/components/BalanceReportRow.js +18 -4
  39. package/lib/types/components/CompactionStatusRow.d.ts +24 -0
  40. package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
  41. package/lib/types/components/CompactionStatusRow.js +72 -0
  42. package/lib/types/components/GoalTodoPanel.js +2 -2
  43. package/lib/types/components/HelpMenu.d.ts +2 -2
  44. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  45. package/lib/types/components/HelpMenu.js +5 -4
  46. package/lib/types/components/InlineMathParagraph.d.ts +22 -0
  47. package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
  48. package/lib/types/components/InlineMathParagraph.js +178 -0
  49. package/lib/types/components/LogoV2.d.ts +41 -3
  50. package/lib/types/components/LogoV2.d.ts.map +1 -1
  51. package/lib/types/components/LogoV2.js +148 -24
  52. package/lib/types/components/Markdown.d.ts +10 -3
  53. package/lib/types/components/Markdown.d.ts.map +1 -1
  54. package/lib/types/components/Markdown.js +47 -14
  55. package/lib/types/components/MathBlock.d.ts +13 -0
  56. package/lib/types/components/MathBlock.d.ts.map +1 -0
  57. package/lib/types/components/MathBlock.js +136 -0
  58. package/lib/types/components/MessageList.d.ts +10 -1
  59. package/lib/types/components/MessageList.d.ts.map +1 -1
  60. package/lib/types/components/MessageList.js +15 -5
  61. package/lib/types/components/MigratePicker.d.ts +30 -0
  62. package/lib/types/components/MigratePicker.d.ts.map +1 -0
  63. package/lib/types/components/MigratePicker.js +38 -0
  64. package/lib/types/components/PromptInput.d.ts +17 -0
  65. package/lib/types/components/PromptInput.d.ts.map +1 -1
  66. package/lib/types/components/PromptInput.js +96 -9
  67. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  68. package/lib/types/components/SplitDiffView.js +3 -1
  69. package/lib/types/components/StarPrompt.d.ts +53 -0
  70. package/lib/types/components/StarPrompt.d.ts.map +1 -0
  71. package/lib/types/components/StarPrompt.js +281 -0
  72. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  73. package/lib/types/components/StreamingMarkdown.js +20 -3
  74. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  75. package/lib/types/components/SubagentCard.js +12 -6
  76. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
  77. package/lib/types/components/SubagentDetailScene.js +8 -3
  78. package/lib/types/components/TimelineRail.d.ts.map +1 -1
  79. package/lib/types/components/TimelineRail.js +9 -1
  80. package/lib/types/components/Whale.d.ts +17 -8
  81. package/lib/types/components/Whale.d.ts.map +1 -1
  82. package/lib/types/components/Whale.js +25 -15
  83. package/lib/types/components/WhaleGirl.d.ts +29 -0
  84. package/lib/types/components/WhaleGirl.d.ts.map +1 -0
  85. package/lib/types/components/WhaleGirl.js +32 -0
  86. package/lib/types/components/WorkingSpinner.d.ts +4 -1
  87. package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
  88. package/lib/types/components/WorkingSpinner.js +2 -2
  89. package/lib/types/components/bigfont.d.ts +47 -18
  90. package/lib/types/components/bigfont.d.ts.map +1 -1
  91. package/lib/types/components/bigfont.js +55 -40
  92. package/lib/types/components/design-system/HintLine.d.ts +1 -2
  93. package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
  94. package/lib/types/components/design-system/HintLine.js +1 -2
  95. package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
  96. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  97. package/lib/types/components/design-system/ThemeProvider.js +40 -1
  98. package/lib/types/components/maidPortrait.d.ts +44 -0
  99. package/lib/types/components/maidPortrait.d.ts.map +1 -0
  100. package/lib/types/components/maidPortrait.js +178 -0
  101. package/lib/types/components/mathPreview.d.ts +25 -0
  102. package/lib/types/components/mathPreview.d.ts.map +1 -0
  103. package/lib/types/components/mathPreview.js +48 -0
  104. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
  105. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  106. package/lib/types/components/messages/AssistantThinkingMessage.js +4 -2
  107. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
  108. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  109. package/lib/types/components/messages/AssistantToolUseMessage.js +31 -26
  110. package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
  111. package/lib/types/components/messages/TranscriptImages.js +11 -1
  112. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
  113. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  114. package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
  115. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  116. package/lib/types/components/questions/PlanReviewPanel.js +3 -3
  117. package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
  118. package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
  119. package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
  120. package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
  121. package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
  122. package/lib/types/components/sessions/SourceTabs.js +70 -0
  123. package/lib/types/components/splashEggs.d.ts +56 -0
  124. package/lib/types/components/splashEggs.d.ts.map +1 -0
  125. package/lib/types/components/splashEggs.js +67 -0
  126. package/lib/types/components/splashFonts.d.ts +119 -0
  127. package/lib/types/components/splashFonts.d.ts.map +1 -0
  128. package/lib/types/components/splashFonts.js +267 -0
  129. package/lib/types/components/splashLayout.d.ts +41 -0
  130. package/lib/types/components/splashLayout.d.ts.map +1 -0
  131. package/lib/types/components/splashLayout.js +40 -0
  132. package/lib/types/components/whaleGirlSprite.d.ts +17 -0
  133. package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
  134. package/lib/types/components/whaleGirlSprite.js +47 -0
  135. package/lib/types/deepseekPricing.d.ts +74 -0
  136. package/lib/types/deepseekPricing.d.ts.map +1 -1
  137. package/lib/types/deepseekPricing.js +110 -11
  138. package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
  139. package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
  140. package/lib/types/dsh-adapter/activity-store.js +359 -0
  141. package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
  142. package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
  143. package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
  144. package/lib/types/dsh-adapter/channel/background-action.d.ts +2 -1
  145. package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
  146. package/lib/types/dsh-adapter/channel/background-action.js +2 -0
  147. package/lib/types/dsh-adapter/channel/binding-events.d.ts +15 -14
  148. package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
  149. package/lib/types/dsh-adapter/channel/binding-events.js +70 -21
  150. package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -2
  151. package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
  152. package/lib/types/dsh-adapter/channel/compaction.js +35 -4
  153. package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
  154. package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
  155. package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
  156. package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
  157. package/lib/types/dsh-adapter/channel/model-switch.js +6 -2
  158. package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
  159. package/lib/types/dsh-adapter/channel/paths.js +7 -1
  160. package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
  161. package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
  162. package/lib/types/dsh-adapter/channel/preferences.js +16 -0
  163. package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
  164. package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
  165. package/lib/types/dsh-adapter/channel/projection.js +127 -17
  166. package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
  167. package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
  168. package/lib/types/dsh-adapter/channel/question-record.js +107 -0
  169. package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
  170. package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
  171. package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
  172. package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
  173. package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
  174. package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
  175. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +3 -1
  176. package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
  177. package/lib/types/dsh-adapter/channel/session-live-adoption.js +10 -3
  178. package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
  179. package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
  180. package/lib/types/dsh-adapter/channel/session-metadata.js +43 -9
  181. package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
  182. package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
  183. package/lib/types/dsh-adapter/channel/session-reset.js +7 -1
  184. package/lib/types/dsh-adapter/channel/session-resume.d.ts +2 -1
  185. package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
  186. package/lib/types/dsh-adapter/channel/session-resume.js +5 -2
  187. package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
  188. package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
  189. package/lib/types/dsh-adapter/channel/state.d.ts +19 -1
  190. package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
  191. package/lib/types/dsh-adapter/channel/state.js +8 -3
  192. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +32 -17
  193. package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
  194. package/lib/types/dsh-adapter/channel/subagent-projection.js +309 -8
  195. package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
  196. package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
  197. package/lib/types/dsh-adapter/channel.d.ts +1 -1
  198. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  199. package/lib/types/dsh-adapter/channel.js +34 -18
  200. package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
  201. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
  202. package/lib/types/dsh-adapter/compat/index.js +1 -1
  203. package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
  204. package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
  205. package/lib/types/dsh-adapter/compat/messages.js +9 -0
  206. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
  207. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
  208. package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
  209. package/lib/types/dsh-adapter/compat/settings.d.ts +2 -0
  210. package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -1
  211. package/lib/types/dsh-adapter/compat/settings.js +14 -0
  212. package/lib/types/dsh-adapter/contract.d.ts +5 -4
  213. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  214. package/lib/types/dsh-adapter/contract.js +9 -5
  215. package/lib/types/dsh-adapter/index.d.ts +36 -1
  216. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  217. package/lib/types/dsh-adapter/index.js +22 -6
  218. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
  219. package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
  220. package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
  221. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
  222. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
  223. package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
  224. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
  225. package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
  226. package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
  227. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
  228. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
  229. package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
  230. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
  231. package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
  232. package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
  233. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
  234. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
  235. package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
  236. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
  237. package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
  238. package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
  239. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
  240. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
  241. package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
  242. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
  243. package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
  244. package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
  245. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
  246. package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
  247. package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
  248. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
  249. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
  250. package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
  251. package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
  252. package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
  253. package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
  254. package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
  255. package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
  256. package/lib/types/dsh-adapter/migrate/browse.js +90 -0
  257. package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
  258. package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
  259. package/lib/types/dsh-adapter/migrate/cli.js +106 -0
  260. package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
  261. package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
  262. package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
  263. package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
  264. package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
  265. package/lib/types/dsh-adapter/migrate/index.js +107 -0
  266. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
  267. package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
  268. package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
  269. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
  270. package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
  271. package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
  272. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
  273. package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
  274. package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
  275. package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
  276. package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
  277. package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
  278. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
  279. package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
  280. package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
  281. package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
  282. package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
  283. package/lib/types/dsh-adapter/migrate/picker.js +86 -0
  284. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
  285. package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
  286. package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
  287. package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
  288. package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
  289. package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
  290. package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
  291. package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
  292. package/lib/types/dsh-adapter/migrate/types.js +11 -0
  293. package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
  294. package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
  295. package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
  296. package/lib/types/dsh-adapter/plugin.d.ts +5 -3
  297. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  298. package/lib/types/dsh-adapter/plugin.js +168 -372
  299. package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
  300. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  301. package/lib/types/dsh-adapter/providerWizard.js +254 -66
  302. package/lib/types/dsh-adapter/questions.d.ts +22 -15
  303. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  304. package/lib/types/dsh-adapter/questions.js +47 -45
  305. package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
  306. package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
  307. package/lib/types/dsh-adapter/sessions/digest.js +20 -13
  308. package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
  309. package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
  310. package/lib/types/dsh-adapter/sessions/frames.js +5 -4
  311. package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
  312. package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
  313. package/lib/types/dsh-adapter/sessions/list.js +188 -164
  314. package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
  315. package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
  316. package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
  317. package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
  318. package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
  319. package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
  320. package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
  321. package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
  322. package/lib/types/dsh-adapter/sessions/store.js +62 -25
  323. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  324. package/lib/types/dsh-adapter/settings-sections.js +7 -4
  325. package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
  326. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
  327. package/lib/types/dsh-adapter/sideQuestion.js +98 -2
  328. package/lib/types/dsh-adapter/subagents.d.ts +44 -6
  329. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
  330. package/lib/types/dsh-adapter/subagents.js +163 -26
  331. package/lib/types/herdr.d.ts +2 -0
  332. package/lib/types/herdr.d.ts.map +1 -1
  333. package/lib/types/herdr.js +9 -3
  334. package/lib/types/history.d.ts +13 -1
  335. package/lib/types/history.d.ts.map +1 -1
  336. package/lib/types/history.js +15 -2
  337. package/lib/types/i18n.d.ts +512 -41
  338. package/lib/types/i18n.d.ts.map +1 -1
  339. package/lib/types/i18n.js +199 -20
  340. package/lib/types/ink/components/App.d.ts +2 -2
  341. package/lib/types/ink/components/App.d.ts.map +1 -1
  342. package/lib/types/ink/components/App.js +5 -1
  343. package/lib/types/ink/components/Image.d.ts +14 -1
  344. package/lib/types/ink/components/Image.d.ts.map +1 -1
  345. package/lib/types/ink/components/Image.js +2 -2
  346. package/lib/types/ink/events/input-event.js +3 -3
  347. package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
  348. package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
  349. package/lib/types/ink/hooks/use-terminal-images.js +13 -0
  350. package/lib/types/ink/ink.d.ts +6 -0
  351. package/lib/types/ink/ink.d.ts.map +1 -1
  352. package/lib/types/ink/ink.js +16 -1
  353. package/lib/types/ink/kitty-graphics.d.ts +44 -3
  354. package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
  355. package/lib/types/ink/kitty-graphics.js +184 -23
  356. package/lib/types/ink/log-update.d.ts.map +1 -1
  357. package/lib/types/ink/log-update.js +19 -1
  358. package/lib/types/ink/output.d.ts +24 -2
  359. package/lib/types/ink/output.d.ts.map +1 -1
  360. package/lib/types/ink/output.js +83 -5
  361. package/lib/types/ink/parse-keypress.d.ts +26 -1
  362. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  363. package/lib/types/ink/parse-keypress.js +156 -13
  364. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  365. package/lib/types/ink/render-node-to-output.js +8 -1
  366. package/lib/types/ink/screen.d.ts +24 -0
  367. package/lib/types/ink/screen.d.ts.map +1 -1
  368. package/lib/types/ink/screen.js +89 -0
  369. package/lib/types/ink/selection.d.ts +68 -18
  370. package/lib/types/ink/selection.d.ts.map +1 -1
  371. package/lib/types/ink/selection.js +178 -31
  372. package/lib/types/ink/sixel-codec.d.ts +12 -1
  373. package/lib/types/ink/sixel-codec.d.ts.map +1 -1
  374. package/lib/types/ink/sixel-codec.js +29 -5
  375. package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
  376. package/lib/types/ink/sixel-graphics.js +5 -3
  377. package/lib/types/ink/styles.d.ts +9 -0
  378. package/lib/types/ink/styles.d.ts.map +1 -1
  379. package/lib/types/ink/terminal-image.d.ts +8 -0
  380. package/lib/types/ink/terminal-image.d.ts.map +1 -1
  381. package/lib/types/ink/terminal-querier.d.ts +7 -1
  382. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  383. package/lib/types/ink/terminal-querier.js +12 -2
  384. package/lib/types/ink/timeline-rail.d.ts +5 -0
  385. package/lib/types/ink/timeline-rail.d.ts.map +1 -1
  386. package/lib/types/math/inline-layout.d.ts +29 -0
  387. package/lib/types/math/inline-layout.d.ts.map +1 -0
  388. package/lib/types/math/inline-layout.js +106 -0
  389. package/lib/types/math/layout.d.ts +58 -0
  390. package/lib/types/math/layout.d.ts.map +1 -0
  391. package/lib/types/math/layout.js +59 -0
  392. package/lib/types/math/renderer.d.ts +64 -0
  393. package/lib/types/math/renderer.d.ts.map +1 -0
  394. package/lib/types/math/renderer.js +256 -0
  395. package/lib/types/screens/Chat.d.ts +17 -1
  396. package/lib/types/screens/Chat.d.ts.map +1 -1
  397. package/lib/types/screens/Chat.js +618 -57
  398. package/lib/types/screens/SessionSupervisor.d.ts +2 -1
  399. package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
  400. package/lib/types/screens/SessionSupervisor.js +156 -19
  401. package/lib/types/screens/Settings.d.ts.map +1 -1
  402. package/lib/types/screens/Settings.js +49 -11
  403. package/lib/types/screens/StatusLine.d.ts +5 -1
  404. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  405. package/lib/types/screens/StatusLine.js +47 -17
  406. package/lib/types/screens/chatOverlay.d.ts +5 -0
  407. package/lib/types/screens/chatOverlay.d.ts.map +1 -1
  408. package/lib/types/screens/chatOverlay.js +1 -0
  409. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
  410. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
  411. package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
  412. package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
  413. package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
  414. package/lib/types/screens/sessionSupervisor/model.js +26 -0
  415. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
  416. package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
  417. package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
  418. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
  419. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
  420. package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
  421. package/lib/types/sessionHistory.d.ts +2 -2
  422. package/lib/types/sessionHistory.d.ts.map +1 -1
  423. package/lib/types/sessionHistory.js +31 -5
  424. package/lib/types/settings/definitions.d.ts +681 -0
  425. package/lib/types/settings/definitions.d.ts.map +1 -0
  426. package/lib/types/settings/definitions.js +511 -0
  427. package/lib/types/starAction.d.ts +44 -0
  428. package/lib/types/starAction.d.ts.map +1 -0
  429. package/lib/types/starAction.js +52 -0
  430. package/lib/types/terminal-utils/latex.d.ts +10 -0
  431. package/lib/types/terminal-utils/latex.d.ts.map +1 -0
  432. package/lib/types/terminal-utils/latex.js +1417 -0
  433. package/lib/types/terminal-utils/markdown.d.ts +3 -1
  434. package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
  435. package/lib/types/terminal-utils/markdown.js +26 -1
  436. package/lib/types/terminal-utils/math.d.ts +66 -0
  437. package/lib/types/terminal-utils/math.d.ts.map +1 -0
  438. package/lib/types/terminal-utils/math.js +337 -0
  439. package/lib/types/tips.d.ts.map +1 -1
  440. package/lib/types/tips.js +6 -0
  441. package/lib/types/tuiDisplayPrefs.d.ts +67 -0
  442. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  443. package/lib/types/tuiDisplayPrefs.js +59 -0
  444. package/lib/types/ui.d.ts +1 -1
  445. package/lib/types/ui.d.ts.map +1 -1
  446. package/lib/types/ui.js +1 -1
  447. package/lib/types/usageStats.d.ts +98 -0
  448. package/lib/types/usageStats.d.ts.map +1 -0
  449. package/lib/types/usageStats.js +169 -0
  450. package/lib/types/utils/bmp.d.ts +17 -0
  451. package/lib/types/utils/bmp.d.ts.map +1 -0
  452. package/lib/types/utils/bmp.js +154 -0
  453. package/lib/types/utils/clipboard.d.ts +14 -2
  454. package/lib/types/utils/clipboard.d.ts.map +1 -1
  455. package/lib/types/utils/clipboard.js +143 -8
  456. package/lib/types/utils/fold-long-lines.d.ts +1 -1
  457. package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
  458. package/lib/types/utils/fold-long-lines.js +3 -2
  459. package/lib/types/utils/keymap.d.ts +4 -1
  460. package/lib/types/utils/keymap.d.ts.map +1 -1
  461. package/lib/types/utils/keymap.js +8 -0
  462. package/lib/types/utils/modifiers.d.ts +4 -3
  463. package/lib/types/utils/modifiers.d.ts.map +1 -1
  464. package/lib/types/utils/modifiers.js +4 -3
  465. package/lib/types/working-activity.d.ts +10 -9
  466. package/lib/types/working-activity.d.ts.map +1 -1
  467. package/lib/types/working-activity.js +17 -10
  468. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
  469. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
  470. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
  471. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
  472. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
  473. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
  474. package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
  475. package/package.json +117 -99
  476. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
  477. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
  478. package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
  479. package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
  480. package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
  481. package/lib/types/dsh-adapter/channel/activity.js +0 -113
  482. package/lib/types/terminal-utils/terminal.d.ts +0 -18
  483. package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
  484. package/lib/types/terminal-utils/terminal.js +0 -96
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Building the session list.
3
3
  *
4
- * One resolution path produces one complete, honestly-classified record per
4
+ * One resolution path produces one usable, honestly-classified record per
5
5
  * stored session — every kind, empties included — and callers decide what to
6
6
  * show. That split is deliberate: the old picker filtered while it resolved,
7
7
  * so "hide sub-agent runs" and "resolve a title" were the same pass and
@@ -9,24 +9,27 @@
9
9
  * toggle sub-agent runs into view, or offer to clean up boot artifacts,
10
10
  * without re-deriving anything.
11
11
  *
12
- * Cost: one `stat` per session always, plus one bounded log read per session
13
- * whose revision moved since the last listing. On a warm index that is zero
14
- * log reads. A log whose opening prompt exceeds the cheap window takes one
15
- * progressive, memory-bounded recovery scan and caches the result. The path
12
+ * Cost: backend enumeration plus a revision comparison per session. Only a
13
+ * changed revision needs artifact I/O, and append-only changes read the new
14
+ * suffix. Incomplete titles are recovered after the list is returned. The path
16
15
  * this replaces decompressed every frame of the twenty most recent logs on
17
16
  * every open — 3.9 s over a 31 MB history.
18
17
  *
19
18
  * @module @deepseek-harness-tui/dsh-tui/sessions/list
20
19
  */
21
20
  import { basename } from 'node:path';
22
- import { digestSession, recoverAppendedTitle, recoverSessionTitle, sessionTitleAnchor, } from './digest.js';
21
+ import { beginListingSnapshot } from './snapshot.js';
22
+ import { digestAppendedSuffix, digestSession, sessionTitleAnchor, } from './digest.js';
23
23
  import { fileFacts } from './frames.js';
24
+ import { scheduleTitleRecovery, titleRecoveryNeedsWork } from './recovery.js';
24
25
  import { classify, readHeader } from './header.js';
25
26
  import { findSessionLogFile, resolveLocatedPath } from '../compat/sessionLog.js';
26
- import { readIndex, writeIndex } from './store.js';
27
+ import { indexFileStamp, readIndex, writeIndex } from './store.js';
27
28
  import { readLastUsed } from '../../sessionHistory.js';
28
- /** Compressed bytes one listing may spend on full-log title recovery scans. */
29
- const TITLE_SCAN_BUDGET_BYTES = 16 * 1024 * 1024;
29
+ /** A late overlapping listing must not write an older index over a newer one. */
30
+ const listingVersions = new WeakMap();
31
+ /** Large append batches use bounded windows, then background title recovery. */
32
+ const FOREGROUND_SUFFIX_BYTES = 2 * 1024 * 1024;
30
33
  /** Pull `{ header, revision }` out of one `listSnapshots()` element. */
31
34
  function readSnapshot(value) {
32
35
  if (value === null || typeof value !== 'object')
@@ -59,7 +62,11 @@ export async function enumerateSessions(source, signal) {
59
62
  return snapshots.map(readSnapshot).filter((entry) => entry !== undefined);
60
63
  }
61
64
  if (typeof source.list === 'function') {
62
- const headers = await source.list(signal);
65
+ // Handle-based providers take an options object; legacy providers took a
66
+ // bare signal. identity is part of the handle-based service contract.
67
+ const headers = typeof source.identity === 'symbol'
68
+ ? await source.list.call(source, { signal })
69
+ : await source.list(signal);
63
70
  return headers
64
71
  .map((raw) => readSnapshot(raw) ?? bareListed(raw))
65
72
  .filter((entry) => entry !== undefined);
@@ -113,14 +120,15 @@ function locate(source, raw, sessionId) {
113
120
  * filtering of any kind is applied — sub-agent runs and sessions with no
114
121
  * conversation are present and labelled as such.
115
122
  */
116
- export async function listSummaries(source, signal) {
117
- let listed;
118
- try {
119
- listed = await enumerateSessions(source, signal);
120
- }
121
- catch {
122
- return [];
123
- }
123
+ export async function listSummaries(source, signal, onEnriched, onPartial) {
124
+ const identity = source.identity ?? source;
125
+ const version = (listingVersions.get(identity) ?? 0) + 1;
126
+ listingVersions.set(identity, version);
127
+ const saveSnapshot = beginListingSnapshot(source);
128
+ // A failed enumeration is not a successful empty store. Let the screen keep
129
+ // its snapshot beside an error instead of erasing it (including on disk).
130
+ const listed = await enumerateSessions(source, signal);
131
+ signal?.throwIfAborted();
124
132
  // Children are counted from the same listing rather than by walking logs:
125
133
  // lineage lives in the header, so a parent's sub-agent count is free.
126
134
  const children = new Map();
@@ -132,92 +140,152 @@ export async function listSummaries(source, signal) {
132
140
  continue;
133
141
  children.set(parent, (children.get(parent) ?? 0) + 1);
134
142
  }
143
+ const indexStamp = indexFileStamp();
135
144
  const index = readIndex();
136
145
  const next = new Map();
137
146
  const lastUsed = readLastUsed();
147
+ // Recent conversations lead cold partial batches; backend directory order
148
+ // must not keep the useful rows behind thousands of old delegated runs.
149
+ const activity = (entry) => Math.max(index.get(entry.header.id)?.derived?.modifiedAt ?? 0, lastUsed[entry.header.id] ?? 0, entry.header.createdAt ?? 0);
150
+ listed.sort((a, b) => activity(b) - activity(a));
138
151
  let changed = false;
139
152
  const records = [];
140
- // Full-log recovery scans are charged against one budget per listing and run
141
- // most-recent-first, so a cold cache after an upgrade improves incrementally
142
- // instead of decompressing the whole history in one open.
153
+ const summaryOf = ({ header, facts, cached, derived }) => ({
154
+ id: header.id,
155
+ kind: classify(header),
156
+ title: {
157
+ text: derived?.title !== undefined && derived.title.length > 0
158
+ ? derived.title
159
+ : basename(header.cwd ?? '') || header.id.slice(0, 8),
160
+ source: derived?.titleSource ?? 'fallback',
161
+ },
162
+ cwd: header.cwd ?? '',
163
+ createdAt: header.createdAt ?? derived?.modifiedAt ?? facts?.modifiedAt ?? 0,
164
+ updatedAt: Math.max(derived?.modifiedAt ?? facts?.modifiedAt ?? 0, lastUsed[header.id] ?? 0, header.createdAt ?? 0),
165
+ bytes: derived?.bytes ?? facts?.bytes,
166
+ // Without a readable artifact nothing can be proven empty, and hiding a
167
+ // real session is the worse error — so an unreadable log is listed.
168
+ hasPrompt: derived?.hasPrompt ?? true,
169
+ agentPreset: header.agentPreset,
170
+ model: derived?.model,
171
+ label: derived?.label,
172
+ branch: cached?.branch,
173
+ childCount: children.get(header.id) ?? 0,
174
+ });
175
+ const recordsById = new Map();
176
+ const earlyEnrichments = new Map();
177
+ let summariesReady = false;
178
+ const notifyEnriched = (id, enriched) => {
179
+ if (!summariesReady) {
180
+ earlyEnrichments.set(id, enriched);
181
+ return;
182
+ }
183
+ const record = recordsById.get(id);
184
+ if (record === undefined || record.derived?.revision !== enriched.revision)
185
+ return;
186
+ record.derived = enriched;
187
+ onEnriched?.(summaryOf(record));
188
+ };
143
189
  const scanWork = [];
144
190
  for (const { header, raw, revision } of listed) {
145
191
  const cached = index.get(header.id);
146
- const path = locate(source, raw, header.id);
147
- const facts = path === undefined ? undefined : fileFacts(path);
148
- // Falls back to the file's own identity when the backend offered no token.
149
- const token = revision ?? (facts === undefined ? undefined : `${facts.bytes}:${facts.modifiedAt}`);
150
- let derived;
151
- if (cached?.derived !== undefined &&
152
- token !== undefined &&
153
- cached.derived.revision === token &&
154
- cached.derived.titleComplete) {
155
- derived = cached.derived;
192
+ let facts;
193
+ let derived = cached?.derived;
194
+ let path;
195
+ if (revision !== undefined && derived?.revision === revision && derived.modifiedAt === undefined) {
196
+ // Schema v3 held the same derived facts but not mtime. Upgrade that
197
+ // record with one metadata read rather than re-decoding its log.
198
+ path = locate(source, raw, header.id);
199
+ facts = path === undefined ? undefined : fileFacts(path);
200
+ derived = { ...derived, modifiedAt: facts?.modifiedAt ?? 0 };
201
+ changed = true;
156
202
  }
157
- else if (path !== undefined && token !== undefined) {
158
- const digest = digestSession(path, header.cwd ?? '');
159
- let title = digest.title;
160
- const hasPrompt = digest.hasPrompt;
161
- let titleComplete = digest.titleComplete === true;
162
- const previous = cached?.derived;
163
- // Across an append-only revision, validate the old EOF neighborhood then
164
- // scan only the new frames. This preserves an older authoritative title
165
- // without trusting file size alone, and still observes a newly appended
166
- // rename even when later output pushed it outside the cheap tail window.
167
- // Only title evidence carries forward: a formerly empty session can
168
- // have acquired its first human message in the appended suffix.
169
- if (!titleComplete &&
170
- previous !== undefined &&
171
- facts !== undefined &&
172
- previous.identity !== undefined &&
173
- previous.identity === facts.identity &&
174
- previous.anchor !== undefined &&
175
- facts.bytes >= previous.bytes) {
176
- const oldAnchor = await sessionTitleAnchor(path, previous.bytes, signal);
177
- if (oldAnchor === previous.anchor) {
178
- if (facts.bytes === previous.bytes && previous.titleComplete) {
179
- title = previous.title.length === 0
180
- ? undefined
181
- : { text: previous.title, source: previous.titleSource };
182
- titleComplete = true;
183
- }
184
- else if (facts.bytes > previous.bytes) {
185
- const appended = await recoverAppendedTitle(path, previous.bytes, facts.bytes, signal);
186
- if (appended.title !== undefined)
187
- title = appended.title;
188
- if (appended.complete && (appended.title !== undefined || previous.titleComplete)) {
189
- if (appended.title === undefined) {
190
- title = previous.title.length === 0
191
- ? undefined
192
- : { text: previous.title, source: previous.titleSource };
193
- }
194
- titleComplete = true;
203
+ // The backend's opaque revision is authoritative. A hit does not even
204
+ // resolve a path; incomplete titles are handled by the recovery queue.
205
+ if (revision === undefined || derived === undefined || derived.revision !== revision) {
206
+ path = locate(source, raw, header.id);
207
+ facts = path === undefined ? undefined : fileFacts(path);
208
+ // Older persistence implementations provide no revision. Their one
209
+ // metadata read per entry remains necessary to detect changes.
210
+ const token = revision ?? facts?.stamp;
211
+ if (facts !== undefined && derived?.artifactStamp === facts.stamp) {
212
+ // Historical logical revisions include the whole corpus. Our digest
213
+ // reads only this artifact. Retain the original revision as well so
214
+ // unrelated appends cannot restart title recovery or reset its backoff.
215
+ // Only fallback text depends on the freshly enumerated header.
216
+ const fallback = basename(header.cwd ?? '');
217
+ if (derived.titleSource === 'fallback' && derived.title !== fallback) {
218
+ derived = { ...derived, title: fallback };
219
+ changed = true;
220
+ }
221
+ }
222
+ else if (token === undefined || derived?.revision !== token) {
223
+ derived = undefined;
224
+ if (cached?.derived !== undefined)
225
+ changed = true;
226
+ if (path !== undefined && token !== undefined) {
227
+ const previous = cached?.derived;
228
+ const appendGrowth = (facts !== undefined && previous?.identity !== undefined &&
229
+ previous.identity === facts.identity && previous.anchor !== undefined &&
230
+ facts.bytes > previous.bytes &&
231
+ await sessionTitleAnchor(path, previous.bytes, signal) === previous.anchor);
232
+ if (appendGrowth && facts !== undefined && previous !== undefined && facts.bytes - previous.bytes <= FOREGROUND_SUFFIX_BYTES) {
233
+ const suffix = await digestAppendedSuffix(path, previous.bytes, facts.bytes, signal);
234
+ if (suffix.complete) {
235
+ derived = {
236
+ revision: token,
237
+ bytes: facts.bytes,
238
+ modifiedAt: facts.modifiedAt,
239
+ identity: facts.identity,
240
+ artifactStamp: facts.stamp,
241
+ anchor: await sessionTitleAnchor(path, facts.bytes, signal),
242
+ title: suffix.title?.text ?? previous.title,
243
+ titleSource: suffix.title?.source ?? previous.titleSource,
244
+ titleComplete: suffix.title !== undefined || previous.titleComplete,
245
+ hasPrompt: previous.hasPrompt || suffix.hasHumanPrompt,
246
+ model: suffix.model ?? previous.model,
247
+ label: suffix.label ?? previous.label,
248
+ };
195
249
  }
196
250
  }
251
+ if (derived === undefined) {
252
+ const digest = digestSession(path, header.cwd ?? '');
253
+ const carried = appendGrowth && digest.titleComplete !== true ? previous : undefined;
254
+ derived = {
255
+ revision: token,
256
+ bytes: facts?.bytes ?? 0,
257
+ modifiedAt: facts?.modifiedAt,
258
+ identity: facts?.identity,
259
+ artifactStamp: facts?.stamp,
260
+ anchor: facts === undefined ? undefined : await sessionTitleAnchor(path, facts.bytes, signal),
261
+ title: carried?.title ?? digest.title?.text ?? '',
262
+ titleSource: carried?.titleSource ?? digest.title?.source ?? 'fallback',
263
+ titleComplete: digest.titleComplete === true,
264
+ hasPrompt: digest.hasPrompt,
265
+ model: digest.model ?? carried?.model,
266
+ label: digest.label ?? carried?.label,
267
+ };
268
+ }
269
+ changed = true;
197
270
  }
198
271
  }
199
- derived = {
200
- revision: token,
201
- bytes: facts?.bytes ?? 0,
202
- identity: facts?.identity,
203
- anchor: facts === undefined ? undefined : await sessionTitleAnchor(path, facts.bytes, signal),
204
- title: title?.text ?? '',
205
- titleSource: title?.source ?? 'fallback',
206
- titleComplete,
207
- hasPrompt,
208
- model: digest.model,
209
- label: digest.label,
210
- };
211
- changed = true;
212
- if (!titleComplete &&
213
- facts !== undefined &&
214
- signal?.aborted !== true) {
215
- const createdAt = header.createdAt ?? facts.modifiedAt;
272
+ }
273
+ if (derived !== undefined && !derived.titleComplete && signal?.aborted !== true &&
274
+ titleRecoveryNeedsWork(header.id, derived.revision, enriched => notifyEnriched(header.id, enriched))) {
275
+ // A revision hit still may need enrichment, but locating that rare log
276
+ // stays off the ordinary warm path once recovery has been scheduled.
277
+ if (path === undefined)
278
+ path = locate(source, raw, header.id);
279
+ if (facts === undefined && path !== undefined)
280
+ facts = fileFacts(path);
281
+ if (path !== undefined && facts !== undefined && derived.bytes === facts.bytes) {
216
282
  scanWork.push({
217
283
  id: header.id,
284
+ revision: derived.revision,
218
285
  path,
219
286
  bytes: facts.bytes,
220
- updatedAt: Math.max(facts.modifiedAt, lastUsed[header.id] ?? 0, createdAt),
287
+ stamp: facts.stamp,
288
+ priority: Math.max(facts.modifiedAt, lastUsed[header.id] ?? 0, header.createdAt ?? 0),
221
289
  });
222
290
  }
223
291
  }
@@ -227,93 +295,49 @@ export async function listSummaries(source, signal) {
227
295
  if (derived !== undefined || cached?.branch !== undefined) {
228
296
  next.set(header.id, { derived, branch: cached?.branch });
229
297
  }
230
- records.push({ header, facts, cached, derived });
231
- }
232
- const recordsById = new Map(records.map(record => [record.header.id, record]));
233
- // Phase 2: full-log title recovery, most-recent-first, under one byte budget.
234
- scanWork.sort((left, right) => right.updatedAt - left.updatedAt);
235
- let scanBudget = TITLE_SCAN_BUDGET_BYTES;
236
- for (const work of scanWork) {
237
- if (scanBudget <= 0)
238
- break;
239
- let recovered;
240
- try {
241
- recovered = await recoverSessionTitle(work.path, work.bytes, signal);
242
- }
243
- catch {
244
- continue;
245
- }
246
- if (recovered === undefined)
247
- continue;
248
- scanBudget -= work.bytes;
249
- const entry = next.get(work.id);
250
- if (entry?.derived === undefined)
251
- continue;
252
- const base = entry.derived;
253
- if (recovered.title === undefined && recovered.complete) {
254
- // A conclusive no-title scan with no prompt anywhere is a boot artifact;
255
- // otherwise the opening prompt stands in as the title.
256
- next.set(work.id, {
257
- ...entry,
258
- derived: {
259
- ...base,
260
- title: '',
261
- titleSource: 'fallback',
262
- titleComplete: recovered.complete,
263
- hasPrompt: recovered.hasPrompt ?? base.hasPrompt,
264
- },
265
- });
298
+ const record = { header, facts, cached, derived };
299
+ records.push(record);
300
+ recordsById.set(header.id, record);
301
+ // Yield even for a cold index: scanning many individually bounded logs
302
+ // must not freeze the renderer. Partial rows are never saved as a snapshot.
303
+ if (records.length % 32 === 0) {
304
+ if (listingVersions.get(identity) === version)
305
+ onPartial?.(records.map(summaryOf).sort(compareSummaries));
306
+ await new Promise(resolve => setImmediate(resolve));
307
+ signal?.throwIfAborted();
266
308
  }
267
- else {
268
- next.set(work.id, {
269
- ...entry,
270
- derived: {
271
- ...base,
272
- title: recovered.title?.text ?? base.title,
273
- titleSource: recovered.title?.source ?? base.titleSource,
274
- titleComplete: recovered.complete,
275
- hasPrompt: recovered.hasPrompt ?? base.hasPrompt,
276
- },
277
- });
278
- }
279
- const record = recordsById.get(work.id);
280
- if (record !== undefined)
281
- record.derived = next.get(work.id).derived;
282
309
  }
283
310
  // Entries for sessions the backend no longer lists are dropped here; that is
284
311
  // the whole of the cache's garbage collection, and it runs on every listing.
285
- if (changed || next.size !== index.size)
312
+ signal?.throwIfAborted();
313
+ const newest = listingVersions.get(identity) === version;
314
+ if (newest && (changed || next.size !== index.size) && indexFileStamp() === indexStamp)
286
315
  writeIndex(next);
287
- const summaries = records.map(({ header, facts, cached, derived }) => ({
288
- id: header.id,
289
- kind: classify(header),
290
- title: {
291
- text: derived?.title !== undefined && derived.title.length > 0
292
- ? derived.title
293
- : basename(header.cwd ?? '') || header.id.slice(0, 8),
294
- source: derived?.titleSource ?? 'fallback',
295
- },
296
- cwd: header.cwd ?? '',
297
- createdAt: header.createdAt ?? facts?.modifiedAt ?? 0,
298
- updatedAt: Math.max(facts?.modifiedAt ?? 0, lastUsed[header.id] ?? 0, header.createdAt ?? 0),
299
- bytes: facts?.bytes,
300
- // Without a readable artifact nothing can be proven empty, and hiding a
301
- // real session is the worse error — so an unreadable log is listed.
302
- hasPrompt: derived?.hasPrompt ?? true,
303
- agentPreset: header.agentPreset,
304
- model: derived?.model,
305
- label: derived?.label,
306
- branch: cached?.branch,
307
- childCount: children.get(header.id) ?? 0,
308
- }));
316
+ for (const [id, enriched] of earlyEnrichments) {
317
+ const record = recordsById.get(id);
318
+ if (record?.derived?.revision === enriched.revision)
319
+ record.derived = enriched;
320
+ }
321
+ const summaries = records.map(summaryOf);
322
+ summariesReady = true;
323
+ if (newest) {
324
+ for (const work of scanWork) {
325
+ scheduleTitleRecovery(work, derived => notifyEnriched(work.id, derived));
326
+ }
327
+ }
309
328
  // A total order, not just a sort key. `updatedAt` is dominated by the log's
310
329
  // mtime, and sessions written inside the same millisecond tie on it — which
311
330
  // would leave their relative order down to whatever the backend happened to
312
331
  // enumerate first, so the same history could list differently twice in a
313
332
  // row. Creation time breaks the tie, and the id breaks that.
314
- return summaries.sort((left, right) => right.updatedAt - left.updatedAt ||
315
- right.createdAt - left.createdAt ||
316
- (left.id < right.id ? -1 : left.id > right.id ? 1 : 0));
333
+ summaries.sort(compareSummaries);
334
+ if (newest)
335
+ saveSnapshot(summaries);
336
+ return summaries;
337
+ }
338
+ function compareSummaries(left, right) {
339
+ return right.updatedAt - left.updatedAt || right.createdAt - left.createdAt ||
340
+ (left.id < right.id ? -1 : left.id > right.id ? 1 : 0);
317
341
  }
318
342
  /**
319
343
  * Resolve one session's artifact path.
@@ -0,0 +1,16 @@
1
+ import { type DerivedEntry } from './store.js';
2
+ interface RecoveryWork {
3
+ readonly id: string;
4
+ readonly revision: string;
5
+ readonly path: string;
6
+ readonly bytes: number;
7
+ readonly stamp: string;
8
+ readonly priority: number;
9
+ readonly listeners: Set<(derived: DerivedEntry) => void>;
10
+ }
11
+ /** Deduplicate recovery per session/revision and retry damaged logs with backoff. */
12
+ export declare function scheduleTitleRecovery(work: Omit<RecoveryWork, 'listeners'>, onComplete?: (derived: DerivedEntry) => void): void;
13
+ /** A queued or backed-off revision needs no path lookup on another open. */
14
+ export declare function titleRecoveryNeedsWork(id: string, revision: string, onComplete?: (derived: DerivedEntry) => void): boolean;
15
+ export {};
16
+ //# sourceMappingURL=recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/sessions/recovery.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAErF,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC,CAAA;CACzD;AAqED,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI,CAa/H;AAED,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAS1H"}
@@ -0,0 +1,108 @@
1
+ /** Best-effort, process-local deep title recovery outside the listing path. */
2
+ import { fileFacts } from './frames.js';
3
+ import { recoverSessionTitle } from './digest.js';
4
+ import { indexFileStamp, readIndex, writeIndex } from './store.js';
5
+ const pending = new Map();
6
+ const retries = new Map();
7
+ const RETRY_DELAYS = [1000, 5000, 30_000, 300_000];
8
+ let running;
9
+ let scheduled = false;
10
+ function deferRetry(work) {
11
+ const old = retries.get(work.id);
12
+ const attempts = old?.revision === work.revision ? old.attempts + 1 : 1;
13
+ retries.set(work.id, {
14
+ revision: work.revision,
15
+ attempts,
16
+ retryAfter: Date.now() + RETRY_DELAYS[Math.min(attempts - 1, RETRY_DELAYS.length - 1)],
17
+ });
18
+ }
19
+ function kick() {
20
+ if (scheduled || running !== undefined || pending.size === 0)
21
+ return;
22
+ scheduled = true;
23
+ setImmediate(() => {
24
+ scheduled = false;
25
+ if (running !== undefined)
26
+ return;
27
+ const work = [...pending.values()].sort((a, b) => b.priority - a.priority)[0];
28
+ if (work === undefined)
29
+ return;
30
+ pending.delete(work.id);
31
+ running = work;
32
+ void recover(work).finally(() => {
33
+ running = undefined;
34
+ kick();
35
+ });
36
+ });
37
+ }
38
+ async function recover(work) {
39
+ try {
40
+ const recovered = await recoverSessionTitle(work.path, work.bytes);
41
+ const facts = fileFacts(work.path);
42
+ if (facts?.stamp !== work.stamp)
43
+ return;
44
+ if (!recovered.complete) {
45
+ deferRetry(work);
46
+ return;
47
+ }
48
+ const stamp = indexFileStamp();
49
+ const index = readIndex();
50
+ const entry = index.get(work.id);
51
+ if (entry?.derived?.revision !== work.revision || entry.derived.titleComplete)
52
+ return;
53
+ const derived = {
54
+ ...entry.derived,
55
+ title: recovered.title?.text ?? '',
56
+ titleSource: recovered.title?.source ?? 'fallback',
57
+ titleComplete: true,
58
+ hasPrompt: recovered.hasPrompt ?? entry.derived.hasPrompt,
59
+ };
60
+ index.set(work.id, { ...entry, derived });
61
+ if (indexFileStamp() !== stamp)
62
+ return;
63
+ writeIndex(index);
64
+ retries.delete(work.id);
65
+ for (const listener of work.listeners) {
66
+ try {
67
+ listener(derived);
68
+ }
69
+ catch { /* UI observers cannot fail recovery. */ }
70
+ }
71
+ }
72
+ catch {
73
+ // An unreadable or changing artifact remains visible with conservative
74
+ // metadata. Reopen retries under backoff, or immediately on revision change.
75
+ deferRetry(work);
76
+ }
77
+ }
78
+ /** Deduplicate recovery per session/revision and retry damaged logs with backoff. */
79
+ export function scheduleTitleRecovery(work, onComplete) {
80
+ const retry = retries.get(work.id);
81
+ if (retry?.revision !== work.revision)
82
+ retries.delete(work.id);
83
+ else if (Date.now() < retry.retryAfter)
84
+ return;
85
+ const existing = pending.get(work.id) ?? (running?.id === work.id ? running : undefined);
86
+ if (existing?.revision === work.revision) {
87
+ if (onComplete !== undefined)
88
+ existing.listeners.add(onComplete);
89
+ return;
90
+ }
91
+ const listeners = new Set();
92
+ if (onComplete !== undefined)
93
+ listeners.add(onComplete);
94
+ pending.set(work.id, { ...work, listeners });
95
+ kick();
96
+ }
97
+ /** A queued or backed-off revision needs no path lookup on another open. */
98
+ export function titleRecoveryNeedsWork(id, revision, onComplete) {
99
+ const existing = [pending.get(id), running?.id === id ? running : undefined]
100
+ .find(item => item?.revision === revision);
101
+ if (existing?.revision === revision) {
102
+ if (onComplete !== undefined)
103
+ existing.listeners.add(onComplete);
104
+ return false;
105
+ }
106
+ const retry = retries.get(id);
107
+ return retry?.revision !== revision || Date.now() >= retry.retryAfter;
108
+ }
@@ -0,0 +1,7 @@
1
+ import type { SessionSource } from './list.js';
2
+ import type { SessionSummary } from './types.js';
3
+ /** Undefined is unknown; an empty snapshot is a successful empty listing. */
4
+ export declare function readListingSnapshot(source: SessionSource): readonly SessionSummary[] | undefined;
5
+ /** Capture ordering before async work, including across distinct Context proxies. */
6
+ export declare function beginListingSnapshot(source: SessionSource): (rows: readonly SessionSummary[]) => void;
7
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/sessions/snapshot.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAiDhD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,cAAc,EAAE,GAAG,SAAS,CAGhG;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,KAAK,IAAI,CAiBrG"}