@vibefield/rosetta-room 0.0.0-stage → 0.1.1

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 (435) hide show
  1. package/README.md +247 -2
  2. package/dist/HistoryRoom.d.ts +98 -0
  3. package/dist/HistoryRoom.js +440 -0
  4. package/dist/TranscriptReader.d.ts +22 -0
  5. package/dist/TranscriptReader.js +72 -0
  6. package/dist/components/ColdStart.d.ts +4 -0
  7. package/dist/components/ColdStart.js +5 -0
  8. package/dist/components/FilterChips.d.ts +4 -0
  9. package/dist/components/FilterChips.js +5 -0
  10. package/dist/components/HostAct.d.ts +9 -0
  11. package/dist/components/HostAct.js +16 -0
  12. package/dist/components/HostMenu.d.ts +41 -0
  13. package/dist/components/HostMenu.js +216 -0
  14. package/dist/components/IngestStatus.d.ts +4 -0
  15. package/dist/components/IngestStatus.js +20 -0
  16. package/dist/components/ListActivityNotice.d.ts +5 -0
  17. package/dist/components/ListActivityNotice.js +4 -0
  18. package/dist/components/ListSections.d.ts +20 -0
  19. package/dist/components/ListSections.js +39 -0
  20. package/dist/components/RenameHeading.d.ts +9 -0
  21. package/dist/components/RenameHeading.js +75 -0
  22. package/dist/components/SearchStrip.d.ts +5 -0
  23. package/dist/components/SearchStrip.js +8 -0
  24. package/dist/components/SummaryMetrics.d.ts +13 -0
  25. package/dist/components/SummaryMetrics.js +9 -0
  26. package/dist/components/SummaryPanels.d.ts +35 -0
  27. package/dist/components/SummaryPanels.js +117 -0
  28. package/dist/components/Transcript.d.ts +46 -0
  29. package/dist/components/Transcript.js +358 -0
  30. package/dist/components/charts/ActivityChartDetail.d.ts +13 -0
  31. package/dist/components/charts/ActivityChartDetail.js +78 -0
  32. package/dist/components/charts/CalendarHeatmap.d.ts +16 -0
  33. package/dist/components/charts/CalendarHeatmap.js +55 -0
  34. package/dist/components/charts/DayActivityChart.d.ts +8 -0
  35. package/dist/components/charts/DayActivityChart.js +71 -0
  36. package/dist/components/charts/ModelsChartDetail.d.ts +7 -0
  37. package/dist/components/charts/ModelsChartDetail.js +19 -0
  38. package/dist/components/charts/ProjectChartDialog.d.ts +19 -0
  39. package/dist/components/charts/ProjectChartDialog.js +39 -0
  40. package/dist/components/charts/Streamgraph.d.ts +16 -0
  41. package/dist/components/charts/Streamgraph.js +94 -0
  42. package/dist/components/charts/Treemap.d.ts +26 -0
  43. package/dist/components/charts/Treemap.js +81 -0
  44. package/dist/components/charts/index.d.ts +9 -0
  45. package/dist/components/charts/index.js +4 -0
  46. package/dist/components/charts/streamgraph-layout.d.ts +23 -0
  47. package/dist/components/charts/streamgraph-layout.js +114 -0
  48. package/dist/components/charts/treemap-layout.d.ts +32 -0
  49. package/dist/components/charts/treemap-layout.js +140 -0
  50. package/dist/components/charts/types.d.ts +65 -0
  51. package/dist/components/charts/types.js +8 -0
  52. package/dist/components/file-viewer/FileViewerBrowsers.d.ts +10 -0
  53. package/dist/components/file-viewer/FileViewerBrowsers.js +65 -0
  54. package/dist/components/file-viewer/FileViewerDialog.d.ts +33 -0
  55. package/dist/components/file-viewer/FileViewerDialog.js +82 -0
  56. package/dist/components/file-viewer/FileViewerHeader.d.ts +26 -0
  57. package/dist/components/file-viewer/FileViewerHeader.js +17 -0
  58. package/dist/components/file-viewer/ImageGalleryDialog.d.ts +14 -0
  59. package/dist/components/file-viewer/ImageGalleryDialog.js +98 -0
  60. package/dist/components/file-viewer/diff/index.d.ts +2 -0
  61. package/dist/components/file-viewer/diff/index.js +2 -0
  62. package/dist/components/file-viewer/diff/parse.d.ts +2 -0
  63. package/dist/components/file-viewer/diff/parse.js +164 -0
  64. package/dist/components/file-viewer/diff/types.d.ts +44 -0
  65. package/dist/components/file-viewer/diff/types.js +7 -0
  66. package/dist/components/file-viewer/gallery-source.d.ts +11 -0
  67. package/dist/components/file-viewer/gallery-source.js +75 -0
  68. package/dist/components/file-viewer/image-resource.d.ts +19 -0
  69. package/dist/components/file-viewer/image-resource.js +60 -0
  70. package/dist/components/file-viewer/index.d.ts +5 -0
  71. package/dist/components/file-viewer/index.js +8 -0
  72. package/dist/components/file-viewer/markdown/blocks.d.ts +2 -0
  73. package/dist/components/file-viewer/markdown/blocks.js +277 -0
  74. package/dist/components/file-viewer/markdown/index.d.ts +4 -0
  75. package/dist/components/file-viewer/markdown/index.js +35 -0
  76. package/dist/components/file-viewer/markdown/inline.d.ts +10 -0
  77. package/dist/components/file-viewer/markdown/inline.js +178 -0
  78. package/dist/components/file-viewer/markdown/render.d.ts +9 -0
  79. package/dist/components/file-viewer/markdown/render.js +78 -0
  80. package/dist/components/file-viewer/markdown/types.d.ts +57 -0
  81. package/dist/components/file-viewer/markdown/types.js +11 -0
  82. package/dist/components/file-viewer/minimap/CodeMinimap.d.ts +10 -0
  83. package/dist/components/file-viewer/minimap/CodeMinimap.js +296 -0
  84. package/dist/components/file-viewer/minimap/layout.d.ts +60 -0
  85. package/dist/components/file-viewer/minimap/layout.js +117 -0
  86. package/dist/components/file-viewer/minimap/palette.d.ts +2 -0
  87. package/dist/components/file-viewer/minimap/palette.js +73 -0
  88. package/dist/components/file-viewer/minimap/raster.d.ts +19 -0
  89. package/dist/components/file-viewer/minimap/raster.js +122 -0
  90. package/dist/components/file-viewer/registry.d.ts +25 -0
  91. package/dist/components/file-viewer/registry.js +182 -0
  92. package/dist/components/file-viewer/syntax/grammars.d.ts +16 -0
  93. package/dist/components/file-viewer/syntax/grammars.js +221 -0
  94. package/dist/components/file-viewer/syntax/index.d.ts +8 -0
  95. package/dist/components/file-viewer/syntax/index.js +9 -0
  96. package/dist/components/file-viewer/syntax/languages.d.ts +14 -0
  97. package/dist/components/file-viewer/syntax/languages.js +115 -0
  98. package/dist/components/file-viewer/syntax/tokenize-config.d.ts +2 -0
  99. package/dist/components/file-viewer/syntax/tokenize-config.js +132 -0
  100. package/dist/components/file-viewer/syntax/tokenize-css.d.ts +2 -0
  101. package/dist/components/file-viewer/syntax/tokenize-css.js +169 -0
  102. package/dist/components/file-viewer/syntax/tokenize-markup.d.ts +2 -0
  103. package/dist/components/file-viewer/syntax/tokenize-markup.js +124 -0
  104. package/dist/components/file-viewer/syntax/tokenize.d.ts +9 -0
  105. package/dist/components/file-viewer/syntax/tokenize.js +289 -0
  106. package/dist/components/file-viewer/syntax/types.d.ts +74 -0
  107. package/dist/components/file-viewer/syntax/types.js +13 -0
  108. package/dist/components/file-viewer/types.d.ts +111 -0
  109. package/dist/components/file-viewer/types.js +8 -0
  110. package/dist/components/file-viewer/use-file-content.d.ts +26 -0
  111. package/dist/components/file-viewer/use-file-content.js +144 -0
  112. package/dist/components/file-viewer/views/BinaryView.d.ts +2 -0
  113. package/dist/components/file-viewer/views/BinaryView.js +34 -0
  114. package/dist/components/file-viewer/views/CodeView.d.ts +2 -0
  115. package/dist/components/file-viewer/views/CodeView.js +46 -0
  116. package/dist/components/file-viewer/views/DiffBody.d.ts +7 -0
  117. package/dist/components/file-viewer/views/DiffBody.js +77 -0
  118. package/dist/components/file-viewer/views/DiffView.d.ts +2 -0
  119. package/dist/components/file-viewer/views/DiffView.js +11 -0
  120. package/dist/components/file-viewer/views/ImageView.d.ts +9 -0
  121. package/dist/components/file-viewer/views/ImageView.js +28 -0
  122. package/dist/components/file-viewer/views/MarkdownView.d.ts +9 -0
  123. package/dist/components/file-viewer/views/MarkdownView.js +20 -0
  124. package/dist/components/file-viewer/views/SvgView.d.ts +9 -0
  125. package/dist/components/file-viewer/views/SvgView.js +10 -0
  126. package/dist/components/git/ChangeTree.d.ts +20 -0
  127. package/dist/components/git/ChangeTree.js +35 -0
  128. package/dist/components/git/CommitViewer.d.ts +12 -0
  129. package/dist/components/git/CommitViewer.js +85 -0
  130. package/dist/components/git/GitChanges.d.ts +17 -0
  131. package/dist/components/git/GitChanges.js +70 -0
  132. package/dist/components/git/GitHistory.d.ts +9 -0
  133. package/dist/components/git/GitHistory.js +58 -0
  134. package/dist/components/git/co-author.d.ts +14 -0
  135. package/dist/components/git/co-author.js +55 -0
  136. package/dist/components/git/git-file-source.d.ts +18 -0
  137. package/dist/components/git/git-file-source.js +53 -0
  138. package/dist/components/git/git-host.d.ts +24 -0
  139. package/dist/components/git/git-host.js +130 -0
  140. package/dist/components/git/index.d.ts +10 -0
  141. package/dist/components/git/index.js +12 -0
  142. package/dist/components/git/path-tree.d.ts +23 -0
  143. package/dist/components/git/path-tree.js +73 -0
  144. package/dist/components/git/session-files.d.ts +9 -0
  145. package/dist/components/git/session-files.js +50 -0
  146. package/dist/components/git/types.d.ts +92 -0
  147. package/dist/components/git/types.js +9 -0
  148. package/dist/components/projects/ProjectActivitySparkline.d.ts +6 -0
  149. package/dist/components/projects/ProjectActivitySparkline.js +12 -0
  150. package/dist/components/projects/ProjectList.d.ts +25 -0
  151. package/dist/components/projects/ProjectList.js +43 -0
  152. package/dist/components/projects/ProjectListItem.d.ts +19 -0
  153. package/dist/components/projects/ProjectListItem.js +78 -0
  154. package/dist/components/projects/ProjectsColumn.d.ts +19 -0
  155. package/dist/components/projects/ProjectsColumn.js +36 -0
  156. package/dist/components/projects/index.d.ts +8 -0
  157. package/dist/components/projects/index.js +4 -0
  158. package/dist/components/search/MatchStepper.d.ts +9 -0
  159. package/dist/components/search/MatchStepper.js +14 -0
  160. package/dist/components/search/SearchLauncher.d.ts +12 -0
  161. package/dist/components/search/SearchLauncher.js +13 -0
  162. package/dist/components/search/SearchSheet.d.ts +29 -0
  163. package/dist/components/search/SearchSheet.js +230 -0
  164. package/dist/components/search/index.d.ts +8 -0
  165. package/dist/components/search/index.js +4 -0
  166. package/dist/components/search/shortcut.d.ts +25 -0
  167. package/dist/components/search/shortcut.js +32 -0
  168. package/dist/components/sessions/SessionList.d.ts +24 -0
  169. package/dist/components/sessions/SessionList.js +76 -0
  170. package/dist/components/sessions/SessionListItem.d.ts +13 -0
  171. package/dist/components/sessions/SessionListItem.js +58 -0
  172. package/dist/components/sessions/SessionsColumn.d.ts +26 -0
  173. package/dist/components/sessions/SessionsColumn.js +32 -0
  174. package/dist/components/sessions/index.d.ts +9 -0
  175. package/dist/components/sessions/index.js +4 -0
  176. package/dist/components/sessions/session-display.d.ts +8 -0
  177. package/dist/components/sessions/session-display.js +18 -0
  178. package/dist/components/sessions/types.d.ts +7 -0
  179. package/dist/components/sessions/types.js +1 -0
  180. package/dist/components/transcript/Activity.d.ts +45 -0
  181. package/dist/components/transcript/Activity.js +75 -0
  182. package/dist/components/transcript/Anchor.d.ts +8 -0
  183. package/dist/components/transcript/Anchor.js +23 -0
  184. package/dist/components/transcript/Attachments.d.ts +21 -0
  185. package/dist/components/transcript/Attachments.js +138 -0
  186. package/dist/components/transcript/AuthoredMessage.d.ts +19 -0
  187. package/dist/components/transcript/AuthoredMessage.js +17 -0
  188. package/dist/components/transcript/Compaction.d.ts +9 -0
  189. package/dist/components/transcript/Compaction.js +50 -0
  190. package/dist/components/transcript/DayPill.d.ts +38 -0
  191. package/dist/components/transcript/DayPill.js +68 -0
  192. package/dist/components/transcript/Document.d.ts +32 -0
  193. package/dist/components/transcript/Document.js +503 -0
  194. package/dist/components/transcript/Favicon.d.ts +32 -0
  195. package/dist/components/transcript/Favicon.js +71 -0
  196. package/dist/components/transcript/HeadOfDocument.d.ts +19 -0
  197. package/dist/components/transcript/HeadOfDocument.js +44 -0
  198. package/dist/components/transcript/Ledger.d.ts +53 -0
  199. package/dist/components/transcript/Ledger.js +182 -0
  200. package/dist/components/transcript/LineDetail.d.ts +24 -0
  201. package/dist/components/transcript/LineDetail.js +81 -0
  202. package/dist/components/transcript/Marker.d.ts +33 -0
  203. package/dist/components/transcript/Marker.js +21 -0
  204. package/dist/components/transcript/MessagePreview.d.ts +12 -0
  205. package/dist/components/transcript/MessagePreview.js +58 -0
  206. package/dist/components/transcript/Prompt.d.ts +20 -0
  207. package/dist/components/transcript/Prompt.js +55 -0
  208. package/dist/components/transcript/Prose.d.ts +19 -0
  209. package/dist/components/transcript/Prose.js +109 -0
  210. package/dist/components/transcript/ReceiptPill.d.ts +10 -0
  211. package/dist/components/transcript/ReceiptPill.js +10 -0
  212. package/dist/components/transcript/ResponseHead.d.ts +9 -0
  213. package/dist/components/transcript/ResponseHead.js +36 -0
  214. package/dist/components/transcript/Subthread.d.ts +19 -0
  215. package/dist/components/transcript/Subthread.js +96 -0
  216. package/dist/components/transcript/Team.d.ts +53 -0
  217. package/dist/components/transcript/Team.js +185 -0
  218. package/dist/components/transcript/Thinking.d.ts +24 -0
  219. package/dist/components/transcript/Thinking.js +50 -0
  220. package/dist/components/transcript/TimelineMeta.d.ts +9 -0
  221. package/dist/components/transcript/TimelineMeta.js +161 -0
  222. package/dist/components/transcript/TranscriptLoading.d.ts +10 -0
  223. package/dist/components/transcript/TranscriptLoading.js +10 -0
  224. package/dist/components/transcript/WebDetail.d.ts +8 -0
  225. package/dist/components/transcript/WebDetail.js +29 -0
  226. package/dist/components/transcript/Workflow.d.ts +12 -0
  227. package/dist/components/transcript/Workflow.js +208 -0
  228. package/dist/components/transcript/activity-plan.d.ts +84 -0
  229. package/dist/components/transcript/activity-plan.js +209 -0
  230. package/dist/components/transcript/attachment-file-source.d.ts +23 -0
  231. package/dist/components/transcript/attachment-file-source.js +103 -0
  232. package/dist/components/transcript/attachment-gallery.d.ts +12 -0
  233. package/dist/components/transcript/attachment-gallery.js +33 -0
  234. package/dist/components/transcript/detail-parts.d.ts +50 -0
  235. package/dist/components/transcript/detail-parts.js +295 -0
  236. package/dist/components/transcript/disclosure-state.d.ts +6 -0
  237. package/dist/components/transcript/disclosure-state.js +32 -0
  238. package/dist/components/transcript/disclosure-store.d.ts +8 -0
  239. package/dist/components/transcript/disclosure-store.js +31 -0
  240. package/dist/components/transcript/document-model.d.ts +15 -0
  241. package/dist/components/transcript/document-model.js +104 -0
  242. package/dist/components/transcript/document-plan.d.ts +28 -0
  243. package/dist/components/transcript/document-plan.js +145 -0
  244. package/dist/components/transcript/fold-preference.d.ts +17 -0
  245. package/dist/components/transcript/fold-preference.js +63 -0
  246. package/dist/components/transcript/glyphs.d.ts +15 -0
  247. package/dist/components/transcript/glyphs.js +47 -0
  248. package/dist/components/transcript/index.d.ts +23 -0
  249. package/dist/components/transcript/index.js +22 -0
  250. package/dist/components/transcript/message-file-source.d.ts +15 -0
  251. package/dist/components/transcript/message-file-source.js +31 -0
  252. package/dist/components/transcript/message-preview.d.ts +9 -0
  253. package/dist/components/transcript/message-preview.js +46 -0
  254. package/dist/components/transcript/read-file-source.d.ts +7 -0
  255. package/dist/components/transcript/read-file-source.js +34 -0
  256. package/dist/components/transcript/reader-context.d.ts +13 -0
  257. package/dist/components/transcript/reader-context.js +55 -0
  258. package/dist/components/transcript/reading-identity.d.ts +2 -0
  259. package/dist/components/transcript/reading-identity.js +52 -0
  260. package/dist/components/transcript/scroll-to-row.d.ts +2 -0
  261. package/dist/components/transcript/scroll-to-row.js +13 -0
  262. package/dist/components/transcript/thread-index.d.ts +14 -0
  263. package/dist/components/transcript/thread-index.js +40 -0
  264. package/dist/components/transcript/thread-navigation.d.ts +5 -0
  265. package/dist/components/transcript/thread-navigation.js +3 -0
  266. package/dist/components/transcript/timeline-meta-file-source.d.ts +6 -0
  267. package/dist/components/transcript/timeline-meta-file-source.js +55 -0
  268. package/dist/components/transcript/timeline-meta-state.d.ts +12 -0
  269. package/dist/components/transcript/timeline-meta-state.js +24 -0
  270. package/dist/components/ui/ColumnHeading.d.ts +27 -0
  271. package/dist/components/ui/ColumnHeading.js +7 -0
  272. package/dist/components/ui/ConfirmDialog.d.ts +14 -0
  273. package/dist/components/ui/ConfirmDialog.js +22 -0
  274. package/dist/components/ui/DialogShell.d.ts +18 -0
  275. package/dist/components/ui/DialogShell.js +40 -0
  276. package/dist/components/ui/EmptyState.d.ts +10 -0
  277. package/dist/components/ui/EmptyState.js +6 -0
  278. package/dist/components/ui/ListSummaryHeader.d.ts +9 -0
  279. package/dist/components/ui/ListSummaryHeader.js +6 -0
  280. package/dist/components/ui/ListToolbar.d.ts +6 -0
  281. package/dist/components/ui/ListToolbar.js +5 -0
  282. package/dist/components/ui/ResultGroupHeader.d.ts +9 -0
  283. package/dist/components/ui/ResultGroupHeader.js +5 -0
  284. package/dist/components/ui/SegmentedControl.d.ts +16 -0
  285. package/dist/components/ui/SegmentedControl.js +9 -0
  286. package/dist/components/ui/SummaryMetric.d.ts +13 -0
  287. package/dist/components/ui/SummaryMetric.js +10 -0
  288. package/dist/components/ui/Veil.d.ts +7 -0
  289. package/dist/components/ui/Veil.js +5 -0
  290. package/dist/components/ui/index.d.ts +20 -0
  291. package/dist/components/ui/index.js +10 -0
  292. package/dist/components/worktree/WorktreeColumn.d.ts +22 -0
  293. package/dist/components/worktree/WorktreeColumn.js +170 -0
  294. package/dist/components/worktree/WorktreeFileTree.d.ts +19 -0
  295. package/dist/components/worktree/WorktreeFileTree.js +60 -0
  296. package/dist/components/worktree/WorktreeHeader.d.ts +32 -0
  297. package/dist/components/worktree/WorktreeHeader.js +81 -0
  298. package/dist/components/worktree/WorktreeList.d.ts +8 -0
  299. package/dist/components/worktree/WorktreeList.js +12 -0
  300. package/dist/components/worktree/index.d.ts +12 -0
  301. package/dist/components/worktree/index.js +7 -0
  302. package/dist/components/worktree/types.d.ts +17 -0
  303. package/dist/components/worktree/types.js +3 -0
  304. package/dist/components/worktree/use-worktree-guest.d.ts +21 -0
  305. package/dist/components/worktree/use-worktree-guest.js +92 -0
  306. package/dist/components/worktree/worktree-file-commands.d.ts +19 -0
  307. package/dist/components/worktree/worktree-file-commands.js +112 -0
  308. package/dist/components/worktree/worktree-file-source.d.ts +15 -0
  309. package/dist/components/worktree/worktree-file-source.js +75 -0
  310. package/dist/components/worktree/worktree-host.d.ts +31 -0
  311. package/dist/components/worktree/worktree-host.js +242 -0
  312. package/dist/fixtures/index.d.ts +24 -0
  313. package/dist/fixtures/index.js +292 -0
  314. package/dist/host-inputs.d.ts +231 -0
  315. package/dist/host-inputs.js +35 -0
  316. package/dist/index.d.ts +18 -0
  317. package/dist/index.js +14 -0
  318. package/dist/lib/activity-details.d.ts +23 -0
  319. package/dist/lib/activity-details.js +78 -0
  320. package/dist/lib/activity-order.d.ts +32 -0
  321. package/dist/lib/activity-order.js +86 -0
  322. package/dist/lib/agent-paths.d.ts +6 -0
  323. package/dist/lib/agent-paths.js +19 -0
  324. package/dist/lib/agents.d.ts +15 -0
  325. package/dist/lib/agents.js +60 -0
  326. package/dist/lib/catalog-status.d.ts +3 -0
  327. package/dist/lib/catalog-status.js +10 -0
  328. package/dist/lib/chart-data.d.ts +14 -0
  329. package/dist/lib/chart-data.js +151 -0
  330. package/dist/lib/day-activity.d.ts +21 -0
  331. package/dist/lib/day-activity.js +56 -0
  332. package/dist/lib/format.d.ts +24 -0
  333. package/dist/lib/format.js +116 -0
  334. package/dist/lib/hooks.d.ts +118 -0
  335. package/dist/lib/hooks.js +608 -0
  336. package/dist/lib/icons.d.ts +21 -0
  337. package/dist/lib/icons.js +49 -0
  338. package/dist/lib/image-media.d.ts +6 -0
  339. package/dist/lib/image-media.js +30 -0
  340. package/dist/lib/ingest-activity.d.ts +50 -0
  341. package/dist/lib/ingest-activity.js +151 -0
  342. package/dist/lib/ingest.d.ts +25 -0
  343. package/dist/lib/ingest.js +70 -0
  344. package/dist/lib/model-labels.d.ts +5 -0
  345. package/dist/lib/model-labels.js +28 -0
  346. package/dist/lib/model.d.ts +73 -0
  347. package/dist/lib/model.js +141 -0
  348. package/dist/lib/motion.d.ts +13 -0
  349. package/dist/lib/motion.js +80 -0
  350. package/dist/lib/room-storage.d.ts +13 -0
  351. package/dist/lib/room-storage.js +40 -0
  352. package/dist/lib/search-results.d.ts +27 -0
  353. package/dist/lib/search-results.js +83 -0
  354. package/dist/lib/search-sheet.d.ts +119 -0
  355. package/dist/lib/search-sheet.js +282 -0
  356. package/dist/lib/sections.d.ts +19 -0
  357. package/dist/lib/sections.js +36 -0
  358. package/dist/lib/session-activity.d.ts +5 -0
  359. package/dist/lib/session-activity.js +15 -0
  360. package/dist/lib/session-leases.d.ts +15 -0
  361. package/dist/lib/session-leases.js +61 -0
  362. package/dist/lib/spend.d.ts +42 -0
  363. package/dist/lib/spend.js +112 -0
  364. package/dist/lib/tint.d.ts +9 -0
  365. package/dist/lib/tint.js +53 -0
  366. package/dist/lib/transcript/collaboration.d.ts +97 -0
  367. package/dist/lib/transcript/collaboration.js +423 -0
  368. package/dist/lib/transcript/families.d.ts +212 -0
  369. package/dist/lib/transcript/families.js +906 -0
  370. package/dist/lib/transcript/favicons.d.ts +54 -0
  371. package/dist/lib/transcript/favicons.js +183 -0
  372. package/dist/lib/transcript/head-of-document.d.ts +27 -0
  373. package/dist/lib/transcript/head-of-document.js +274 -0
  374. package/dist/lib/transcript/head-state.d.ts +182 -0
  375. package/dist/lib/transcript/head-state.js +305 -0
  376. package/dist/lib/transcript/history-window.d.ts +13 -0
  377. package/dist/lib/transcript/history-window.js +52 -0
  378. package/dist/lib/transcript/images.d.ts +8 -0
  379. package/dist/lib/transcript/images.js +60 -0
  380. package/dist/lib/transcript/index.d.ts +15 -0
  381. package/dist/lib/transcript/index.js +8 -0
  382. package/dist/lib/transcript/ledger.d.ts +143 -0
  383. package/dist/lib/transcript/ledger.js +513 -0
  384. package/dist/lib/transcript/protocol.d.ts +23 -0
  385. package/dist/lib/transcript/protocol.js +1 -0
  386. package/dist/lib/transcript/sittings.d.ts +75 -0
  387. package/dist/lib/transcript/sittings.js +147 -0
  388. package/dist/lib/transcript/tail-scroll.d.ts +36 -0
  389. package/dist/lib/transcript/tail-scroll.js +167 -0
  390. package/dist/lib/transcript/tail-state.d.ts +17 -0
  391. package/dist/lib/transcript/tail-state.js +30 -0
  392. package/dist/lib/transcript/turns.d.ts +192 -0
  393. package/dist/lib/transcript/turns.js +576 -0
  394. package/dist/lib/transcript/use-transcript-opening.d.ts +12 -0
  395. package/dist/lib/transcript/use-transcript-opening.js +31 -0
  396. package/dist/lib/transcript/use-transcript-tail.d.ts +25 -0
  397. package/dist/lib/transcript/use-transcript-tail.js +158 -0
  398. package/dist/lib/transcript/vocabulary.d.ts +119 -0
  399. package/dist/lib/transcript/vocabulary.js +293 -0
  400. package/dist/lib/transcript/web-address.d.ts +6 -0
  401. package/dist/lib/transcript/web-address.js +18 -0
  402. package/dist/lib/transcript/workflow.d.ts +31 -0
  403. package/dist/lib/transcript/workflow.js +133 -0
  404. package/dist/lib/use-activity-order.d.ts +2 -0
  405. package/dist/lib/use-activity-order.js +23 -0
  406. package/dist/lib/use-day-usage.d.ts +8 -0
  407. package/dist/lib/use-day-usage.js +31 -0
  408. package/dist/lib/use-deferred-list-order.d.ts +26 -0
  409. package/dist/lib/use-deferred-list-order.js +142 -0
  410. package/dist/lib/use-ingest-activity.d.ts +2 -0
  411. package/dist/lib/use-ingest-activity.js +49 -0
  412. package/dist/lib/use-list-motion.d.ts +4 -0
  413. package/dist/lib/use-list-motion.js +67 -0
  414. package/dist/ports.d.ts +222 -0
  415. package/dist/ports.js +3 -0
  416. package/dist/room-context.d.ts +60 -0
  417. package/dist/room-context.js +87 -0
  418. package/dist/styles/activity-chart.css +127 -0
  419. package/dist/styles/attachments.css +29 -0
  420. package/dist/styles/favicon.css +73 -0
  421. package/dist/styles/history-room.css +18 -0
  422. package/dist/styles/host-inputs.css +250 -0
  423. package/dist/styles/image-gallery.css +30 -0
  424. package/dist/styles/ingest.css +51 -0
  425. package/dist/styles/message-preview.css +34 -0
  426. package/dist/styles/models-chart.css +66 -0
  427. package/dist/styles/project-chart.css +19 -0
  428. package/dist/styles/reader.css +33 -0
  429. package/dist/styles/room.css +1411 -0
  430. package/dist/styles/search.css +252 -0
  431. package/dist/styles/transcript-activity.css +70 -0
  432. package/dist/styles/transcript-head.css +220 -0
  433. package/dist/styles/transcript-loading.css +57 -0
  434. package/dist/styles/transcript.css +1226 -0
  435. package/package.json +61 -4
@@ -0,0 +1,143 @@
1
+ import type { TimelineEntry } from "@vibefield/rosetta-protocol";
2
+ import type { LedgerDetail } from "./families.js";
3
+ import type { LedgerClass, LedgerContext, LedgerGlyph, ObjectPart, ToolFamily } from "./vocabulary.js";
4
+ /** Even a single activity line closes to its head (2026-09-09 amendment). */
5
+ export declare const RUN_FOLD_THRESHOLD = 1;
6
+ /** How many members a fold names before it degrades to `… N more`. */
7
+ export declare const FOLD_NAME_LIMIT = 4;
8
+ /**
9
+ * T-5. `failed` is red (failed · denied · timed out — the act did not
10
+ * complete). `muted` is not red, because nothing failed: cancelled,
11
+ * interrupted, and a status the source never proved. `running` is the green
12
+ * breath, and only a live session should draw it as alive. Success is the
13
+ * absence of all three.
14
+ */
15
+ export type LedgerState = "done" | "running" | "failed" | "muted";
16
+ /**
17
+ * How the result slot is drawn. `plain` and `muted` are bare spans; `failed`
18
+ * and `running` are the record's `.why` span, which takes its hue from the
19
+ * line's state.
20
+ */
21
+ export type ResultTone = "plain" | "failed" | "muted" | "running";
22
+ export interface LedgerLine {
23
+ /** Stable across renders: the first member row's `timeline_id`. */
24
+ readonly key: string;
25
+ /** Every row behind this line — one, or a fold's members. Anchors, focus
26
+ * landing and the watermark all read `timeline_id` / `ordinal` from here. */
27
+ readonly rows: readonly TimelineEntry[];
28
+ readonly family: ToolFamily;
29
+ readonly cls: LedgerClass;
30
+ /** The FAMILY glyph. A `failed` line draws `#g-fail` in this slot instead,
31
+ * and a `running` line draws the breathing dot — state substitutes, the
32
+ * name does not change. */
33
+ readonly glyph: LedgerGlyph;
34
+ readonly verb: string;
35
+ /** Concatenate in order with no separator; each part carries its own
36
+ * spacing. `tone` names the record's own class: plain · dir · query · aside. */
37
+ readonly object: readonly ObjectPart[];
38
+ readonly result: string | null;
39
+ readonly resultTone: ResultTone;
40
+ readonly state: LedgerState;
41
+ /** Time-of-day for the margin anchor: `completed_at ?? row.at`, and a fold's
42
+ * first stamp — or its LAST when `elided`. */
43
+ readonly at: number | null;
44
+ readonly startedAt: number | null;
45
+ readonly endedAt: number | null;
46
+ /** The line's own span when the source proved one. When `result` is null the
47
+ * projection has already put this in `result` as `21s`. */
48
+ readonly durationMs: number | null;
49
+ readonly detail: LedgerDetail;
50
+ /** §04: a question, a finding, a structured document — and any failure whose
51
+ * diagnostic is longer than the one phrase the result slot can hold. */
52
+ readonly openByDefault: boolean;
53
+ readonly folded: boolean;
54
+ /** Members in the fold; 1 for a plain line. */
55
+ readonly foldCount: number;
56
+ /** The fold gave up naming its members; draw `→` before `at`. */
57
+ readonly elided: boolean;
58
+ /** Proven child sessions this line owns — the component resolves each to a
59
+ * subthread drawn under the line (§03 F). */
60
+ readonly childSessionIds: readonly string[];
61
+ /** The bounded failure text, when there is one. Never the tool's output. */
62
+ readonly diagnostic: string | null;
63
+ }
64
+ /** Every proven child session a row owns — the same fact `Transcript.tsx`
65
+ * already places subthreads by, exported so the component keeps one source. */
66
+ export declare function linkedChildSessionIds(row: TimelineEntry): readonly string[];
67
+ /**
68
+ * One `tool_use` row as one ledger line: the §04 sentence, wrapped in the
69
+ * evidence the row actually carries. Throws if the row is not a tool use —
70
+ * `documentTurns` never hands it anything else.
71
+ */
72
+ export declare function ledgerLine(row: TimelineEntry, context?: LedgerContext): LedgerLine;
73
+ /**
74
+ * A command's name for a fold's list: the program, plus the first argument
75
+ * that is not a flag or a flag's value, each reduced to its own last segment.
76
+ * `pnpm -F field-app test` → `pnpm test`; `cargo clippy --all-targets --
77
+ * -D warnings` → `cargo clippy`; `node scripts/probe-silhouette.mjs --bays 1`
78
+ * → `node probe-silhouette`; `ls` → `ls`. Those are the record's own four
79
+ * drawings, and they are what this reproduces.
80
+ *
81
+ * Flag ARITY is unknowable from the text, so a single-dash flag is assumed to
82
+ * take a value (which is what `-F field-app` needs). When that assumption lands
83
+ * on a token that names nothing — `grep -r x .` reaches `.` — the program
84
+ * stands alone rather than the fold reading `grep .`.
85
+ */
86
+ export declare function commandName(command: string): string;
87
+ /**
88
+ * A contiguous run of `tool_use` rows as the lines the ledger draws. Folding
89
+ * happens here and only here — see the rules at the top of this module.
90
+ */
91
+ export declare function ledgerLines(rows: readonly TimelineEntry[], context?: LedgerContext): LedgerLine[];
92
+ /**
93
+ * One noun of the head's sentence. `names` is non-empty only for `file_change`
94
+ * — the changed files, up to FOLD_NAME_LIMIT, the fold line's own device — and
95
+ * `more` counts the ones past the limit. Two files that share a name keep
96
+ * their directory (`a/index.ts, b/index.ts`), so two edits never read as one.
97
+ * A run with no tool lines says the one thing it holds: `2 thoughts`.
98
+ */
99
+ export interface RunNoun {
100
+ readonly family: ToolFamily | "thinking";
101
+ readonly text: string;
102
+ readonly names: readonly string[];
103
+ readonly more: number;
104
+ }
105
+ /** A member of the run that is not a tool line, as the sentence needs it. */
106
+ export type RunOther = {
107
+ readonly kind: "thinking";
108
+ readonly row: TimelineEntry;
109
+ } | {
110
+ readonly kind: "marker";
111
+ readonly row: TimelineEntry;
112
+ readonly failed: boolean;
113
+ } | {
114
+ readonly kind: "summary";
115
+ readonly row: TimelineEntry;
116
+ };
117
+ export interface RunSummary {
118
+ /** Acts first, then looks, each class by count — `3 edits`, `17 commands`,
119
+ * `4 reads` — counted over ROWS so a fold does not shrink the figure. */
120
+ readonly nouns: readonly RunNoun[];
121
+ /** Lines that did not complete: failed, denied, timed out. Drawn in red at
122
+ * the right beside the span, where a narrow column cannot hide it. */
123
+ readonly failed: number;
124
+ /** Notices inside the run that state a failure: a runtime error, a failed
125
+ * async task. Drawn beside `failed`, in the same red. */
126
+ readonly errors: number;
127
+ /** The whole run's span, from its first known stamp to its last. Raw
128
+ * milliseconds: the record draws a span only once it is at least a second,
129
+ * which is a presentation threshold and stays with the component. */
130
+ readonly spanMs: number | null;
131
+ /** Tool lines the ladder draws. */
132
+ readonly lineCount: number;
133
+ readonly rowCount: number;
134
+ /** Lines plus thoughts, markers and summaries — what decides the fold. */
135
+ readonly memberCount: number;
136
+ /** Reasoning is silent in the sentence unless it is all the run has. */
137
+ readonly thoughtCount: number;
138
+ /** The last line still running — a live head carries it (Q11 A). */
139
+ readonly running: LedgerLine | null;
140
+ /** The run opens closed. The component may still force it open for focus. */
141
+ readonly closedByDefault: boolean;
142
+ }
143
+ export declare function runSummary(lines: readonly LedgerLine[], others?: readonly RunOther[]): RunSummary;
@@ -0,0 +1,513 @@
1
+ import { projectAction } from "./families.js";
2
+ import { FAMILY_CLASS, FOLD_NOUN, basename, canonicalText, familyNoun, firstLine, part, resourceLabel, rowStamps, spanText, stampSpan, urlHost, } from "./vocabulary.js";
3
+ /** Even a single activity line closes to its head (2026-09-09 amendment). */
4
+ export const RUN_FOLD_THRESHOLD = 1;
5
+ /** How many members a fold names before it degrades to `… N more`. */
6
+ export const FOLD_NAME_LIMIT = 4;
7
+ /* ── one row ─────────────────────────────────────────────────────────────── */
8
+ function toolOf(row) {
9
+ if (row.body.type !== "tool_use") {
10
+ throw new Error(`timeline entry ${row.timeline_id} is not a tool use`);
11
+ }
12
+ return row.body.tool;
13
+ }
14
+ function stateOf(status, basis) {
15
+ switch (status) {
16
+ case "failed":
17
+ case "denied":
18
+ case "timed_out":
19
+ return "failed";
20
+ case "cancelled":
21
+ case "interrupted":
22
+ return "muted";
23
+ case "unknown":
24
+ // A terminal record proves that the call finished even when its native
25
+ // format omitted success/failure. Treat that as neutral completion; it
26
+ // must not look live, failed, or like a warning.
27
+ return basis === "native_terminal_record" ? "done" : "muted";
28
+ case "pending":
29
+ case "running":
30
+ return "running";
31
+ case "succeeded":
32
+ return "done";
33
+ }
34
+ }
35
+ /** `timed out` · `status unknown`. Proven completion says nothing at all. */
36
+ function statusWord(status, basis) {
37
+ if (status === "succeeded")
38
+ return null;
39
+ if (status === "unknown") {
40
+ return basis === "native_terminal_record" ? null : "status unknown";
41
+ }
42
+ return status.replaceAll("_", " ");
43
+ }
44
+ /**
45
+ * The failure's own words, which always beat the family's outcome — Grok
46
+ * reporting `found 0 matches` as a failure is drawn in red with the source's
47
+ * sentence, not with the vocabulary's cheerful `found nothing`.
48
+ */
49
+ function failureResult(tool, action) {
50
+ const text = tool.failure?.summary ?? tool.failure?.diagnostic ?? null;
51
+ const line = text === null ? null : firstLine(text, 60);
52
+ const timedOut = tool.status.value === "timed_out" || tool.failure?.kind === "timeout";
53
+ if ((action.type === "web_fetch" || action.type === "web_navigate") && !timedOut) {
54
+ const status = action.outcome?.http_status;
55
+ if (status != null && status >= 400)
56
+ return `HTTP ${status}`;
57
+ }
58
+ if (action.type === "shell" || action.type === "code_execute") {
59
+ if (timedOut) {
60
+ // The BUDGET, in the seconds the caller set it in — `timed out · 120s`
61
+ // (§04). It is a limit that was hit, not a span that was measured.
62
+ const budget = action.type === "shell" ? action.timeout_ms : null;
63
+ return budget === null ? "timed out" : `timed out · ${Math.round(budget / 1000)}s`;
64
+ }
65
+ const exit = action.outcome?.exit_code ?? null;
66
+ const code = exit === null || exit === 0 ? null : `exit ${exit}`;
67
+ if (code === null)
68
+ return line;
69
+ return line === null ? code : `${code} · ${line}`;
70
+ }
71
+ if (timedOut && line === null)
72
+ return "timed out";
73
+ return line;
74
+ }
75
+ function childSessionIdsOf(action) {
76
+ switch (action.type) {
77
+ case "delegate":
78
+ return action.child_session_id === null ? [] : [action.child_session_id];
79
+ case "collaborate":
80
+ return action.linked_session_id === null ? [] : [action.linked_session_id];
81
+ case "workflow":
82
+ return action.run == null
83
+ ? []
84
+ : [...new Set(action.run.workers.flatMap((worker) => worker.child_session_id === null ? [] : [worker.child_session_id]))];
85
+ default:
86
+ return [];
87
+ }
88
+ }
89
+ function workflowState(action, fallback) {
90
+ if (action.type !== "workflow" || action.run == null)
91
+ return fallback;
92
+ switch (action.run.status) {
93
+ case "completed":
94
+ return "done";
95
+ case "running":
96
+ return "running";
97
+ case "failed":
98
+ return "failed";
99
+ case "killed":
100
+ case "cancelled":
101
+ case "stopped":
102
+ case "unknown":
103
+ return "muted";
104
+ }
105
+ }
106
+ /** Every proven child session a row owns — the same fact `Transcript.tsx`
107
+ * already places subthreads by, exported so the component keeps one source. */
108
+ export function linkedChildSessionIds(row) {
109
+ return row.body.type === "tool_use" ? childSessionIdsOf(row.body.tool.action) : [];
110
+ }
111
+ /**
112
+ * One `tool_use` row as one ledger line: the §04 sentence, wrapped in the
113
+ * evidence the row actually carries. Throws if the row is not a tool use —
114
+ * `documentTurns` never hands it anything else.
115
+ */
116
+ export function ledgerLine(row, context = {}) {
117
+ const tool = toolOf(row);
118
+ const action = tool.action;
119
+ const projection = projectAction(action, tool.native, context, {
120
+ sessionId: row.session_id,
121
+ timelineId: row.timeline_id,
122
+ });
123
+ const status = tool.status.value;
124
+ const statusBasis = tool.status.basis;
125
+ // The unknown family is never plain: the row is honest about knowing nothing,
126
+ // and the muted state is what italicises `no detail recorded`.
127
+ const rawState = workflowState(action, stateOf(status, statusBasis));
128
+ const state = action.type === "unknown" && rawState === "done" ? "muted" : rawState;
129
+ const object = [...projection.object];
130
+ if (action.type === "unknown") {
131
+ const word = statusWord(status, statusBasis);
132
+ if (word !== null)
133
+ object.push(part(` · ${word}`));
134
+ }
135
+ const diagnostic = tool.failure?.diagnostic ?? tool.failure?.summary ?? null;
136
+ const rawFailure = failureResult(tool, action);
137
+ const failure = action.type === "workflow" && action.run_id == null && rawState === "failed"
138
+ ? rawFailure === null
139
+ ? "did not start"
140
+ : `did not start · ${rawFailure}`
141
+ : rawFailure;
142
+ const timing = tool.timing;
143
+ const startedAt = timing?.started_at ?? null;
144
+ const endedAt = timing?.completed_at ?? null;
145
+ const durationMs = timing?.duration_ms ??
146
+ (startedAt !== null && endedAt !== null && endedAt > startedAt ? endedAt - startedAt : null);
147
+ let result;
148
+ let resultTone;
149
+ if (state === "running") {
150
+ // The component appends the elapsed: `running · 12s`.
151
+ result = "running";
152
+ resultTone = "running";
153
+ }
154
+ else if (failure !== null) {
155
+ result = failure;
156
+ resultTone = state === "failed" ? "failed" : state === "muted" ? "muted" : "plain";
157
+ }
158
+ else {
159
+ result = projection.result ?? statusWord(status, statusBasis);
160
+ resultTone =
161
+ state === "failed"
162
+ ? "failed"
163
+ : state === "muted" || projection.resultMuted
164
+ ? "muted"
165
+ : "plain";
166
+ }
167
+ if (result === null && durationMs !== null && durationMs >= 1000) {
168
+ result = spanText(durationMs);
169
+ resultTone = "plain";
170
+ }
171
+ const detail = projection.detail.kind === "none" && diagnostic !== null
172
+ ? { kind: "diagnostic", diagnostic }
173
+ : projection.detail;
174
+ return {
175
+ key: row.timeline_id,
176
+ rows: [row],
177
+ family: action.type,
178
+ cls: FAMILY_CLASS[action.type],
179
+ glyph: projection.glyph,
180
+ verb: projection.verb,
181
+ object,
182
+ result,
183
+ resultTone,
184
+ state,
185
+ at: endedAt ?? row.at,
186
+ startedAt: startedAt ?? row.at,
187
+ endedAt,
188
+ durationMs,
189
+ detail,
190
+ openByDefault: projection.openByDefault ||
191
+ (state === "failed" && diagnostic !== null && diagnostic.includes("\n")),
192
+ folded: false,
193
+ foldCount: 1,
194
+ elided: false,
195
+ childSessionIds: childSessionIdsOf(action),
196
+ diagnostic,
197
+ };
198
+ }
199
+ /* ── the fold ────────────────────────────────────────────────────────────── */
200
+ const SCRIPT_EXTENSIONS = /\.(mjs|cjs|js|ts|tsx|sh|bash|zsh|py|rb|pl|lua)$/i;
201
+ /** `.`, `..`, `*` and their kin name nothing; a fold is better off silent. */
202
+ const EMPTY_NAMES = new Set(["", ".", "..", "*", "~", "-"]);
203
+ function tokenLabel(token) {
204
+ const bare = token.replace(/^["']|["']$/g, "");
205
+ const name = bare.split("/").filter(Boolean).at(-1) ?? bare;
206
+ const trimmed = name.replace(SCRIPT_EXTENSIONS, "");
207
+ return trimmed.length > 24 ? `${trimmed.slice(0, 23)}…` : trimmed;
208
+ }
209
+ /**
210
+ * A command's name for a fold's list: the program, plus the first argument
211
+ * that is not a flag or a flag's value, each reduced to its own last segment.
212
+ * `pnpm -F field-app test` → `pnpm test`; `cargo clippy --all-targets --
213
+ * -D warnings` → `cargo clippy`; `node scripts/probe-silhouette.mjs --bays 1`
214
+ * → `node probe-silhouette`; `ls` → `ls`. Those are the record's own four
215
+ * drawings, and they are what this reproduces.
216
+ *
217
+ * Flag ARITY is unknowable from the text, so a single-dash flag is assumed to
218
+ * take a value (which is what `-F field-app` needs). When that assumption lands
219
+ * on a token that names nothing — `grep -r x .` reaches `.` — the program
220
+ * stands alone rather than the fold reading `grep .`.
221
+ */
222
+ export function commandName(command) {
223
+ const tokens = firstLine(command, 400).split(/\s+/).filter(Boolean);
224
+ if (tokens.length === 0)
225
+ return "";
226
+ const program = tokenLabel(tokens[0]);
227
+ let argument = null;
228
+ let index = 1;
229
+ while (index < tokens.length) {
230
+ const token = tokens[index];
231
+ if (token === "--" || token.startsWith("--")) {
232
+ index += 1;
233
+ continue;
234
+ }
235
+ if (token.startsWith("-") && token.length > 1) {
236
+ index += 2;
237
+ continue;
238
+ }
239
+ const label = tokenLabel(token);
240
+ if (EMPTY_NAMES.has(label)) {
241
+ index += 1;
242
+ continue;
243
+ }
244
+ argument = label;
245
+ break;
246
+ }
247
+ return argument === null ? program : `${program} ${argument}`;
248
+ }
249
+ /**
250
+ * What one folded member is called in the fold's name list: a file by its own
251
+ * name, a search by its query, a page by its host, a command by `commandName`.
252
+ * Only LOOK families ever fold, so every other family answers null.
253
+ */
254
+ function memberName(action) {
255
+ switch (action.type) {
256
+ case "shell":
257
+ return commandName(canonicalText(action.command));
258
+ case "file_read": {
259
+ const target = action.targets[0];
260
+ return target === undefined ? null : basename(resourceLabel(target.resource));
261
+ }
262
+ case "file_list":
263
+ return basename(resourceLabel(action.directory));
264
+ case "file_search":
265
+ case "code_lookup":
266
+ case "tool_discovery":
267
+ return action.query;
268
+ case "web_search":
269
+ return action.query;
270
+ case "web_fetch":
271
+ return urlHost(resourceLabel(action.url));
272
+ case "web_navigate":
273
+ return action.url === null ? action.pattern : urlHost(resourceLabel(action.url));
274
+ default:
275
+ return null;
276
+ }
277
+ }
278
+ function actionOf(row) {
279
+ return row.body.type === "tool_use" ? row.body.tool.action : null;
280
+ }
281
+ /** The fold's aggregate outcome — one drawing exists (`3 files · 1 truncated`)
282
+ * and the rest follow it: a fold states the same figure its members do, summed. */
283
+ function foldResult(family, rows) {
284
+ const actions = rows.map(actionOf).filter((action) => action !== null);
285
+ switch (family) {
286
+ case "file_read": {
287
+ const truncated = actions.filter((action) => action.type === "file_read" && action.outcome?.truncated === true).length;
288
+ return truncated === 0 ? null : `${truncated} truncated`;
289
+ }
290
+ case "file_list": {
291
+ const entries = sum(actions.map((action) => (action.type === "file_list" ? action.outcome?.entry_count : null)));
292
+ return entries === null ? null : `${entries} ${entries === 1 ? "entry" : "entries"}`;
293
+ }
294
+ case "file_search": {
295
+ const matches = sum(actions.map((action) => action.type === "file_search" ? action.outcome?.match_count : null));
296
+ const files = sum(actions.map((action) => (action.type === "file_search" ? action.outcome?.file_count : null)));
297
+ if (matches === null)
298
+ return null;
299
+ if (matches === 0)
300
+ return "found nothing";
301
+ const pieces = [`${matches} ${matches === 1 ? "match" : "matches"}`];
302
+ if (files !== null && files > 0)
303
+ pieces.push(`${files} ${files === 1 ? "file" : "files"}`);
304
+ return pieces.join(" · ");
305
+ }
306
+ case "code_lookup": {
307
+ const total = sum(actions.map((action) => action.type === "code_lookup" ? action.outcome?.total_count : null));
308
+ return total === null ? null : `${total} ${total === 1 ? "location" : "locations"}`;
309
+ }
310
+ case "web_search": {
311
+ const counts = actions.map((action) => action.type === "web_search" ? action.outcome?.total_count : null);
312
+ const total = counts.some((count) => count == null) ? null : sum(counts);
313
+ return total === null ? null : `${total} ${total === 1 ? "source" : "sources"}`;
314
+ }
315
+ default:
316
+ return null;
317
+ }
318
+ }
319
+ function sum(values) {
320
+ const known = values.filter((value) => typeof value === "number");
321
+ return known.length === 0 ? null : known.reduce((total, value) => total + value, 0);
322
+ }
323
+ /** A fold's detail is its members' details, concatenated in order. */
324
+ function foldDetail(family, lines) {
325
+ if (family === "shell") {
326
+ const commands = lines.flatMap((line) => line.detail.kind === "command" ? [...line.detail.commands] : []);
327
+ return commands.length === 0 ? { kind: "none" } : { kind: "command", commands };
328
+ }
329
+ const paths = lines.flatMap((line) => line.detail.kind === "paths" ? [...line.detail.paths] : []);
330
+ if (paths.length > 0)
331
+ return { kind: "paths", paths, total: paths.length };
332
+ if (family === "web_search") {
333
+ const details = lines.flatMap((line) => line.detail.kind === "sources" ? [line.detail] : []);
334
+ return {
335
+ kind: "sources",
336
+ sources: details.flatMap((detail) => [...detail.sources]),
337
+ total: details.some((detail) => detail.total === null)
338
+ ? null
339
+ : sum(details.map((detail) => detail.total)),
340
+ };
341
+ }
342
+ const fetches = lines.flatMap((line) => line.detail.kind === "fetch" ? [line.detail.fetch] : []);
343
+ if (fetches.length > 0)
344
+ return { kind: "fetches", fetches };
345
+ const locations = lines.flatMap((line) => line.detail.kind === "locations" ? [...line.detail.locations] : []);
346
+ if (locations.length > 0)
347
+ return { kind: "locations", locations, total: locations.length };
348
+ return { kind: "none" };
349
+ }
350
+ function foldable(line) {
351
+ return line.cls === "look" && line.state === "done";
352
+ }
353
+ function fold(lines) {
354
+ const family = lines[0].family;
355
+ const rows = lines.flatMap((line) => [...line.rows]);
356
+ const names = [];
357
+ for (const row of rows) {
358
+ const action = actionOf(row);
359
+ const members = action?.type === "file_read"
360
+ ? action.targets.map((target) => basename(resourceLabel(target.resource)))
361
+ : [action === null ? null : memberName(action)];
362
+ for (const name of members) {
363
+ if (name !== null && name !== "" && !names.includes(name))
364
+ names.push(name);
365
+ }
366
+ }
367
+ // A read line is the file names in both its single and folded forms. The
368
+ // object column already ellipsizes visually, so removing names from the
369
+ // model would make the closed line less useful without saving any space.
370
+ const elided = family !== "file_read" && names.length > FOLD_NAME_LIMIT;
371
+ const [one, many] = FOLD_NOUN[family];
372
+ const noun = rows.length === 1 ? one : many;
373
+ const object = family === "file_read" && names.length > 0
374
+ ? [part(names.join(", "))]
375
+ : elided
376
+ ? [part(`… ${rows.length} more ${many}`)]
377
+ : [
378
+ part(`${rows.length} ${noun}`),
379
+ ...(names.length === 0 ? [] : [part(` · ${names.join(", ")}`, "aside")]),
380
+ ];
381
+ const stamps = rows.flatMap(rowStamps);
382
+ const first = stamps.length === 0 ? null : Math.min(...stamps);
383
+ const last = stamps.length === 0 ? null : Math.max(...stamps);
384
+ const durationMs = stampSpan(rows);
385
+ let result = foldResult(family, rows);
386
+ // The elided fold states its span as `→ <end>` in the time slot instead.
387
+ if (result === null && !elided && durationMs !== null && durationMs >= 1000) {
388
+ result = spanText(durationMs);
389
+ }
390
+ return {
391
+ key: lines[0].key,
392
+ rows,
393
+ family,
394
+ cls: lines[0].cls,
395
+ glyph: lines[0].glyph,
396
+ verb: lines[0].verb,
397
+ object,
398
+ result,
399
+ resultTone: "plain",
400
+ state: "done",
401
+ at: elided ? last : first,
402
+ startedAt: first,
403
+ endedAt: last,
404
+ durationMs,
405
+ detail: foldDetail(family, lines),
406
+ openByDefault: false,
407
+ folded: true,
408
+ foldCount: rows.length,
409
+ elided,
410
+ childSessionIds: [],
411
+ diagnostic: null,
412
+ };
413
+ }
414
+ /**
415
+ * A contiguous run of `tool_use` rows as the lines the ledger draws. Folding
416
+ * happens here and only here — see the rules at the top of this module.
417
+ */
418
+ export function ledgerLines(rows, context = {}) {
419
+ const singles = rows.map((row) => ledgerLine(row, context));
420
+ const out = [];
421
+ let run = [];
422
+ const flush = () => {
423
+ if (run.length === 0)
424
+ return;
425
+ out.push(run.length === 1 ? run[0] : fold(run));
426
+ run = [];
427
+ };
428
+ for (const line of singles) {
429
+ if (!foldable(line)) {
430
+ flush();
431
+ out.push(line);
432
+ continue;
433
+ }
434
+ if (run.length > 0 && run[0].family !== line.family)
435
+ flush();
436
+ run.push(line);
437
+ }
438
+ flush();
439
+ return out;
440
+ }
441
+ /** The changed files by name. Distinct paths stay distinct: a name shared by
442
+ * two of them carries its parent directory. */
443
+ function fileNames(paths) {
444
+ return paths.map((path, index) => {
445
+ const name = basename(path);
446
+ const twin = paths.some((other, at) => at !== index && basename(other) === name);
447
+ if (!twin)
448
+ return name;
449
+ const parts = path.split("/").filter(Boolean);
450
+ return parts.length >= 2 ? `${parts[parts.length - 2]}/${name}` : name;
451
+ });
452
+ }
453
+ export function runSummary(lines, others = []) {
454
+ const rows = lines.flatMap((line) => [...line.rows]);
455
+ const order = [];
456
+ const counts = new Map();
457
+ const paths = [];
458
+ for (const row of rows) {
459
+ const action = actionOf(row);
460
+ if (action === null)
461
+ continue;
462
+ if (!counts.has(action.type))
463
+ order.push(action.type);
464
+ counts.set(action.type, (counts.get(action.type) ?? 0) + 1);
465
+ if (action.type === "file_change") {
466
+ for (const change of action.changes) {
467
+ const path = resourceLabel(change.path);
468
+ if (path !== "" && !paths.includes(path))
469
+ paths.push(path);
470
+ }
471
+ }
472
+ }
473
+ const names = fileNames(paths);
474
+ // Acts lead: the work product is what a reader wants first, and what
475
+ // survives when a narrow column ellipsizes the tail. Within a class the
476
+ // larger count comes first; ties keep first occurrence.
477
+ const byClass = (cls) => order
478
+ .filter((family) => FAMILY_CLASS[family] === cls)
479
+ .sort((a, b) => (counts.get(b) ?? 0) - (counts.get(a) ?? 0) || order.indexOf(a) - order.indexOf(b));
480
+ const nouns = [...byClass("act"), ...byClass("look")].map((family) => ({
481
+ family,
482
+ text: familyNoun(family, counts.get(family) ?? 0),
483
+ names: family === "file_change" ? names.slice(0, FOLD_NAME_LIMIT) : [],
484
+ more: family === "file_change" ? Math.max(0, names.length - FOLD_NAME_LIMIT) : 0,
485
+ }));
486
+ const thoughtCount = others.filter((other) => other.kind === "thinking").length;
487
+ if (nouns.length === 0 && thoughtCount > 0) {
488
+ nouns.push({
489
+ family: "thinking",
490
+ text: `${thoughtCount} ${thoughtCount === 1 ? "thought" : "thoughts"}`,
491
+ names: [],
492
+ more: 0,
493
+ });
494
+ }
495
+ const allRows = [...rows, ...others.map((other) => other.row)];
496
+ const memberCount = lines.length + others.length;
497
+ return {
498
+ nouns,
499
+ failed: lines.filter((line) => line.state === "failed").length,
500
+ errors: others.filter((other) => other.kind === "marker" && other.failed).length,
501
+ spanMs: stampSpan(allRows),
502
+ lineCount: lines.length,
503
+ rowCount: allRows.length,
504
+ memberCount,
505
+ thoughtCount,
506
+ running: [...lines].reverse().find((line) => line.state === "running") ?? null,
507
+ // Notices and summaries alone have no sentence to close to (R-2).
508
+ // Questions addressed to the reader are speech and stay visible (R-1).
509
+ closedByDefault: memberCount >= RUN_FOLD_THRESHOLD &&
510
+ (lines.length > 0 || thoughtCount > 0) &&
511
+ !lines.some((line) => line.family === "question"),
512
+ };
513
+ }
@@ -0,0 +1,23 @@
1
+ import type { ToolAction, ToolInteraction } from "@vibefield/rosetta-protocol";
2
+ type Family<K extends ToolAction["type"]> = Extract<ToolAction, {
3
+ type: K;
4
+ }>;
5
+ export type NativeToolRef = ToolInteraction["native"];
6
+ export type ToolFailure = NonNullable<ToolInteraction["failure"]>;
7
+ export type ToolTiming = NonNullable<ToolInteraction["timing"]>;
8
+ export type FileDelta = Family<"file_change">["changes"][number];
9
+ export type FindingItem = Family<"finding">["findings"][number];
10
+ export type DisplayField = Family<"external">["fields"][number];
11
+ export type DisplayValue = DisplayField["value"];
12
+ export type DisplayScalar = Extract<DisplayValue, {
13
+ type: "list";
14
+ }>["value"][number];
15
+ export type UserQuestion = Family<"question">["questions"][number];
16
+ export type UserAnswer = Family<"question">["answers"][number];
17
+ export type CollaboratorRef = NonNullable<Family<"collaborate">["outcome"]>["participants"][number];
18
+ export type SourceLocation = NonNullable<Family<"code_lookup">["outcome"]>["locations"][number];
19
+ export type SourceRange = NonNullable<Family<"file_read">["targets"][number]["range"]>;
20
+ export type CanonicalDocument = Family<"structured_output">["document"];
21
+ export type WebSource = NonNullable<Family<"web_search">["outcome"]>["sources"][number];
22
+ export type FindingSeverity = FindingItem["severity"];
23
+ export {};
@@ -0,0 +1 @@
1
+ export {};