@vibefield/rosetta-room 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,34 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ // A file nothing here can read as a document. The honest answer is not an
3
+ // error and not an empty frame: it is the file's first bytes, which is the
4
+ // only thing anyone can truthfully say about it.
5
+ import { useMemo } from "react";
6
+ /** How much of the file the dump shows. A hex view is for identifying a
7
+ * file — a magic number, a header, an encoding — not for reading it. */
8
+ const DUMP_BYTES = 4096;
9
+ const COLUMNS = 16;
10
+ const HEX = Array.from({ length: 256 }, (_, byte) => byte.toString(16).padStart(2, "0"));
11
+ function dump(bytes) {
12
+ const rows = [];
13
+ const end = Math.min(bytes.length, DUMP_BYTES);
14
+ for (let at = 0; at < end; at += COLUMNS) {
15
+ let hex = "";
16
+ let text = "";
17
+ for (let column = 0; column < COLUMNS; column += 1) {
18
+ const byte = at + column < end ? bytes[at + column] : null;
19
+ hex += byte === null ? " " : `${HEX[byte]} `;
20
+ // Printable ASCII only; everything else is a dot, the way every hex
21
+ // dump since 1970 has drawn it.
22
+ text += byte === null ? " " : byte >= 0x20 && byte < 0x7f ? String.fromCharCode(byte) : ".";
23
+ }
24
+ rows.push({ offset: at.toString(16).padStart(8, "0"), hex, text });
25
+ }
26
+ return rows;
27
+ }
28
+ export function BinaryView({ file }) {
29
+ const rows = useMemo(() => dump(file.bytes), [file]);
30
+ const shown = Math.min(file.bytes.length, DUMP_BYTES);
31
+ return (_jsxs("div", { className: "ah-fileview__scroll ah-hex", children: [_jsxs("p", { className: "ah-hex__note", children: ["Nothing here reads this format.", " ", shown < file.handle.size
32
+ ? `These are the first ${shown.toLocaleString()} bytes of ${file.handle.size.toLocaleString()}.`
33
+ : `All ${shown.toLocaleString()} bytes are here.`] }), rows.map((row) => (_jsxs("div", { className: "ah-hex__row", children: [_jsx("span", { className: "ah-hex__offset", children: row.offset }), _jsx("span", { className: "ah-hex__bytes", children: row.hex }), _jsx("span", { className: "ah-hex__text", children: row.text })] }, row.offset)))] }));
34
+ }
@@ -0,0 +1,2 @@
1
+ import type { ViewBodyProps } from "../types.js";
2
+ export declare function CodeView({ file }: ViewBodyProps): import("react").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Source, with a gutter and highlighting.
3
+ //
4
+ // Virtualized, because a viewer that will open any file in a worktree will be
5
+ // handed a 60,000-line lockfile eventually, and 60,000 rows of spans is a
6
+ // frozen window. Nineteen pixels is the estimate and minimum row pitch; the
7
+ // virtualizer measures wrapped rows from their DOM boxes and corrects every
8
+ // following offset when the available width changes.
9
+ import { useCallback, useMemo, useRef } from "react";
10
+ import { useVirtualizer } from "@tanstack/react-virtual";
11
+ import { CodeMinimap } from "../minimap/CodeMinimap.js";
12
+ import { highlight, PLAIN_TEXT } from "../syntax/index.js";
13
+ /** One visual row's minimum and unmeasured estimate, in CSS px. */
14
+ const LINE_HEIGHT = 19;
15
+ /** Rows drawn beyond the viewport, so a flick does not show blank bands. */
16
+ const OVERSCAN = 30;
17
+ /** A tab uses the same stop width in the source listing and minimap. */
18
+ const TAB_COLUMNS = 2;
19
+ export function CodeView({ file }) {
20
+ const scrollerRef = useRef(null);
21
+ const lines = useMemo(() => {
22
+ const source = file.text ?? "";
23
+ const highlighted = highlight(source, file.kind.language ?? PLAIN_TEXT);
24
+ // A file that ends in a newline is not a file with a blank last line;
25
+ // every editor counts it the same way.
26
+ return highlighted.length > 1 && highlighted[highlighted.length - 1].length === 0
27
+ ? highlighted.slice(0, -1)
28
+ : highlighted;
29
+ }, [file]);
30
+ // Handed to CSS as a variable so the wrapped source measure begins at one
31
+ // stable gutter edge regardless of the number of lines in the file.
32
+ const digits = `${String(lines.length).length}ch`;
33
+ const virtualizer = useVirtualizer({
34
+ count: lines.length,
35
+ getScrollElement: () => scrollerRef.current,
36
+ estimateSize: () => LINE_HEIGHT,
37
+ overscan: OVERSCAN,
38
+ });
39
+ const scrollToLine = useCallback((lineIndex) => {
40
+ virtualizer.scrollToIndex(lineIndex, { align: "center" });
41
+ }, [virtualizer]);
42
+ return (_jsxs("div", { className: "ah-code-shell", children: [_jsx("div", { className: "ah-fileview__scroll ah-code", ref: scrollerRef, style: { "--ah-code-digits": digits }, children: _jsx("div", { className: "ah-code__sizer", style: { height: virtualizer.getTotalSize() }, children: virtualizer.getVirtualItems().map((row) => (_jsxs("div", { className: "ah-code__line", "data-index": row.index, ref: virtualizer.measureElement, style: { transform: `translateY(${row.start}px)` }, children: [_jsx("span", { className: "ah-code__num", children: row.index + 1 }), _jsx("code", { children: lines[row.index].map((token, at) => token.kind === "plain" ? (token.text) : (
43
+ // eslint-disable-next-line react/no-array-index-key -- the
44
+ // token list is derived from immutable text; index IS its id.
45
+ _jsx("span", { "data-t": token.kind, children: token.text }, at))) })] }, row.key))) }) }), _jsx(CodeMinimap, { lines: lines, lineHeight: LINE_HEIGHT, tabColumns: TAB_COLUMNS, scrollerRef: scrollerRef, scrollToLine: scrollToLine })] }));
46
+ }
@@ -0,0 +1,7 @@
1
+ export interface DiffBodyProps {
2
+ /** git's own unified diff for one file. */
3
+ readonly unified: string;
4
+ /** The file's name, which is how the lines get their language. */
5
+ readonly name: string;
6
+ }
7
+ export declare function DiffBody({ unified, name }: DiffBodyProps): import("react").JSX.Element;
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // A file's change, as git described it — the pane itself, so that both the
3
+ // file viewer (which reaches it through the registry) and the commit viewer
4
+ // (which lays two of these out side by side) draw exactly the same thing.
5
+ //
6
+ // Unified rather than side-by-side: this dialog is 1080px at most and a
7
+ // split view halves the measure twice over — once for the gutter, once for
8
+ // the second pane — and the room's own transcript already argues that a
9
+ // narrow column of code is the thing that suffers first.
10
+ //
11
+ // The line hues are §2.5's, and they are not an exception: DESIGN.md defines
12
+ // `--vf-green` as "positive delta" and `--vf-red` as "negative delta"
13
+ // outright. What stays neutral is the diffstat FIGURE — §8's rule that hue
14
+ // says which project or which state, and `+214 −38` is neither.
15
+ import { useMemo, useRef } from "react";
16
+ import { useVirtualizer } from "@tanstack/react-virtual";
17
+ import { parseDiff } from "../diff/index.js";
18
+ import { highlight, languageFor, PLAIN_TEXT } from "../syntax/index.js";
19
+ /** Matches `--ah-code-line`; the virtualizer scrolls by it. */
20
+ const LINE_HEIGHT = 19;
21
+ const OVERSCAN = 24;
22
+ const MARK = {
23
+ add: "+",
24
+ del: "−",
25
+ context: " ",
26
+ note: "",
27
+ };
28
+ export function DiffBody({ unified, name }) {
29
+ const scrollerRef = useRef(null);
30
+ const { rows, parsed } = useMemo(() => {
31
+ const diff = parseDiff(unified);
32
+ // Every line is highlighted in the file's own language — a diff of Rust
33
+ // should read as Rust. The tokenizer runs per line here rather than over
34
+ // the file, so a block comment that opens outside the hunk is not known
35
+ // to be open; that is the honest cost of only having the hunks.
36
+ const language = languageFor(name) ?? PLAIN_TEXT;
37
+ const out = [];
38
+ for (const hunk of diff.hunks) {
39
+ out.push({
40
+ kind: "hunk",
41
+ header: hunk.header,
42
+ range: hunk.oldStart === null || hunk.newStart === null
43
+ ? "@@"
44
+ : `@@ −${hunk.oldStart} +${hunk.newStart} @@`,
45
+ });
46
+ for (const line of hunk.lines) {
47
+ out.push({
48
+ kind: "line",
49
+ line,
50
+ tokens: line.kind === "note" ? [] : (highlight(line.text, language)[0] ?? []),
51
+ });
52
+ }
53
+ }
54
+ return { rows: out, parsed: diff };
55
+ }, [unified, name]);
56
+ const virtualizer = useVirtualizer({
57
+ count: rows.length,
58
+ getScrollElement: () => scrollerRef.current,
59
+ estimateSize: () => LINE_HEIGHT,
60
+ overscan: OVERSCAN,
61
+ });
62
+ if (rows.length === 0) {
63
+ const why = parsed.absence === "binary"
64
+ ? "git will not diff a binary file, and neither will this."
65
+ : parsed.absence === "mode-only"
66
+ ? "Only the file's mode changed. Its content is identical."
67
+ : parsed.renamedFrom !== null
68
+ ? `Renamed from ${parsed.renamedFrom}, with no change to its content.`
69
+ : "The two sides are identical.";
70
+ return (_jsxs("div", { className: "ah-fileview__state", children: [_jsx("b", { children: "No lines changed" }), _jsx("span", { children: why })] }));
71
+ }
72
+ const gutter = `${String(Math.max(...rows.map((row) => row.kind === "line" ? Math.max(row.line.oldNumber ?? 0, row.line.newNumber ?? 0) : 0))).length}ch`;
73
+ return (_jsxs("div", { className: "ah-fileview__scroll ah-code ah-diff", ref: scrollerRef, style: { "--ah-code-digits": gutter }, children: [_jsxs("p", { className: "ah-diff__stat", children: [_jsxs("span", { className: "tnum", children: ["+", parsed.added, " \u2212", parsed.deleted] }), parsed.renamedFrom !== null && (_jsxs("span", { className: "ah-diff__renamed", title: parsed.renamedFrom, children: ["renamed from ", parsed.renamedFrom] }))] }), _jsx("div", { className: "ah-code__sizer", style: { height: virtualizer.getTotalSize() }, children: virtualizer.getVirtualItems().map((item) => {
74
+ const row = rows[item.index];
75
+ return (_jsx("div", { className: "ah-code__line", "data-diff": row.kind === "line" ? row.line.kind : "hunk", style: { height: LINE_HEIGHT, transform: `translateY(${item.start}px)` }, children: row.kind === "hunk" ? (_jsxs("span", { className: "ah-diff__hunk", children: [_jsx("span", { className: "ah-diff__range tnum", children: row.range }), row.header !== "" && _jsx("span", { className: "ah-diff__context", children: row.header })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "ah-code__num", children: row.line.oldNumber ?? "" }), _jsx("span", { className: "ah-code__num", children: row.line.newNumber ?? "" }), _jsx("span", { className: "ah-diff__mark", children: MARK[row.line.kind] }), _jsx("code", { children: row.line.kind === "note" ? (_jsx("em", { children: row.line.text })) : (row.tokens.map((token, at) => token.kind === "plain" ? (token.text) : (_jsx("span", { "data-t": token.kind, children: token.text }, at)))) })] })) }, item.key));
76
+ }) })] }));
77
+ }
@@ -0,0 +1,2 @@
1
+ import type { ViewBodyProps } from "../types.js";
2
+ export declare function DiffView({ file }: ViewBodyProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // The registry's way in to the diff pane.
3
+ //
4
+ // A `ViewerDefinition` renders one `OpenFile`; `DiffBody` renders one
5
+ // unified diff. Keeping them apart is what lets the commit viewer lay two
6
+ // panes out without pretending its selection is a file the registry
7
+ // resolved.
8
+ import { DiffBody } from "./DiffBody.js";
9
+ export function DiffView({ file }) {
10
+ return _jsx(DiffBody, { unified: file.unified ?? "", name: file.handle.name });
11
+ }
@@ -0,0 +1,9 @@
1
+ import type { ViewBodyProps } from "../types.js";
2
+ export declare const IMAGE_MODES: readonly [{
3
+ readonly id: "fit";
4
+ readonly label: "Fit";
5
+ }, {
6
+ readonly id: "actual";
7
+ readonly label: "1:1";
8
+ }];
9
+ export declare function ImageView({ file, mode, onRetry }: ViewBodyProps): import("react").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { useImageUrl } from "../image-resource.js";
4
+ export const IMAGE_MODES = [
5
+ { id: "fit", label: "Fit" },
6
+ { id: "actual", label: "1:1" },
7
+ ];
8
+ export function ImageView({ file, mode, onRetry }) {
9
+ const [natural, setNatural] = useState(null);
10
+ const [failedUrl, setFailedUrl] = useState(null);
11
+ const [loadedUrl, setLoadedUrl] = useState(null);
12
+ // Byte-only sources retain the generic viewer seam. Transcript images use
13
+ // shared HTTP resources and allocate no Blob.
14
+ const blob = useMemo(() => file.image ? null : URL.createObjectURL(new Blob([file.bytes], { type: file.kind.mime ?? "application/octet-stream" })), [file]);
15
+ useEffect(() => () => { if (blob)
16
+ URL.revokeObjectURL(blob); }, [blob]);
17
+ const addressed = useImageUrl(file.image, mode === "actual" ? "full" : "preview", file.imageAttempt);
18
+ const url = file.image ? addressed.url : blob;
19
+ const dimensions = file.image?.width && file.image.height ? file.image : natural;
20
+ if (url === null && addressed.pending)
21
+ return _jsx("div", { className: "ah-image", "data-mode": mode, "aria-busy": "true", children: _jsx("span", { className: "ah-image__loading", role: "status", children: "Loading image\u2026" }) });
22
+ if (url === null || failedUrl === url)
23
+ return _jsxs("div", { className: "ah-fileview__state", children: [_jsx("b", { children: "Could not load this image" }), _jsx("span", { children: "The image could not be read or decoded." }), onRetry && _jsx("button", { className: "ah-fileview__retry", type: "button", onClick: onRetry, children: "Retry" })] });
24
+ return _jsxs("div", { className: "ah-image", "data-mode": mode, "aria-busy": loadedUrl !== url, children: [loadedUrl !== url && _jsx("span", { className: "ah-image__loading", role: "status", children: "Loading image\u2026" }), _jsx("div", { className: "ah-image__frame ah-fileview__scroll", children: _jsx("img", { src: url, alt: file.handle.name, decoding: "async", onLoad: event => {
25
+ setLoadedUrl(url);
26
+ setNatural({ width: event.currentTarget.naturalWidth, height: event.currentTarget.naturalHeight });
27
+ }, onError: () => setFailedUrl(url) }, url) }), dimensions && _jsxs("span", { className: "ah-image__facts tnum", children: [dimensions.width, " \u00D7 ", dimensions.height] })] });
28
+ }
@@ -0,0 +1,9 @@
1
+ import type { ViewBodyProps } from "../types.js";
2
+ export declare const MARKDOWN_MODES: readonly [{
3
+ readonly id: "rendered";
4
+ readonly label: "Rendered";
5
+ }, {
6
+ readonly id: "source";
7
+ readonly label: "Source";
8
+ }];
9
+ export declare function MarkdownView(props: ViewBodyProps): import("react").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // A markdown file, rendered — or read as its own source, which is the one
3
+ // switch this view offers. Both readings are true, and a viewer that only
4
+ // offers the pretty one is hiding the file from the person who came to see
5
+ // the file.
6
+ import { useMemo } from "react";
7
+ import { parseMarkdown } from "../markdown/index.js";
8
+ import { MarkdownBlocks } from "../markdown/render.js";
9
+ import { CodeView } from "./CodeView.js";
10
+ export const MARKDOWN_MODES = [
11
+ { id: "rendered", label: "Rendered" },
12
+ { id: "source", label: "Source" },
13
+ ];
14
+ export function MarkdownView(props) {
15
+ const { file, mode, renderMarkdown } = props;
16
+ const blocks = useMemo(() => (mode === "source" || renderMarkdown !== undefined ? [] : parseMarkdown(file.text ?? "")), [file, mode, renderMarkdown]);
17
+ if (mode === "source")
18
+ return _jsx(CodeView, { ...props });
19
+ return (_jsx("div", { className: "ah-fileview__scroll ah-md", children: _jsx("div", { className: "ah-md__measure ah-markdown", children: renderMarkdown === undefined ? _jsx(MarkdownBlocks, { blocks: blocks }) : renderMarkdown(file.text ?? "") }) }));
20
+ }
@@ -0,0 +1,9 @@
1
+ import type { ViewBodyProps } from "../types.js";
2
+ export declare const SVG_MODES: readonly [{
3
+ readonly id: "rendered";
4
+ readonly label: "Rendered";
5
+ }, {
6
+ readonly id: "source";
7
+ readonly label: "Source";
8
+ }];
9
+ export declare function SvgView(props: ViewBodyProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CodeView } from "./CodeView.js";
3
+ import { ImageView } from "./ImageView.js";
4
+ export const SVG_MODES = [
5
+ { id: "rendered", label: "Rendered" },
6
+ { id: "source", label: "Source" },
7
+ ];
8
+ export function SvgView(props) {
9
+ return props.mode === "source" ? _jsx(CodeView, { ...props }) : _jsx(ImageView, { ...props });
10
+ }
@@ -0,0 +1,20 @@
1
+ import type { StatusLetter } from "./types.js";
2
+ import type { TreeRow } from "./path-tree.js";
3
+ export interface ChangeTreeProps {
4
+ readonly rows: readonly TreeRow[];
5
+ /** The letter each path earned, by path. */
6
+ readonly letters: ReadonlyMap<string, StatusLetter>;
7
+ /** Paths the open session touched. Empty until the typed tool projection
8
+ * ships, which draws no marks rather than guessing at them. */
9
+ readonly sessionPaths: ReadonlySet<string>;
10
+ readonly selectedPath: string | null;
11
+ readonly onSelect: (row: TreeRow) => void;
12
+ /** The act offered on each row — staging or unstaging, depending on which
13
+ * group this is. `null` while no client can serve it. */
14
+ readonly action: {
15
+ readonly label: string;
16
+ readonly run: (row: TreeRow) => void;
17
+ } | null;
18
+ readonly onDiscard: ((row: TreeRow) => void) | null;
19
+ }
20
+ export declare function ChangeTree({ rows, letters, sessionPaths, selectedPath, onSelect, action, onDiscard, }: ChangeTreeProps): import("react").JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // One group's worth of changed files, as a subtree.
3
+ //
4
+ // The row is column ③'s row, with git's letter in front of the name: same
5
+ // glyph set, same 26px height, same indent, same order — because these are
6
+ // two views of ONE repository, and two lists that drew it differently would
7
+ // be two repositories as far as the eye is concerned. The glyph comes from
8
+ // mille's own `FileIcon`, which needs nothing but a name and a kind, so the
9
+ // two columns cannot drift apart as the theme changes.
10
+ //
11
+ // The letter is git's own, in the §2.5 hue its meaning earns: added is a
12
+ // positive delta, deleted a negative one, and everything else is a state the
13
+ // ramp can carry without a colour. A file this session touched wears a mark
14
+ // before its glyph — the one fact a general git client cannot show, and the
15
+ // reason column ⑤ is in a room about agent sessions at all.
16
+ import { FileIcon } from "@vibecook/mille-ui/icons";
17
+ import { vibefieldIconTheme } from "@vibecook/mille-ui/icons/vibefield";
18
+ /** What each of git's letters means, in words, for a tooltip. */
19
+ const MEANING = {
20
+ M: "modified",
21
+ A: "added",
22
+ D: "deleted",
23
+ R: "renamed",
24
+ C: "copied",
25
+ T: "type changed",
26
+ "?": "untracked",
27
+ U: "conflicted",
28
+ };
29
+ export function ChangeTree({ rows, letters, sessionPaths, selectedPath, onSelect, action, onDiscard, }) {
30
+ return (_jsx("div", { className: "ah-changetree", role: "list", children: rows.map((row) => {
31
+ const letter = letters.get(row.path) ?? null;
32
+ const touched = sessionPaths.has(row.path);
33
+ return (_jsxs("div", { className: "ah-changerow", role: "listitem", "data-kind": row.kind, "data-selected": row.path === selectedPath ? "" : undefined, style: { paddingLeft: `${8 + row.depth * 14}px` }, children: [_jsxs("button", { type: "button", className: "ah-changerow__name", title: row.path, onClick: () => onSelect(row), children: [_jsx("i", { className: "ah-changerow__mark", "data-touched": touched ? "" : undefined, title: touched ? "this session touched this file" : undefined }), _jsx(FileIcon, { className: "ah-changerow__icon", entry: { name: row.label, kind: row.kind === "directory" ? 1 : 0 }, theme: vibefieldIconTheme, expanded: row.kind === "directory" }), _jsx("code", { className: "ah-changerow__letter", "data-letter": letter ?? undefined, title: letter === null ? undefined : MEANING[letter], children: letter ?? "" }), _jsx("span", { children: row.label })] }), _jsxs("span", { className: "ah-changerow__acts", children: [onDiscard !== null && row.kind === "file" && (_jsx("button", { type: "button", title: "Discard changes to this file", onClick: () => onDiscard(row), children: "\u21A9" })), action !== null && (_jsx("button", { type: "button", title: action.label, onClick: () => action.run(row), children: action.label === "Stage" ? "+" : "−" }))] })] }, `${row.kind}:${row.path}`));
34
+ }) }));
35
+ }
@@ -0,0 +1,12 @@
1
+ import type { Commit, CommitFile, GitClient } from "./types.js";
2
+ export interface CommitViewerProps {
3
+ readonly commit: Commit;
4
+ /** `null` while git is still being asked what it touched. */
5
+ readonly files: readonly CommitFile[] | null;
6
+ readonly client: GitClient | null;
7
+ readonly sessionPaths: ReadonlySet<string>;
8
+ readonly currentTimestamp: number;
9
+ readonly onClose: () => void;
10
+ readonly onReceipt: (text: string) => void;
11
+ }
12
+ export declare function CommitViewer({ commit, files, client, sessionPaths, currentTimestamp, onClose, onReceipt, }: CommitViewerProps): import("react").JSX.Element;
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // One commit, opened over the room.
3
+ //
4
+ // This is the shape a commit actually wants and a 280px column could never
5
+ // give it: the files on the left, the change on the right, both at once. It
6
+ // is the same surface the file viewer uses — same shell, same material, same
7
+ // Escape — because a reader opening a commit and a reader opening a file are
8
+ // doing the same kind of thing, and the room should not have two answers for
9
+ // "something opened over what I was reading".
10
+ //
11
+ // The left pane is the Changes view's own subtree, so a path learned in the
12
+ // column still holds here; the right pane is the file viewer's own diff, so
13
+ // a change looks the same wherever it is read.
14
+ import { useEffect, useMemo, useState } from "react";
15
+ import { DiffBody } from "../file-viewer/index.js";
16
+ import { AgentMark } from "../../lib/agents.js";
17
+ import { clockShort, dayLabel } from "../../lib/format.js";
18
+ import { CopyGlyph, CloseGlyph } from "../../lib/icons.js";
19
+ import { DialogShell } from "../ui/index.js";
20
+ import { ChangeTree } from "./ChangeTree.js";
21
+ import { creditedAgents } from "./co-author.js";
22
+ import { buildPathTree } from "./path-tree.js";
23
+ export function CommitViewer({ commit, files, client, sessionPaths, currentTimestamp, onClose, onReceipt, }) {
24
+ const rows = useMemo(() => buildPathTree((files ?? []).map((file) => file.path)), [files]);
25
+ const letters = useMemo(() => {
26
+ const out = new Map();
27
+ for (const file of files ?? [])
28
+ out.set(file.path, file.status);
29
+ return out;
30
+ }, [files]);
31
+ // The first file, chosen for the reader: a commit viewer that opens on an
32
+ // empty right pane makes them click twice to see what they came for.
33
+ const [selected, setSelected] = useState(null);
34
+ const firstPath = files?.[0]?.path ?? null;
35
+ useEffect(() => {
36
+ setSelected((current) => (current === null ? firstPath : current));
37
+ }, [firstPath]);
38
+ const [diff, setDiff] = useState({ status: "reading" });
39
+ useEffect(() => {
40
+ if (selected === null || client === null)
41
+ return;
42
+ let cancelled = false;
43
+ setDiff({ status: "reading" });
44
+ void client
45
+ .diff({ path: selected, sha: commit.sha })
46
+ .then((answer) => {
47
+ if (cancelled)
48
+ return;
49
+ if (answer.error !== null)
50
+ setDiff({ status: "failed", reason: answer.error });
51
+ else
52
+ setDiff({ status: "ready", unified: answer.text });
53
+ })
54
+ .catch((error) => {
55
+ if (cancelled)
56
+ return;
57
+ setDiff({
58
+ status: "failed",
59
+ reason: error instanceof Error ? error.message : "the diff failed",
60
+ });
61
+ });
62
+ return () => {
63
+ cancelled = true;
64
+ };
65
+ }, [selected, client, commit.sha]);
66
+ const agents = creditedAgents(commit.coAuthors);
67
+ const drawn = new Set(agents.map((agent) => agent.label));
68
+ const people = [commit.author, ...commit.coAuthors.map((author) => author.name)].filter((name) => name !== "" && !drawn.has(name));
69
+ const selectedName = selected === null ? null : selected.slice(selected.lastIndexOf("/") + 1);
70
+ return (_jsxs(DialogShell, { title: `${commit.short} — ${commit.subject}`, onClose: onClose, wide: true, children: [_jsxs("header", { className: "ah-fileview__head ah-commitview__head", children: [_jsx("div", { className: "ah-fileview__title", children: _jsx("strong", { className: "ah-commitview__subject", title: commit.subject, children: commit.subject }) }), _jsxs("div", { className: "ah-fileview__acts", children: [_jsx("button", { type: "button", className: "ah-iconbtn", title: "Copy the full sha", "aria-label": "Copy the full sha", onClick: () => {
71
+ void navigator.clipboard
72
+ .writeText(commit.sha)
73
+ .then(() => onReceipt("sha copied"))
74
+ .catch(() => onReceipt("the clipboard refused"));
75
+ }, children: _jsx(CopyGlyph, {}) }), _jsx("button", { type: "button", className: "ah-iconbtn", title: "Close (Esc)", "aria-label": "Close", onClick: onClose, children: _jsx(CloseGlyph, {}) })] }), _jsxs("p", { className: "ah-commitview__meta", children: [people.map((name) => (_jsx("span", { children: name }, name))), agents.map((agent) => (_jsx(AgentMark, { kind: agent.kind, note: agent.label }, agent.kind))), _jsx("code", { children: commit.short }), !commit.merge && (_jsxs("span", { className: "tnum", children: ["+", commit.added, " \u2212", commit.deleted] })), _jsxs("time", { className: "tnum", dateTime: new Date(commit.timestampMs).toISOString(), children: [dayLabel(commit.timestampMs, currentTimestamp), " ", clockShort(commit.timestampMs)] })] })] }), _jsxs("div", { className: "ah-commitview", children: [_jsxs("div", { className: "ah-commitview__files", children: [_jsx("div", { className: "ah-group", children: files === null
76
+ ? "Files"
77
+ : `${files.length} changed ${files.length === 1 ? "file" : "files"}` }), _jsx("div", { className: "ah-commitview__list", children: _jsx(ChangeTree, { rows: rows, letters: letters, sessionPaths: sessionPaths, selectedPath: selected, onSelect: (row) => row.kind === "file" && setSelected(row.path),
78
+ // A commit is history: nothing here stages, unstages or
79
+ // discards, because those act on the working tree.
80
+ action: null, onDiscard: null }) })] }), _jsx("div", { className: "ah-commitview__diff", children: selected === null ? (_jsxs("div", { className: "ah-fileview__state", children: [_jsx("b", { children: files === null ? "Reading the commit" : "This commit touched no files" }), _jsx("span", { children: files === null
81
+ ? "Asking git what it changed."
82
+ : commit.merge
83
+ ? "It is a merge, and its parents carry the work."
84
+ : "An empty commit." })] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "ah-commitview__path ah-idname", title: selected, children: _jsx("bdi", { children: selected }) }), diff.status === "ready" ? (_jsx(DiffBody, { unified: diff.unified, name: selectedName ?? selected })) : diff.status === "failed" ? (_jsxs("div", { className: "ah-fileview__state", children: [_jsx("b", { children: "Could not read that change" }), _jsx("span", { children: diff.reason })] })) : (_jsxs("div", { className: "ah-fileview__state", "data-waiting": true, children: [_jsx("b", { children: "Reading" }), _jsx("span", { children: "Asking git for this file's change." })] }))] })) })] })] }));
85
+ }
@@ -0,0 +1,17 @@
1
+ import type { StatusEntry } from "./types.js";
2
+ /** `2 added · 5 modified · 1 deleted` — what git would say about this set in
3
+ * one line, counted off the entries the column is drawing. */
4
+ export declare function changeShapeOf(entries: readonly StatusEntry[]): string;
5
+ export interface GitChangesProps {
6
+ readonly entries: readonly StatusEntry[];
7
+ readonly sessionPaths: ReadonlySet<string>;
8
+ readonly selection: {
9
+ readonly path: string;
10
+ readonly staged: boolean;
11
+ } | null;
12
+ readonly onSelect: (path: string, staged: boolean) => void;
13
+ readonly onStage: ((paths: readonly string[]) => void) | null;
14
+ readonly onUnstage: ((paths: readonly string[]) => void) | null;
15
+ readonly onDiscard: ((paths: readonly string[]) => void) | null;
16
+ }
17
+ export declare function GitChanges({ entries, sessionPaths, selection, onSelect, onStage, onUnstage, onDiscard, }: GitChangesProps): import("react").JSX.Element;
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // The Changes view: what the index holds, and what the working tree holds.
3
+ //
4
+ // Two groups, not a mark on every row — "it is the shape `git status` itself
5
+ // has… and position is the quietest way to say a binary" (design record §8).
6
+ // A file with staged changes AND further edits appears in both, because it is
7
+ // in both, and the two rows open two different diffs.
8
+ import { useMemo } from "react";
9
+ import { EmptyState } from "../ui/index.js";
10
+ import { ChangeTree } from "./ChangeTree.js";
11
+ import { buildPathTree, filesUnder } from "./path-tree.js";
12
+ /** `2 added · 5 modified · 1 deleted` — what git would say about this set in
13
+ * one line, counted off the entries the column is drawing. */
14
+ export function changeShapeOf(entries) {
15
+ const tally = { added: 0, modified: 0, deleted: 0, untracked: 0, conflicted: 0 };
16
+ for (const entry of entries) {
17
+ // One file, one word: the index's letter is what a commit would record,
18
+ // so it speaks first.
19
+ const letter = entry.index ?? entry.worktree;
20
+ if (letter === "A")
21
+ tally.added += 1;
22
+ else if (letter === "D")
23
+ tally.deleted += 1;
24
+ else if (letter === "?")
25
+ tally.untracked += 1;
26
+ else if (letter === "U")
27
+ tally.conflicted += 1;
28
+ else if (letter !== null)
29
+ tally.modified += 1;
30
+ }
31
+ return [
32
+ [tally.conflicted, "conflicted"],
33
+ [tally.added, "added"],
34
+ [tally.modified, "modified"],
35
+ [tally.deleted, "deleted"],
36
+ [tally.untracked, "untracked"],
37
+ ]
38
+ .filter(([count]) => count > 0)
39
+ .map(([count, word]) => `${count} ${word}`)
40
+ .join(" · ");
41
+ }
42
+ function group(entries, slot) {
43
+ const letters = new Map();
44
+ for (const entry of entries) {
45
+ const letter = entry[slot];
46
+ if (letter !== null)
47
+ letters.set(entry.path, letter);
48
+ }
49
+ return {
50
+ rows: buildPathTree([...letters.keys()]),
51
+ letters,
52
+ count: letters.size,
53
+ };
54
+ }
55
+ export function GitChanges({ entries, sessionPaths, selection, onSelect, onStage, onUnstage, onDiscard, }) {
56
+ const staged = useMemo(() => group(entries, "index"), [entries]);
57
+ const unstaged = useMemo(() => group(entries, "worktree"), [entries]);
58
+ if (staged.count === 0 && unstaged.count === 0) {
59
+ return (_jsx(EmptyState, { title: "Nothing to commit", description: "The working tree matches HEAD. Every change this branch has is in its history." }));
60
+ }
61
+ return (_jsxs("div", { className: "ah-scroll", children: [staged.count > 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ah-group", children: ["Staged", _jsx("span", { className: "ah-hitcount tnum", children: staged.count })] }), _jsx(ChangeTree, { rows: staged.rows, letters: staged.letters, sessionPaths: sessionPaths, selectedPath: selection?.staged === true ? selection.path : null, onSelect: (row) => row.kind === "file" && onSelect(row.path, true), action: onUnstage === null
62
+ ? null
63
+ : { label: "Unstage", run: (row) => onUnstage(filesUnder(staged.rows, row)) }, onDiscard: null })] })), unstaged.count > 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ah-group", children: ["Unstaged", _jsx("span", { className: "ah-hitcount tnum", children: unstaged.count })] }), _jsx(ChangeTree, { rows: unstaged.rows, letters: unstaged.letters, sessionPaths: sessionPaths, selectedPath: selection?.staged === false ? selection.path : null, onSelect: (row) => row.kind === "file" && onSelect(row.path, false), action: onStage === null
64
+ ? null
65
+ : { label: "Stage", run: (row) => onStage(filesUnder(unstaged.rows, row)) },
66
+ // Discard is the one act here that destroys work, so it is offered
67
+ // only on the unstaged side — the side where "throw this away" is
68
+ // the whole of what it means.
69
+ onDiscard: onDiscard === null ? null : (row) => onDiscard(filesUnder(unstaged.rows, row)) })] }))] }));
70
+ }
@@ -0,0 +1,9 @@
1
+ import type { Commit } from "./types.js";
2
+ export interface GitHistoryProps {
3
+ readonly commits: readonly Commit[];
4
+ /** The commit the column has opened, so the row it came from stays lit. */
5
+ readonly selectedSha: Commit | null;
6
+ readonly onSelect: (commit: Commit) => void;
7
+ readonly currentTimestamp: number;
8
+ }
9
+ export declare function GitHistory({ commits, selectedSha, onSelect, currentTimestamp, }: GitHistoryProps): import("react").JSX.Element;
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // The History view: what this branch has committed.
3
+ //
4
+ // The commit row is the session row one object down — message on top, the
5
+ // byline and diffstat in the middle, sha bottom-left and age bottom-right —
6
+ // with two rules from the design record §8:
7
+ //
8
+ // · the diffstat is NEUTRAL, never git's green and red. Hue in this room
9
+ // says which project or which state; a direction of change is neither;
10
+ // · only one git state is drawn — not pushed yet — because it is the one
11
+ // the reader can still act on.
12
+ //
13
+ // The record's third rule was that the row carries no agent mark, because
14
+ // "which one ran this session is already on the session row". That held for
15
+ // the column it described, which was scoped to ONE session. This one is a
16
+ // view of the PROJECT's repository and lists commits from sessions that are
17
+ // not in this room at all — most of them from no session it has ever seen.
18
+ // The session row cannot speak for them, so the redundancy the rule guarded
19
+ // against does not exist here, and the mark is the fastest way to read a
20
+ // history for who built it. It follows §2.6's rule for provider identity:
21
+ // monochrome, at `currentColor`, carrying no hue of its own.
22
+ //
23
+ // The record also says the row is not pressable, "this proposal has no diff
24
+ // view, and a hover fill would be promising one". There is a diff view now,
25
+ // so the row is pressable and the promise is kept.
26
+ import { EmptyState } from "../ui/index.js";
27
+ import { AgentMark } from "../../lib/agents.js";
28
+ import { lastActive } from "../../lib/format.js";
29
+ import { creditedAgents } from "./co-author.js";
30
+ /**
31
+ * Everyone git says wrote this commit, minus the agents the row is already
32
+ * drawing as marks.
33
+ *
34
+ * A recognised agent is a glyph at the end of the message line; naming it
35
+ * here as well would spend a 280px row saying the same thing twice. An
36
+ * UNRECOGNISED co-author is a person, and keeps their name.
37
+ */
38
+ function byline(commit) {
39
+ const drawn = new Set(creditedAgents(commit.coAuthors).map((agent) => agent.label));
40
+ return [commit.author, ...commit.coAuthors.map((author) => author.name)]
41
+ .filter((name) => name !== "" && !drawn.has(name))
42
+ .join(", ");
43
+ }
44
+ /** The unpushed mark: an arrow out, in the row's marker column. */
45
+ function PushMark() {
46
+ return (_jsx("i", { className: "ah-push", title: "not pushed yet", children: _jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M8 13V3.6" }), _jsx("path", { d: "M3.8 7.8 8 3.4l4.2 4.4" })] }) }));
47
+ }
48
+ export function GitHistory({ commits, selectedSha, onSelect, currentTimestamp, }) {
49
+ if (commits.length === 0) {
50
+ return (_jsx(EmptyState, { title: "No commits yet", description: "This branch has no history of its own to show." }));
51
+ }
52
+ return (_jsx("div", { className: "ah-scroll", children: commits.map((commit) => {
53
+ const agents = creditedAgents(commit.coAuthors);
54
+ return (_jsxs("button", { type: "button", className: "ah-commit", "data-selected": commit.sha === selectedSha?.sha ? "" : undefined, onClick: () => onSelect(commit), children: [commit.pushed === false && _jsx(PushMark, {}), _jsxs("span", { className: "ah-commit__l1", children: [_jsx("strong", { title: commit.subject, children: commit.subject }), agents.length > 0 && (_jsx("span", { className: "ah-agents ah-commit__agents", children: agents.map((agent) => (_jsx(AgentMark, { kind: agent.kind, note: agent.label }, agent.kind))) }))] }), _jsxs("span", { className: "ah-commit__meta", children: [_jsx("span", { className: "ah-commit__who", title: byline(commit), children: byline(commit) }), _jsx("span", { children: "\u00B7" }), commit.merge ? (
55
+ // A merge's diffstat is not a fact about one person's work.
56
+ _jsx("span", { children: "merge" })) : (_jsxs(_Fragment, { children: [_jsxs("span", { className: "tnum", children: ["+", commit.added, " \u2212", commit.deleted] }), _jsx("span", { children: "\u00B7" }), _jsxs("span", { className: "tnum", children: [commit.files, " ", commit.files === 1 ? "file" : "files"] })] }))] }), _jsxs("span", { className: "ah-commit__l3", children: [_jsx("code", { children: commit.short }), _jsx("span", { className: "ah-last", children: lastActive(commit.timestampMs, currentTimestamp) })] })] }, commit.sha));
57
+ }) }));
58
+ }
@@ -0,0 +1,14 @@
1
+ import type { CoAuthor } from "./types.js";
2
+ /** The runtime kind this co-author is, or `null` when nothing recognises it —
3
+ * which is how a human co-author stays a human. */
4
+ export declare function agentKindOf(author: CoAuthor): string | null;
5
+ export interface CreditedAgent {
6
+ readonly kind: string;
7
+ /** The trailer's own name — `Claude Opus 5 (1M context)` is more than the
8
+ * kind knows, and it is what the reader recognises. */
9
+ readonly label: string;
10
+ }
11
+ /** The agents credited on a commit, deduplicated by kind and in trailer
12
+ * order. Two trailers for one agent is one mark, because the row is saying
13
+ * WHICH agent, not how many times it signed. */
14
+ export declare function creditedAgents(coAuthors: readonly CoAuthor[]): readonly CreditedAgent[];