@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,6 @@
1
+ import type { AssetRef } from "@vibefield/rosetta-protocol";
2
+ /** File-format hints for image targets without a filename extension or MIME type.
3
+ * This only selects the existing viewer; the browser still validates/decodes it. */
4
+ export declare function imageMediaTypeFromBytes(bytes: Uint8Array): string | null;
5
+ /** Transcript images must be committed WebP bundles produced by ingestion. */
6
+ export declare function isOptimizedImageAsset(asset: AssetRef): boolean;
@@ -0,0 +1,30 @@
1
+ /** File-format hints for image targets without a filename extension or MIME type.
2
+ * This only selects the existing viewer; the browser still validates/decodes it. */
3
+ export function imageMediaTypeFromBytes(bytes) {
4
+ const starts = (...prefix) => prefix.every((value, index) => bytes[index] === value);
5
+ const text = (start, length) => String.fromCharCode(...bytes.subarray(start, start + length));
6
+ if (starts(137, 80, 78, 71, 13, 10, 26, 10))
7
+ return "image/png";
8
+ if (starts(255, 216, 255))
9
+ return "image/jpeg";
10
+ if (["GIF87a", "GIF89a"].includes(text(0, 6)))
11
+ return "image/gif";
12
+ if (text(0, 4) === "RIFF" && text(8, 4) === "WEBP")
13
+ return "image/webp";
14
+ if (text(0, 2) === "BM")
15
+ return "image/bmp";
16
+ if (starts(0, 0, 1, 0))
17
+ return "image/x-icon";
18
+ if (text(4, 4) === "ftyp" && ["avif", "avis"].includes(text(8, 4)))
19
+ return "image/avif";
20
+ if (/^\s*(?:<\?xml[^>]*>\s*)?<svg[\s>]/i.test(new TextDecoder().decode(bytes.subarray(0, 512))))
21
+ return "image/svg+xml";
22
+ return null;
23
+ }
24
+ /** Transcript images must be committed WebP bundles produced by ingestion. */
25
+ export function isOptimizedImageAsset(asset) {
26
+ const member = (value) => value?.media_type === "image/webp"
27
+ && value.byte_len > 0 && /^[a-f0-9]{64}$/.test(value.digest)
28
+ && value.url === `/api/assets/${value.digest}.webp`;
29
+ return member(asset) && ["rail", "tile", "tile2x", "preview"].every(variant => member(asset.image_variants?.[variant]));
30
+ }
@@ -0,0 +1,50 @@
1
+ import type { IngestProgress, RuntimeBackfill, SearchBuildProgress, SearchReadiness } from "@vibefield/rosetta-protocol";
2
+ export interface ActivityFeed {
3
+ readonly ingest: IngestProgress | null;
4
+ readonly canonicalReady: boolean | null;
5
+ readonly searchReadiness: SearchReadiness | null;
6
+ readonly searchProgress: SearchBuildProgress | null;
7
+ readonly connectionError: string | null;
8
+ readonly startedAt: number | null;
9
+ readonly uptimeMs: number;
10
+ readonly receivedAt: number | null;
11
+ }
12
+ export interface ActivityPhase {
13
+ readonly key: string;
14
+ readonly title: string;
15
+ readonly detail: string;
16
+ readonly amount: string;
17
+ readonly step: number;
18
+ readonly current: number;
19
+ readonly total: number;
20
+ readonly unit: "bytes" | "files" | "documents" | "records" | null;
21
+ readonly fraction: number | null;
22
+ readonly active: boolean;
23
+ }
24
+ export declare const fraction: (done: number, total: number) => number | null;
25
+ export declare function progressBytes(value: number): string;
26
+ export declare function progressDuration(ms: number): string;
27
+ /** Percentages describe the named step, never an invented overall ETA. */
28
+ export declare function activityPhase(feed: ActivityFeed): ActivityPhase | null;
29
+ export declare function runtimeActivity(row: RuntimeBackfill, restoring?: boolean): {
30
+ label: string;
31
+ fraction: number | null;
32
+ };
33
+ export interface ActivitySamples {
34
+ readonly identity: string;
35
+ readonly points: readonly {
36
+ at: number;
37
+ value: number;
38
+ }[];
39
+ readonly changedAt: number;
40
+ readonly rate: number | null;
41
+ }
42
+ /** Eight seconds of actual observations smooth variable batch sizes. A restart,
43
+ * phase transition, retry, or regressing counter starts a new sample window. */
44
+ export declare function sampleActivity(previous: ActivitySamples | null, feed: ActivityFeed, phase: ActivityPhase): ActivitySamples;
45
+ export interface IngestActivity {
46
+ readonly phase: ActivityPhase;
47
+ readonly feed: ActivityFeed;
48
+ readonly footer: string;
49
+ readonly elapsed: string;
50
+ }
@@ -0,0 +1,151 @@
1
+ const number = (value) => value.toLocaleString();
2
+ export const fraction = (done, total) => total > 0
3
+ ? Math.max(0, Math.min(1, done / total)) : null;
4
+ export function progressBytes(value) {
5
+ if (value < 1_000)
6
+ return `${Math.max(0, Math.round(value))} B`;
7
+ if (value < 1_000_000)
8
+ return `${(value / 1_000).toFixed(0)} KB`;
9
+ if (value < 1_000_000_000)
10
+ return `${(value / 1_000_000).toFixed(1)} MB`;
11
+ return `${(value / 1_000_000_000).toFixed(2)} GB`;
12
+ }
13
+ export function progressDuration(ms) {
14
+ const seconds = Math.floor(Math.max(0, ms) / 1_000);
15
+ if (seconds < 60)
16
+ return `${seconds}s`;
17
+ if (seconds < 3_600)
18
+ return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
19
+ return `${Math.floor(seconds / 3_600)}h ${Math.floor((seconds % 3_600) / 60)}m`;
20
+ }
21
+ /** Percentages describe the named step, never an invented overall ETA. */
22
+ export function activityPhase(feed) {
23
+ const ingest = feed.ingest;
24
+ if (ingest?.phase === "awaiting_consent" || feed.receivedAt === null)
25
+ return null;
26
+ const runtimes = ingest?.runtimes ?? [];
27
+ const sessions = runtimes.reduce((sum, row) => sum + row.sessions_total, 0);
28
+ const base = {
29
+ key: "discovering", title: "Finding your history", step: 1,
30
+ detail: "Checking the agents on this Mac. Your history stays on this device.",
31
+ amount: "Looking for conversations…", current: 0, total: 0,
32
+ unit: null, fraction: null, active: true,
33
+ };
34
+ if (ingest?.phase === "discovering")
35
+ return base;
36
+ if (ingest?.phase === "restoring") {
37
+ const current = runtimes.filter((row) => row.state === "streaming")
38
+ .reduce((sum, row) => sum + row.records, 0);
39
+ return { ...base, key: "restoring", title: "Restoring saved progress",
40
+ detail: "Recovering saved conversations so your import can continue.",
41
+ amount: `${number(current)} items restored`, current, unit: "records" };
42
+ }
43
+ if (ingest?.phase === "metadata_ready")
44
+ return {
45
+ ...base, key: "paused", title: "History scan complete", active: false,
46
+ detail: "Transcript import is paused after scanning your history.",
47
+ amount: `${number(sessions)} sessions found`,
48
+ };
49
+ if (ingest?.phase === "finalizing" || ingest?.phase === "publishing")
50
+ return {
51
+ ...base, key: ingest.phase, step: 3,
52
+ title: ingest.phase === "publishing" ? "Saving your archive" : "Finishing your archive",
53
+ detail: ingest.phase === "publishing"
54
+ ? "Saving your history to this device. Search is next."
55
+ : "Checking conversations and preparing your activity summaries.",
56
+ amount: `${number(sessions)} sessions imported`,
57
+ };
58
+ if (ingest && ingest.phase !== "live") {
59
+ const scanning = runtimes.length === 0 || runtimes.some((row) => row.state === "skimming") ||
60
+ runtimes.every((row) => row.state === "queued");
61
+ if (scanning) {
62
+ const current = runtimes.reduce((sum, row) => sum + row.files_skimmed, 0);
63
+ const total = runtimes.reduce((sum, row) => sum + row.files_total, 0);
64
+ return {
65
+ ...base, key: "metadata", title: "Discovering conversations",
66
+ detail: `${number(sessions)} sessions found. Projects appear as each agent is scanned.`,
67
+ amount: `${number(current)} files checked`, current, total, unit: "files",
68
+ fraction: fraction(current, total),
69
+ };
70
+ }
71
+ if (runtimes.some((row) => row.state === "streaming")) {
72
+ const current = runtimes.reduce((sum, row) => sum + row.bytes_streamed, 0);
73
+ const total = runtimes.some((row) => row.bytes_total === 0 && row.sessions_total > 0) ? 0
74
+ : runtimes.reduce((sum, row) => sum + row.bytes_total, 0);
75
+ return {
76
+ ...base, key: "reading", title: "Reading conversations", step: 2,
77
+ detail: "You can browse conversations as each agent becomes ready.",
78
+ amount: `${progressBytes(current)} processed`, current, total, unit: "bytes",
79
+ fraction: fraction(current, total),
80
+ };
81
+ }
82
+ return {
83
+ ...base, key: "organizing", title: "Organizing conversations", step: 3,
84
+ detail: "Putting messages and tool activity in order before they become available.",
85
+ amount: `${number(sessions)} sessions found`,
86
+ };
87
+ }
88
+ if (feed.searchReadiness === "failed")
89
+ return {
90
+ ...base, key: "search_failed", title: "Search needs attention", step: 4, active: false,
91
+ detail: "Your conversations are available. Search will retry automatically.",
92
+ amount: "Ready to browse",
93
+ };
94
+ if (feed.canonicalReady && feed.searchReadiness === "ready")
95
+ return {
96
+ ...base, key: "ready", title: "Your archive is ready", step: 4, active: false,
97
+ detail: "Browse and search all your conversations.",
98
+ amount: `${number(sessions)} sessions imported`, fraction: 1,
99
+ };
100
+ // Routine live repair must not reopen the first-run import panel.
101
+ if (feed.canonicalReady && !feed.searchProgress &&
102
+ (feed.searchReadiness === "catching-up" || feed.searchReadiness === "stale"))
103
+ return null;
104
+ if (feed.canonicalReady) {
105
+ const progress = feed.searchProgress;
106
+ const indexing = !progress || progress.stage === "indexing";
107
+ return {
108
+ ...base, key: `search_${progress?.stage ?? "waiting"}`, step: 4,
109
+ title: indexing ? "Preparing search" : "Finishing search",
110
+ detail: indexing ? "Your conversations are ready to browse. Search will be available shortly."
111
+ : progress.stage === "publishing" ? "Saving the search index. Your conversations are ready to browse."
112
+ : "Checking the search index. Your conversations are ready to browse.",
113
+ amount: progress ? `${number(progress.documents_done)} of ${number(progress.documents_total)} messages`
114
+ : "Ready to browse",
115
+ current: progress?.documents_done ?? 0, total: progress?.documents_total ?? 0,
116
+ unit: indexing ? "documents" : null,
117
+ fraction: indexing && progress ? fraction(progress.documents_done, progress.documents_total) : null,
118
+ };
119
+ }
120
+ return base;
121
+ }
122
+ export function runtimeActivity(row, restoring = false) {
123
+ if (restoring && row.state === "streaming")
124
+ return { label: `${number(row.records)} items restored`, fraction: null };
125
+ switch (row.state) {
126
+ case "queued": return { label: row.sessions_total ? "Waiting to read" : "Waiting to scan", fraction: null };
127
+ case "skimming": return { label: `${number(row.sessions_total)} sessions found`, fraction: fraction(row.files_skimmed, row.files_total) };
128
+ case "streaming": return { label: `${progressBytes(row.bytes_streamed)} processed`, fraction: fraction(row.bytes_streamed, row.bytes_total) };
129
+ case "preparing": return { label: "Organizing conversations", fraction: null };
130
+ case "applying": return { label: "Making conversations available", fraction: null };
131
+ case "done": return { label: "Ready to browse", fraction: 1 };
132
+ }
133
+ }
134
+ /** Eight seconds of actual observations smooth variable batch sizes. A restart,
135
+ * phase transition, retry, or regressing counter starts a new sample window. */
136
+ export function sampleActivity(previous, feed, phase) {
137
+ const at = feed.receivedAt ?? 0;
138
+ const identity = `${feed.startedAt}:${phase.key}:${phase.unit}`;
139
+ const last = previous?.points.at(-1);
140
+ if (!previous || previous.identity !== identity || !last || phase.current < last.value || at < last.at) {
141
+ return { identity, points: [{ at, value: phase.current }], changedAt: at, rate: null };
142
+ }
143
+ if (at === last.at || feed.connectionError)
144
+ return previous;
145
+ const points = [...previous.points.filter((point) => at - point.at <= 8_000), { at, value: phase.current }];
146
+ const first = points[0];
147
+ const changedAt = phase.current !== last.value ? at : previous.changedAt;
148
+ const rate = at - first.at >= 1_000 && at - changedAt < 4_000
149
+ ? (phase.current - first.value) * 1_000 / (at - first.at) : null;
150
+ return { identity, points, changedAt, rate: rate !== null && rate > 0 ? rate : null };
151
+ }
@@ -0,0 +1,25 @@
1
+ import type { IngestProgress, ProjectBackfill, SessionRow } from "@vibefield/rosetta-protocol";
2
+ /** The backfill is still running: veils may be down, cards may cook. */
3
+ export declare function isIngestActive(ingest: IngestProgress | null): boolean;
4
+ /** The census (skim) has not yet named every session: the LISTS themselves
5
+ * are still incomplete, so the list sections stay veiled. */
6
+ export declare function isCensusRunning(ingest: IngestProgress | null): boolean;
7
+ /** Census meter: files skimmed over the discovery walk's total. */
8
+ export declare function censusProgress(ingest: IngestProgress | null): number | null;
9
+ /** Stream meter: transcript bytes read over the census's byte total. */
10
+ export declare function backfillProgress(ingest: IngestProgress | null): number | null;
11
+ /** A session whose figures are still cooking. During the backfill this is
12
+ * the cooking card; during live it marks a transcript still being read. */
13
+ export declare function isSessionCooking(session: SessionRow): boolean;
14
+ /** The daemon's per-project backfill fold, keyed the way the room keys
15
+ * projects — the canonical id, with the daemon's unassigned bucket under
16
+ * UNASSIGNED_PROJECT_ID. Empty until the skims settle the plan, and empty
17
+ * on a daemon too old to carry the fold, so every consumer degrades to the
18
+ * meta-derived cooking state it had before. */
19
+ export declare function projectBackfills(ingest: IngestProgress | null): ReadonlyMap<string, ProjectBackfill>;
20
+ /** One project's byte meter, 0..1. A source that grew mid-backfill can
21
+ * overshoot its census total, so the meter clamps; null when the census
22
+ * counted nothing to read. */
23
+ export declare function projectBackfillProgress(row: ProjectBackfill): number | null;
24
+ /** "2,314 of 5,912 sessions" — the veil labels' one counting form. */
25
+ export declare function sessionCountLabel(indexed: number, total: number): string;
@@ -0,0 +1,70 @@
1
+ import { UNASSIGNED_PROJECT_ID } from "./model.js";
2
+ /** The backfill is still running: veils may be down, cards may cook. */
3
+ export function isIngestActive(ingest) {
4
+ return ingest !== null && ingest.phase !== "live";
5
+ }
6
+ /** The census (skim) has not yet named every session: the LISTS themselves
7
+ * are still incomplete, so the list sections stay veiled. */
8
+ export function isCensusRunning(ingest) {
9
+ if (!isIngestActive(ingest))
10
+ return false;
11
+ if (ingest === null)
12
+ return true;
13
+ // The explicit audit seam proves every bounded skim has committed. Runtime
14
+ // rows remain queued because complete-record streaming has not started.
15
+ if (ingest.phase === "metadata_ready")
16
+ return false;
17
+ if (ingest.runtimes.length === 0)
18
+ return true;
19
+ return ingest.runtimes.some((runtime) => runtime.state === "queued" || runtime.state === "skimming");
20
+ }
21
+ /** Census meter: files skimmed over the discovery walk's total. */
22
+ export function censusProgress(ingest) {
23
+ if (ingest === null)
24
+ return null;
25
+ const totals = ingest.runtimes.reduce((sum, runtime) => ({
26
+ done: sum.done + runtime.files_skimmed,
27
+ all: sum.all + runtime.files_total,
28
+ }), { done: 0, all: 0 });
29
+ return totals.all > 0 ? totals.done / totals.all : null;
30
+ }
31
+ /** Stream meter: transcript bytes read over the census's byte total. */
32
+ export function backfillProgress(ingest) {
33
+ if (ingest === null)
34
+ return null;
35
+ const totals = ingest.runtimes.reduce((sum, runtime) => ({
36
+ done: sum.done +
37
+ (runtime.state === "done" ? runtime.bytes_total : runtime.bytes_streamed),
38
+ all: sum.all + runtime.bytes_total,
39
+ }), { done: 0, all: 0 });
40
+ return totals.all > 0 ? Math.min(1, totals.done / totals.all) : null;
41
+ }
42
+ /** A session whose figures are still cooking. During the backfill this is
43
+ * the cooking card; during live it marks a transcript still being read. */
44
+ export function isSessionCooking(session) {
45
+ return session.stream_state !== "indexed";
46
+ }
47
+ /** The daemon's per-project backfill fold, keyed the way the room keys
48
+ * projects — the canonical id, with the daemon's unassigned bucket under
49
+ * UNASSIGNED_PROJECT_ID. Empty until the skims settle the plan, and empty
50
+ * on a daemon too old to carry the fold, so every consumer degrades to the
51
+ * meta-derived cooking state it had before. */
52
+ export function projectBackfills(ingest) {
53
+ const index = new Map();
54
+ for (const row of ingest?.projects ?? []) {
55
+ index.set(row.project_id ?? UNASSIGNED_PROJECT_ID, row);
56
+ }
57
+ return index;
58
+ }
59
+ /** One project's byte meter, 0..1. A source that grew mid-backfill can
60
+ * overshoot its census total, so the meter clamps; null when the census
61
+ * counted nothing to read. */
62
+ export function projectBackfillProgress(row) {
63
+ if (row.bytes_total === 0)
64
+ return null;
65
+ return Math.min(1, row.bytes_streamed / row.bytes_total);
66
+ }
67
+ /** "2,314 of 5,912 sessions" — the veil labels' one counting form. */
68
+ export function sessionCountLabel(indexed, total) {
69
+ return `${indexed.toLocaleString()} of ${total.toLocaleString()} sessions`;
70
+ }
@@ -0,0 +1,5 @@
1
+ export declare function modelColor(modelId: string): string;
2
+ export declare function formatModelLabel(modelId: string): string;
3
+ /** Resolve palette collisions once for a project's model set, so selecting
4
+ * another day keeps a model's color and adjacent legend entries stay distinct. */
5
+ export declare function createModelColors(ids: readonly string[]): Readonly<Record<string, string>>;
@@ -0,0 +1,28 @@
1
+ export function modelColor(modelId) {
2
+ let hash = 2166136261;
3
+ for (let index = 0; index < modelId.length; index += 1) {
4
+ hash ^= modelId.charCodeAt(index);
5
+ hash = Math.imul(hash, 16777619);
6
+ }
7
+ return `var(--vf-accent-${((hash >>> 0) % 8) + 1})`;
8
+ }
9
+ export function formatModelLabel(modelId) {
10
+ return modelId.startsWith("claude-") ? modelId.slice("claude-".length) : modelId;
11
+ }
12
+ /** Resolve palette collisions once for a project's model set, so selecting
13
+ * another day keeps a model's color and adjacent legend entries stay distinct. */
14
+ export function createModelColors(ids) {
15
+ const colors = Object.create(null);
16
+ const used = new Set();
17
+ for (const id of [...new Set(ids)].sort()) {
18
+ const preferred = modelColor(id);
19
+ let color = preferred;
20
+ for (let index = 1; used.has(color) && index <= 8; index++)
21
+ color = `var(--vf-accent-${index})`;
22
+ if (used.has(color))
23
+ color = `color-mix(in srgb, ${preferred} 65%, var(--vf-text-primary))`;
24
+ colors[id] = color;
25
+ used.add(color);
26
+ }
27
+ return colors;
28
+ }
@@ -0,0 +1,73 @@
1
+ import type { ContributionRow, HeatmapDay, ProjectRow, SessionRow } from "@vibefield/rosetta-protocol";
2
+ import type { AgentShare } from "./agents.js";
3
+ import type { Spend } from "./spend.js";
4
+ export interface ProjectStats {
5
+ /** Daily token totals over the heatmap's window (53 Sunday-aligned weeks
6
+ * ending today), from /heatmap?since_ms=…. */
7
+ heat: readonly HeatmapDay[];
8
+ /** Per-root-session contribution (tokens, messages, …), whole project life. */
9
+ contribution: readonly ContributionRow[];
10
+ }
11
+ export interface ProjectViewModel {
12
+ readonly row: ProjectRow;
13
+ readonly tint: string;
14
+ /** Tokens across the project's whole life (root contributions include
15
+ * their subagent trees). */
16
+ readonly lifetimeTokens: number;
17
+ /** List-price spend across the project's whole life — the project card's
18
+ * primary figure and the ledger's default ranking (§4.1.3). */
19
+ readonly lifetimeSpend: Spend;
20
+ /** List-price spend over the last 30 days, the same heatmap tail. */
21
+ readonly spendLast30Days: Spend;
22
+ /** List-price spend over the 53-week window. */
23
+ readonly spendLast53Weeks: Spend;
24
+ /** Tokens over the last 30 days — the ledger's stated window. */
25
+ readonly tokensLast30Days: number;
26
+ /** 15 two-day buckets, oldest first — the activity shape. */
27
+ readonly recentTokenBuckets: readonly number[];
28
+ /** 53×7 daily totals from the grid's Sunday; cells after today are -1.
29
+ * The heatmap is all of it and the 30-day figures are its tail, so the
30
+ * charts are views of one number and cannot disagree. */
31
+ readonly dailyTokens: readonly number[];
32
+ /** Index of today inside dailyTokens. */
33
+ readonly currentDayIndex: number;
34
+ /** Tokens over the whole 53-week window — the summary panel's stated window. */
35
+ readonly tokensLast53Weeks: number;
36
+ /** Message rows across the project's whole life (contribution sum). */
37
+ readonly lifetimeMessages: number;
38
+ readonly agents: readonly AgentShare[];
39
+ readonly lastActiveMs: number | null;
40
+ readonly rootSessionCount: number;
41
+ /** Every session of the project, subagents included — the readiness base. */
42
+ readonly sessionCount: number;
43
+ /** Sessions the stream phase has fully indexed. */
44
+ readonly indexedSessionCount: number;
45
+ /** Folded over session stream_state. Aggregate requests have their own
46
+ * statsReady gate and may finish after transcripts become browseable. */
47
+ readonly readiness: "pending" | "partial" | "ready";
48
+ /** Aggregate requests finish separately from transcript publication. */
49
+ readonly statsReady: boolean;
50
+ }
51
+ /** Client-only bucket for sessions whose adapters have no native cwd fact.
52
+ * It is deliberately not persisted as a canonical project. */
53
+ export declare const UNASSIGNED_PROJECT_ID = "__rosetta_unassigned__";
54
+ export declare function projectKey(session: SessionRow): string;
55
+ export declare function unassignedProject(): ProjectRow;
56
+ export declare const ACTIVITY_HEATMAP_WEEK_COUNT = 53;
57
+ export declare const ACTIVITY_HEATMAP_DAY_COUNT: number;
58
+ /** Midnight of the Sunday opening the grid's first column. */
59
+ export declare function getActivityGridStartTimestamp(currentTimestamp: number): number;
60
+ /** The viewer's offset, minutes east of UTC — passed to /heatmap so the
61
+ * daemon buckets days the way this screen will label them. */
62
+ export declare function getViewerUtcOffsetMinutes(): number;
63
+ /** The viewer-offset day key for a timestamp — the exact form the heatmap
64
+ * endpoint was asked to bucket in. */
65
+ export declare function getCalendarDayKey(timestamp: number): string;
66
+ export declare function buildProjectViewModel(projectRow: ProjectRow, allSessions: readonly SessionRow[], projectStats: ProjectStats | undefined, getRuntimeKind: (runtimeId: string) => string, currentTimestamp: number,
67
+ /** The room's dealt colour for a project (`TintDealer.projectTint`). */
68
+ projectTint: (projectId: string) => string): ProjectViewModel;
69
+ export interface SnippetPart {
70
+ text: string;
71
+ mark: boolean;
72
+ }
73
+ export declare function parseSnippet(snippet: string): SnippetPart[];
@@ -0,0 +1,141 @@
1
+ import { NO_SPEND, addSpend, spendOf, sumSpend } from "./spend.js";
2
+ import { sessionLastActive } from "./session-activity.js";
3
+ const DAY_IN_MS = 86_400_000;
4
+ /** Client-only bucket for sessions whose adapters have no native cwd fact.
5
+ * It is deliberately not persisted as a canonical project. */
6
+ export const UNASSIGNED_PROJECT_ID = "__rosetta_unassigned__";
7
+ export function projectKey(session) {
8
+ return session.project_id ?? UNASSIGNED_PROJECT_ID;
9
+ }
10
+ export function unassignedProject() {
11
+ return {
12
+ id: UNASSIGNED_PROJECT_ID,
13
+ name: "Unassigned sessions",
14
+ root_paths: [],
15
+ git_repo: null,
16
+ };
17
+ }
18
+ /* ── heatmap grid: 53 columns of weeks, Sunday-aligned, ending today ────── */
19
+ export const ACTIVITY_HEATMAP_WEEK_COUNT = 53;
20
+ export const ACTIVITY_HEATMAP_DAY_COUNT = ACTIVITY_HEATMAP_WEEK_COUNT * 7;
21
+ function startOfDay(ms) {
22
+ const d = new Date(ms);
23
+ d.setHours(0, 0, 0, 0);
24
+ return d.getTime();
25
+ }
26
+ /** Midnight of the Sunday opening the grid's first column. */
27
+ export function getActivityGridStartTimestamp(currentTimestamp) {
28
+ const today = startOfDay(currentTimestamp);
29
+ return (today -
30
+ ((ACTIVITY_HEATMAP_WEEK_COUNT - 1) * 7 + new Date(today).getDay()) * DAY_IN_MS);
31
+ }
32
+ /** The viewer's offset, minutes east of UTC — passed to /heatmap so the
33
+ * daemon buckets days the way this screen will label them. */
34
+ export function getViewerUtcOffsetMinutes() {
35
+ return -new Date().getTimezoneOffset();
36
+ }
37
+ /** The viewer-offset day key for a timestamp — the exact form the heatmap
38
+ * endpoint was asked to bucket in. */
39
+ export function getCalendarDayKey(timestamp) {
40
+ const d = new Date(timestamp + getViewerUtcOffsetMinutes() * 60_000);
41
+ return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}-${String(d.getUTCDate()).padStart(2, "0")}`;
42
+ }
43
+ /** The full 53×7 grid, zero-filled from sparse heatmap days; cells after
44
+ * today hold -1 (not yet, which is not the same as empty). */
45
+ function createActivitySeries(heatmapDays, currentTimestamp) {
46
+ const tokensByDay = new Map(heatmapDays.map((day) => [day.day, day.tokens]));
47
+ const startTimestamp = getActivityGridStartTimestamp(currentTimestamp);
48
+ const currentDayKey = getCalendarDayKey(currentTimestamp);
49
+ const dailyTokens = [];
50
+ let currentDayIndex = ACTIVITY_HEATMAP_DAY_COUNT - 1;
51
+ for (let index = 0; index < ACTIVITY_HEATMAP_DAY_COUNT; index += 1) {
52
+ const key = getCalendarDayKey(startTimestamp + index * DAY_IN_MS + DAY_IN_MS / 2);
53
+ if (key === currentDayKey)
54
+ currentDayIndex = index;
55
+ dailyTokens.push(index > currentDayIndex ? -1 : (tokensByDay.get(key) ?? 0));
56
+ }
57
+ return { dailyTokens, currentDayIndex };
58
+ }
59
+ export function buildProjectViewModel(projectRow, allSessions, projectStats, getRuntimeKind, currentTimestamp,
60
+ /** The room's dealt colour for a project (`TintDealer.projectTint`). */
61
+ projectTint) {
62
+ const projectSessions = allSessions.filter((session) => projectKey(session) === projectRow.id);
63
+ const rootSessions = projectSessions.filter((session) => session.parent_session_id === null);
64
+ const indexedSessionCount = projectSessions.filter((session) => session.stream_state === "indexed").length;
65
+ const readiness = indexedSessionCount === projectSessions.length
66
+ ? "ready"
67
+ : indexedSessionCount === 0
68
+ ? "pending"
69
+ : "partial";
70
+ const { dailyTokens, currentDayIndex } = createActivitySeries(projectStats?.heat ?? [], currentTimestamp);
71
+ // The ledger's 30-day figures are the same series' tail, so the heatmap,
72
+ // the sparkline, and the figure can never disagree.
73
+ const dailyTokensLast30Days = Array.from({ length: 30 }, (_, dayIndex) => Math.max(0, dailyTokens[currentDayIndex - (29 - dayIndex)] ?? 0));
74
+ const recentTokenBuckets = Array.from({ length: 15 }, (_, bucketIndex) => [dailyTokensLast30Days[bucketIndex * 2], dailyTokensLast30Days[bucketIndex * 2 + 1]].reduce((total, value) => total + (value ?? 0), 0));
75
+ const tokensLast30Days = dailyTokensLast30Days.reduce((total, value) => total + value, 0);
76
+ const tokensLast53Weeks = dailyTokens.reduce((total, value) => total + Math.max(0, value), 0);
77
+ const lifetimeTokens = (projectStats?.contribution ?? []).reduce((total, contribution) => total + contribution.tokens, 0);
78
+ const lifetimeSpend = sumSpend(projectStats?.contribution ?? []);
79
+ // Spend windows come from the same heatmap days as the token windows.
80
+ const thirtyDayKeys = new Set(Array.from({ length: 30 }, (_, dayIndex) => getCalendarDayKey(currentTimestamp - (29 - dayIndex) * DAY_IN_MS)));
81
+ let spendLast30Days = NO_SPEND;
82
+ let spendLast53Weeks = NO_SPEND;
83
+ for (const day of projectStats?.heat ?? []) {
84
+ const spend = spendOf(day);
85
+ spendLast53Weeks = addSpend(spendLast53Weeks, spend);
86
+ if (thirtyDayKeys.has(day.day))
87
+ spendLast30Days = addSpend(spendLast30Days, spend);
88
+ }
89
+ const lifetimeMessages = (projectStats?.contribution ?? []).reduce((total, contribution) => total + contribution.messages, 0);
90
+ const sessionCountByRuntimeKind = new Map();
91
+ for (const session of rootSessions) {
92
+ const runtimeKind = getRuntimeKind(session.runtime_id);
93
+ sessionCountByRuntimeKind.set(runtimeKind, (sessionCountByRuntimeKind.get(runtimeKind) ?? 0) + 1);
94
+ }
95
+ const totalSessionCount = rootSessions.length || 1;
96
+ const agents = [...sessionCountByRuntimeKind.entries()]
97
+ .map(([kind, count]) => ({
98
+ kind,
99
+ pct: Math.round((count / totalSessionCount) * 100),
100
+ }))
101
+ .sort((left, right) => right.pct - left.pct);
102
+ const lastActiveMs = rootSessions.reduce((latest, session) => {
103
+ const at = sessionLastActive(session);
104
+ return at === null ? latest : latest === null ? at : Math.max(latest, at);
105
+ }, null);
106
+ return {
107
+ row: projectRow,
108
+ tint: projectTint(projectRow.id),
109
+ lifetimeTokens,
110
+ lifetimeSpend,
111
+ spendLast30Days,
112
+ spendLast53Weeks,
113
+ tokensLast30Days,
114
+ recentTokenBuckets,
115
+ dailyTokens,
116
+ currentDayIndex,
117
+ tokensLast53Weeks,
118
+ lifetimeMessages,
119
+ agents,
120
+ lastActiveMs,
121
+ rootSessionCount: rootSessions.length,
122
+ sessionCount: projectSessions.length,
123
+ indexedSessionCount,
124
+ readiness,
125
+ statsReady: projectStats !== undefined,
126
+ };
127
+ }
128
+ export function parseSnippet(snippet) {
129
+ const parts = [];
130
+ const re = /\[([^\]]*)\]/g;
131
+ let at = 0;
132
+ for (let m = re.exec(snippet); m !== null; m = re.exec(snippet)) {
133
+ if (m.index > at)
134
+ parts.push({ text: snippet.slice(at, m.index), mark: false });
135
+ parts.push({ text: m[1], mark: true });
136
+ at = m.index + m[0].length;
137
+ }
138
+ if (at < snippet.length)
139
+ parts.push({ text: snippet.slice(at), mark: false });
140
+ return parts;
141
+ }
@@ -0,0 +1,13 @@
1
+ /** Shared timing for small, interruptible movements in the reading surfaces. */
2
+ export declare const SETTLE_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
3
+ export declare const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
4
+ export declare function prefersReducedMotion(): boolean;
5
+ /** FLIP in scroll-content coordinates, so ordinary scrolling never looks like
6
+ * a reorder. Only rows crossing the viewport acquire animation layers. */
7
+ export declare class ListMotion {
8
+ private positions;
9
+ private animations;
10
+ private initialized;
11
+ update(container: HTMLElement, reduced: boolean): void;
12
+ cancel(): void;
13
+ }