@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,216 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // A host's menu (`RoomMenu`), drawn as the room's popover rows from the
3
+ // control that opens it: a head's act (R5), ③'s folder (R6), a list's chip
4
+ // (R7), a row's act. The rows are the host's; their faces — the check, the
5
+ // mark, the second line, the group heads, the filter past a count, a row's
6
+ // own act — are the room's.
7
+ //
8
+ // The rows are drawn ABOVE the columns, in the room's root (`MenuLayer`):
9
+ // every column clips what overflows it, so rows hung inside one lost whichever
10
+ // edge crossed it. Anchored to their control, they flip above it when there
11
+ // is more room there, and they are clamped inside the room's box.
12
+ //
13
+ // While it is open it listens for a press outside, for Escape, and for the
14
+ // window's resize and scroll (to stay on its control); the arrow keys walk its
15
+ // rows. It binds nothing while it is closed. Opened by a key, the chosen row
16
+ // takes focus and wears the ring; opened by a pointer, the rows take focus
17
+ // without a ring until a key moves in them.
18
+ import { createContext, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
19
+ import { createPortal } from "react-dom";
20
+ const CHECK = (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m3.5 8.5 3 3 6-7" }) }));
21
+ /** The room's root, where its menus are drawn over every column. Absent (a
22
+ * part mounted outside a room), a menu hangs from its control as before. */
23
+ const MenuLayerContext = createContext(null);
24
+ export const MenuLayerProvider = MenuLayerContext.Provider;
25
+ /** The edge the rows keep from the room's box, and from their control. */
26
+ const MENU_MARGIN = 8;
27
+ const MENU_GAP = 6;
28
+ /** The rows' widest, wherever they open: a path past it ellipsizes. */
29
+ const MENU_MAX_WIDTH = 360;
30
+ /**
31
+ * Where the rows go, in the box's own coordinates: under their control
32
+ * (or over it, when there is more room there and not enough below), from the
33
+ * control's start or end edge, and never past the box's edges less a margin.
34
+ */
35
+ export function placeMenu(control, box, menu, align) {
36
+ const boxWidth = box.right - box.left;
37
+ const boxHeight = box.bottom - box.top;
38
+ const width = Math.max(0, Math.min(menu.width, boxWidth - 2 * MENU_MARGIN));
39
+ const start = control.left - box.left;
40
+ const end = control.right - box.left;
41
+ const wanted = align === "end" ? end - width : start;
42
+ const left = Math.max(MENU_MARGIN, Math.min(boxWidth - MENU_MARGIN - width, wanted));
43
+ const below = boxHeight - MENU_MARGIN - (control.bottom - box.top + MENU_GAP);
44
+ const above = control.top - box.top - MENU_GAP - MENU_MARGIN;
45
+ const side = menu.height <= below || below >= above ? "below" : "above";
46
+ const room = Math.max(0, side === "below" ? below : above);
47
+ const height = Math.min(menu.height, room);
48
+ const top = side === "below" ? control.bottom - box.top + MENU_GAP : control.top - box.top - MENU_GAP - height;
49
+ return { left, top, width, room, side };
50
+ }
51
+ /** A control that opens the host's rows. */
52
+ export function HostMenuButton({ menu, className, label, title, disabled, data, align = "start", children }) {
53
+ const [open, setOpen] = useState(null);
54
+ const rootRef = useRef(null);
55
+ const triggerRef = useRef(null);
56
+ const menuRef = useRef(null);
57
+ // A press that starts with a pointer opens without a ring; a key does not
58
+ // send a pointer first.
59
+ const pointerPress = useRef(false);
60
+ const layer = useContext(MenuLayerContext);
61
+ const id = useId();
62
+ useEffect(() => {
63
+ if (open === null)
64
+ return;
65
+ const pointerDown = (event) => {
66
+ const target = event.target;
67
+ if (rootRef.current?.contains(target) || menuRef.current?.contains(target))
68
+ return;
69
+ setOpen(null);
70
+ };
71
+ const keyDown = (event) => {
72
+ if (event.key !== "Escape")
73
+ return;
74
+ event.preventDefault();
75
+ setOpen(null);
76
+ triggerRef.current?.focus();
77
+ };
78
+ document.addEventListener("pointerdown", pointerDown);
79
+ document.addEventListener("keydown", keyDown);
80
+ return () => {
81
+ document.removeEventListener("pointerdown", pointerDown);
82
+ document.removeEventListener("keydown", keyDown);
83
+ };
84
+ }, [open]);
85
+ const rows = open === null ? null : (_jsx(HostMenuRows, { id: id, menu: menu, align: align, opened: open, control: triggerRef, layer: layer, menuRef: menuRef, onChosen: () => {
86
+ setOpen(null);
87
+ triggerRef.current?.focus();
88
+ } }));
89
+ return (_jsxs("span", { className: "ah-menuhost", ref: rootRef, children: [_jsx("button", { ref: triggerRef, type: "button", className: className, title: title, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open !== null, "aria-controls": open !== null ? id : undefined, disabled: disabled === true, ...data, onPointerDown: () => {
90
+ pointerPress.current = true;
91
+ }, onClick: () => {
92
+ const by = pointerPress.current ? "pointer" : "key";
93
+ pointerPress.current = false;
94
+ setOpen((current) => (current === null ? by : null));
95
+ }, children: children }), rows !== null && (layer === null ? rows : createPortal(rows, layer))] }));
96
+ }
97
+ function matches(item, term) {
98
+ return item.filterText === undefined || item.filterText.toLowerCase().includes(term);
99
+ }
100
+ function rectOf(element) {
101
+ const rect = element.getBoundingClientRect();
102
+ return { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom };
103
+ }
104
+ function HostMenuRows({ id, menu, align, opened, control, layer, menuRef, onChosen, }) {
105
+ const [filter, setFilter] = useState("");
106
+ const listRef = useRef(null);
107
+ const filterRef = useRef(null);
108
+ const total = menu.groups.reduce((count, group) => count + group.items.length, 0);
109
+ const filtering = menu.filterAfter !== undefined && total > menu.filterAfter;
110
+ const term = filter.trim().toLowerCase();
111
+ const groups = !filtering || term === ""
112
+ ? menu.groups
113
+ : menu.groups
114
+ .map((group) => ({ ...group, items: group.items.filter((item) => matches(item, term)) }))
115
+ .filter((group) => group.items.length > 0);
116
+ const radio = menu.groups.some((group) => group.items.some((item) => item.checked !== undefined));
117
+ const rows = () => [...(listRef.current?.querySelectorAll(".ah-menu__item:not(:disabled)") ?? [])];
118
+ // Placed in the room's box, before the first paint and whenever the window
119
+ // moves under it. Measured at its natural size, then held to the room it has.
120
+ useLayoutEffect(() => {
121
+ const element = menuRef.current;
122
+ if (layer === null || element === null)
123
+ return;
124
+ const place = () => {
125
+ const anchor = control.current;
126
+ if (anchor === null)
127
+ return;
128
+ const box = layer.getBoundingClientRect();
129
+ // a box drawn scaled (a host's recede) is measured in its own pixels
130
+ const scale = layer.offsetWidth > 0 ? box.width / layer.offsetWidth : 1;
131
+ const within = (rect) => ({
132
+ left: (rect.left - box.left) / scale,
133
+ top: (rect.top - box.top) / scale,
134
+ right: (rect.right - box.left) / scale,
135
+ bottom: (rect.bottom - box.top) / scale,
136
+ });
137
+ const frame = within(rectOf(layer));
138
+ element.style.maxHeight = "";
139
+ element.style.maxWidth = `${Math.max(0, Math.min(MENU_MAX_WIDTH, frame.right - frame.left - 2 * MENU_MARGIN))}px`;
140
+ const placed = placeMenu(within(rectOf(anchor)), frame, { width: element.offsetWidth, height: element.offsetHeight }, align);
141
+ element.style.left = `${placed.left}px`;
142
+ element.style.top = `${placed.top}px`;
143
+ element.style.maxHeight = `${placed.room}px`;
144
+ element.dataset.side = placed.side;
145
+ };
146
+ place();
147
+ window.addEventListener("resize", place);
148
+ window.addEventListener("scroll", place, true);
149
+ return () => {
150
+ window.removeEventListener("resize", place);
151
+ window.removeEventListener("scroll", place, true);
152
+ };
153
+ }, [layer, control, menuRef, align, groups.length, filtering]);
154
+ // Opening lands on the filter; else, by a key, on the chosen row (which
155
+ // wears the ring), and by a pointer on the rows themselves (no ring).
156
+ useLayoutEffect(() => {
157
+ if (filtering) {
158
+ filterRef.current?.focus();
159
+ return;
160
+ }
161
+ if (opened === "pointer") {
162
+ listRef.current?.focus();
163
+ return;
164
+ }
165
+ const all = rows();
166
+ (all.find((row) => row.getAttribute("aria-checked") === "true") ?? all[0])?.focus();
167
+ // once, on open
168
+ }, []);
169
+ const walk = (event) => {
170
+ const target = event.target;
171
+ // A row's own act is beside it: → reaches it, ← comes back.
172
+ if (event.key === "ArrowRight" && target.classList.contains("ah-menu__item")) {
173
+ const act = target.parentElement?.querySelector(":scope > .ah-menu__act:not(:disabled)");
174
+ if (act) {
175
+ event.preventDefault();
176
+ act.focus();
177
+ }
178
+ return;
179
+ }
180
+ if (event.key === "ArrowLeft" && target.classList.contains("ah-menu__act")) {
181
+ event.preventDefault();
182
+ target.parentElement?.querySelector(":scope > .ah-menu__item")?.focus();
183
+ return;
184
+ }
185
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key))
186
+ return;
187
+ const all = rows();
188
+ if (all.length === 0)
189
+ return;
190
+ event.preventDefault();
191
+ const from = target.classList.contains("ah-menu__act")
192
+ ? target.parentElement?.querySelector(":scope > .ah-menu__item") ?? null
193
+ : target;
194
+ const at = all.indexOf(from);
195
+ const next = event.key === "Home" ? 0
196
+ : event.key === "End" ? all.length - 1
197
+ : event.key === "ArrowDown" ? (at + 1) % all.length
198
+ : at <= 0 ? all.length - 1 : at - 1;
199
+ all[next]?.focus();
200
+ };
201
+ const item = (row) => {
202
+ const choice = (_jsxs("button", { type: "button", className: "ah-menu__item", role: radio ? "menuitemradio" : "menuitem", "aria-checked": radio ? row.checked === true : undefined, "data-depth": row.depth === 1 ? "1" : undefined, "data-key": row.key, disabled: row.disabled === true, tabIndex: -1, onClick: () => {
203
+ row.onSelect?.();
204
+ onChosen();
205
+ }, children: [_jsx("span", { className: "ah-menu__check", children: row.checked === true ? CHECK : null }), row.mark !== undefined && _jsx("span", { className: "ah-menu__mark", children: row.mark }), _jsxs("span", { className: "ah-menu__body", children: [_jsx("span", { className: "ah-menu__label", children: row.label }), row.detail !== undefined && _jsx("span", { className: "ah-menu__detail", children: row.detail })] }), row.aside !== undefined && _jsx("span", { className: "ah-menu__aside", children: row.aside })] }, row.key));
206
+ const act = row.act;
207
+ if (act === undefined)
208
+ return choice;
209
+ // A row with its own act holds two buttons side by side, never one in another.
210
+ return (_jsxs("div", { className: "ah-menu__row", role: "none", "data-key": row.key, children: [choice, _jsx("button", { type: "button", className: "ah-menu__act", role: "menuitem", "data-act": act.key, title: act.label, "aria-label": act.label, disabled: act.disabled === true, tabIndex: -1, onClick: () => {
211
+ act.onPress?.();
212
+ onChosen();
213
+ }, children: act.content })] }, row.key));
214
+ };
215
+ return (_jsxs("div", { className: "ah-menu", ref: menuRef, "data-align": align, "data-layer": layer === null ? undefined : "", onKeyDown: walk, children: [filtering && (_jsx("input", { ref: filterRef, className: "ah-menu__filter", type: "search", value: filter, placeholder: menu.filterPlaceholder ?? "Filter", "aria-label": menu.filterPlaceholder ?? "Filter", "aria-controls": id, onChange: (event) => setFilter(event.currentTarget.value) })), _jsxs("div", { className: "ah-menu__list", id: id, role: "menu", "aria-label": menu.label, ref: listRef, tabIndex: -1, children: [groups.map((group) => (_jsxs("div", { className: "ah-menu__group", role: "group", children: [group.title !== undefined && _jsx("div", { className: "ah-menu__title", children: group.title }), group.items.map(item)] }, group.key))), groups.length === 0 && _jsx("p", { className: "ah-menu__empty", children: menu.empty ?? "Nothing to choose" })] })] }));
216
+ }
@@ -0,0 +1,4 @@
1
+ import type { IngestActivity } from "../lib/ingest-activity.js";
2
+ export declare function IngestStatus({ activity }: {
3
+ readonly activity: IngestActivity | null;
4
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId } from "react";
3
+ import { AgentMark, agentLabel } from "../lib/agents.js";
4
+ import { runtimeActivity } from "../lib/ingest-activity.js";
5
+ function ProgressMeter({ value, label, paused = false }) {
6
+ return _jsx("div", { className: "ah-ingest-meter", role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": value === null ? undefined : Math.floor(value * 100), "data-indeterminate": value === null ? "" : undefined, "data-paused": paused ? "" : undefined, children: _jsx("i", { style: value === null ? undefined : { width: `${value * 100}%` } }) });
7
+ }
8
+ export function IngestStatus({ activity }) {
9
+ const titleId = useId();
10
+ if (!activity)
11
+ return null;
12
+ const { phase, feed, footer, elapsed } = activity;
13
+ const interrupted = feed.connectionError !== null;
14
+ const ready = phase.key === "ready";
15
+ const paused = interrupted || !phase.active;
16
+ return (_jsxs("section", { className: "ah-ingest-status", "aria-labelledby": titleId, "data-state": interrupted ? "disconnected" : ready ? "complete" : phase.key, children: [_jsxs("div", { className: "ah-ingest-status__eyebrow", children: [_jsx("span", { children: ready ? "ALL SET" : "IMPORTING HISTORY" }), _jsx("span", { children: ready ? "✓" : `Step ${phase.step} of 4` })] }), _jsx("h3", { id: titleId, "aria-live": "polite", "aria-atomic": "true", children: interrupted ? "Progress updates paused" : phase.title }), _jsx("p", { className: "ah-ingest-status__detail", children: interrupted ? "Waiting for the background service. Reconnecting automatically…" : phase.detail }), _jsxs("div", { className: "ah-ingest-status__amount", children: [_jsx("span", { children: phase.amount }), phase.fraction !== null && !ready && _jsxs("b", { children: [Math.floor(phase.fraction * 100), "%"] })] }), _jsx(ProgressMeter, { value: phase.fraction, label: phase.title, paused: paused }, phase.key), _jsxs("div", { className: "ah-ingest-status__footer", children: [_jsx("span", { title: feed.connectionError ?? (footer.includes("No new") ? "The service is connected; its work counters have not changed." : undefined), children: footer }), _jsx("span", { children: elapsed })] }), !ready && (feed.ingest?.runtimes.length ?? 0) > 0 && _jsxs("details", { className: "ah-ingest-status__agents", children: [_jsxs("summary", { children: ["Agent details ", _jsx("span", { "aria-hidden": "true", children: "\u2304" })] }), _jsx("ul", { children: feed.ingest?.runtimes.map((runtime) => {
17
+ const status = runtimeActivity(runtime, feed.ingest?.phase === "restoring");
18
+ return _jsxs("li", { children: [_jsx(AgentMark, { kind: runtime.kind }), _jsxs("div", { children: [_jsxs("div", { className: "ah-ingest-status__agent-name", children: [_jsx("strong", { children: agentLabel(runtime.kind) }), runtime.state === "done" && _jsx("span", { "aria-label": "Ready to browse", children: "\u2713" })] }), _jsx("span", { className: "ah-ingest-status__agent-caption", children: status.label }), runtime.state !== "done" && _jsx(ProgressMeter, { value: status.fraction, label: `${agentLabel(runtime.kind)}: ${status.label}`, paused: paused || runtime.state === "queued" })] })] }, runtime.kind);
19
+ }) })] })] }));
20
+ }
@@ -0,0 +1,5 @@
1
+ export declare function ListActivityNotice({ pending, onShow, noun }: {
2
+ readonly pending: boolean;
3
+ readonly onShow: () => void;
4
+ readonly noun: "projects" | "sessions";
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function ListActivityNotice({ pending, onShow, noun }) {
3
+ return (_jsxs(_Fragment, { children: [_jsx("span", { className: "ah-list-update-status", role: "status", children: pending ? `New activity is available in ${noun}.` : "" }), _jsx("button", { type: "button", className: "ah-newpill ah-list-updates", "data-list-updates": "", "data-visible": pending ? "" : undefined, hidden: !pending, onClick: onShow, children: "Show recent activity" })] }));
4
+ }
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from "react";
2
+ import type { ArrangedSection } from "../lib/sections.js";
3
+ /** A section's head: the list's own break, in the host's words. */
4
+ export declare function SectionHead({ sectionKey, children }: {
5
+ readonly sectionKey: string;
6
+ readonly children: ReactNode;
7
+ }): import("react").JSX.Element;
8
+ /** A folded section's line: the host's words, the count, and the act that
9
+ * opens it. Open, the line stays as the section's head and closes it again. */
10
+ export declare function FoldLine<T>({ arranged, open, onToggle, }: {
11
+ readonly arranged: ArrangedSection<T>;
12
+ readonly open: boolean;
13
+ readonly onToggle: () => void;
14
+ }): import("react").JSX.Element;
15
+ /** Which folded sections are open. Each starts folded; one holding the
16
+ * selected row opens, and after that the reader's press decides. */
17
+ export declare function useOpenFolds<T>(arranged: readonly ArrangedSection<T>[] | null, idOf: (row: T) => string, selectedId: string | null): {
18
+ readonly isOpen: (key: string) => boolean;
19
+ readonly toggle: (key: string) => void;
20
+ };
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // A host's sections, drawn (R3): a head over each run, in the list's own day
3
+ // face, and a foot section folded into one line that opens in place. The
4
+ // rows themselves are the list's; this draws only what sits between them.
5
+ import { useCallback, useEffect, useState } from "react";
6
+ import { foldCount } from "../lib/sections.js";
7
+ /** A section's head: the list's own break, in the host's words. */
8
+ export function SectionHead({ sectionKey, children }) {
9
+ return (_jsx("div", { className: "ah-day ah-section", "data-section": sectionKey, children: children }));
10
+ }
11
+ /** A folded section's line: the host's words, the count, and the act that
12
+ * opens it. Open, the line stays as the section's head and closes it again. */
13
+ export function FoldLine({ arranged, open, onToggle, }) {
14
+ const fold = arranged.section.fold;
15
+ return (_jsxs("button", { type: "button", className: "ah-fold", "data-section": arranged.section.key, "aria-expanded": open, onClick: onToggle, children: [_jsx("span", { className: "ah-fold__label", children: fold.label }), _jsx("span", { className: "ah-fold__count tnum", children: foldCount(arranged) }), !open && _jsx("span", { className: "ah-fold__act", children: fold.act })] }));
16
+ }
17
+ /** Which folded sections are open. Each starts folded; one holding the
18
+ * selected row opens, and after that the reader's press decides. */
19
+ export function useOpenFolds(arranged, idOf, selectedId) {
20
+ const [opened, setOpened] = useState(() => new Set());
21
+ const holding = selectedId === null || arranged === null
22
+ ? null
23
+ : (arranged.find((entry) => entry.section.fold !== undefined && entry.rows.some((row) => idOf(row) === selectedId))
24
+ ?.section.key ?? null);
25
+ useEffect(() => {
26
+ if (holding === null)
27
+ return;
28
+ setOpened((current) => (current.has(holding) ? current : new Set([...current, holding])));
29
+ }, [holding, selectedId]);
30
+ const toggle = useCallback((key) => {
31
+ setOpened((current) => {
32
+ const next = new Set(current);
33
+ if (!next.delete(key))
34
+ next.add(key);
35
+ return next;
36
+ });
37
+ }, []);
38
+ return { isOpen: (key) => opened.has(key), toggle };
39
+ }
@@ -0,0 +1,9 @@
1
+ import type { RoomRename } from "../host-inputs.js";
2
+ export interface RenameHeadingProps {
3
+ readonly name: string;
4
+ readonly tint: string | null;
5
+ readonly count: number | null;
6
+ readonly countTitle?: string | undefined;
7
+ readonly rename: RoomRename;
8
+ }
9
+ export declare function RenameHeading({ name, tint, count, countTitle, rename }: RenameHeadingProps): import("react").JSX.Element;
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ②'s head with a host's rename (H4): the project's name is the control.
3
+ // Pressed, it becomes a field holding the name; Enter commits, Escape — or
4
+ // leaving the field — cancels, and a host that refuses says why right there,
5
+ // in its own words, with the field still open. Until the host's catalog
6
+ // brings the new name, the head names the project as the host last said.
7
+ import { useEffect, useRef, useState } from "react";
8
+ function failureWords(cause) {
9
+ const words = cause instanceof Error ? cause.message : typeof cause === "string" ? cause : "";
10
+ return words === "" ? "Could not rename" : `Could not rename — ${words}`;
11
+ }
12
+ export function RenameHeading({ name, tint, count, countTitle, rename }) {
13
+ const [edit, setEdit] = useState({ kind: "idle" });
14
+ const fieldRef = useRef(null);
15
+ const nameRef = useRef(null);
16
+ const label = rename.label ?? "Rename";
17
+ const alive = useRef(true);
18
+ useEffect(() => () => {
19
+ alive.current = false;
20
+ }, []);
21
+ const editing = edit.kind !== "idle";
22
+ useEffect(() => {
23
+ if (edit.kind !== "editing")
24
+ return;
25
+ fieldRef.current?.focus();
26
+ }, [edit.kind]);
27
+ const close = (refocus) => {
28
+ setEdit({ kind: "idle" });
29
+ if (refocus)
30
+ queueMicrotask(() => nameRef.current?.focus());
31
+ };
32
+ const commit = (draft) => {
33
+ const next = draft.trim();
34
+ if (next === "" || next === name) {
35
+ close(true);
36
+ return;
37
+ }
38
+ setEdit({ kind: "saving", draft });
39
+ let answer;
40
+ try {
41
+ answer = rename.onRename(next);
42
+ }
43
+ catch (cause) {
44
+ setEdit({ kind: "editing", draft, failure: failureWords(cause) });
45
+ return;
46
+ }
47
+ Promise.resolve(answer).then(() => {
48
+ if (alive.current)
49
+ close(true);
50
+ }, (cause) => {
51
+ if (alive.current)
52
+ setEdit({ kind: "editing", draft, failure: failureWords(cause) });
53
+ });
54
+ };
55
+ return (_jsxs("div", { className: "ah-colhead", "data-rename": editing ? edit.kind : "", children: [_jsx("i", { style: tint !== null ? { "--tint": tint } : undefined }), !editing ? (_jsx("button", { ref: nameRef, type: "button", className: "ah-rename", title: `${label} · ${name}`, "aria-label": `${label}: ${name}`, onClick: () => setEdit({ kind: "editing", draft: name, failure: null }), children: name })) : (_jsx("input", { ref: fieldRef, className: "ah-rename__field", value: edit.draft, "aria-label": label, "aria-invalid": edit.kind === "editing" && edit.failure !== null ? true : undefined, "aria-busy": edit.kind === "saving" ? true : undefined, readOnly: edit.kind === "saving", onFocus: (event) => event.currentTarget.select(), onChange: (event) => {
56
+ const draft = event.currentTarget.value;
57
+ setEdit((current) => (current.kind === "editing" ? { ...current, draft, failure: null } : current));
58
+ }, onKeyDown: (event) => {
59
+ if (event.key === "Enter") {
60
+ event.preventDefault();
61
+ event.stopPropagation();
62
+ if (edit.kind === "editing")
63
+ commit(edit.draft);
64
+ }
65
+ else if (event.key === "Escape") {
66
+ event.preventDefault();
67
+ event.stopPropagation();
68
+ if (edit.kind === "editing")
69
+ close(true);
70
+ }
71
+ }, onBlur: () => {
72
+ if (edit.kind === "editing")
73
+ close(false);
74
+ } })), edit.kind === "editing" && edit.failure !== null ? (_jsx("span", { className: "ah-rename__failure", role: "alert", children: edit.failure })) : (count !== null && (_jsx("span", { className: "ah-bubble", title: countTitle, children: count })))] }));
75
+ }
@@ -0,0 +1,5 @@
1
+ export declare function SearchStrip({ query, onQuery, scope, }: {
2
+ query: string;
3
+ onQuery: (q: string) => void;
4
+ scope: string;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // The room-level search strip: a line across the head of the room, never a
3
+ // modal. The scope sentence names the vendors actually indexed (§9 — the
4
+ // scope of a search is not the user's to guess).
5
+ import { SearchGlyph } from "../lib/icons.js";
6
+ export function SearchStrip({ query, onQuery, scope, }) {
7
+ return (_jsxs("div", { className: "ah-searchbar", children: [_jsxs("div", { className: "ah-search", children: [_jsx(SearchGlyph, {}), _jsx("input", { type: "search", value: query, placeholder: "Search your whole agentic past", "aria-label": "Search your whole agentic past", autoComplete: "off", spellCheck: false, onChange: (e) => onQuery(e.target.value) }), query !== "" && (_jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => onQuery(""), children: "\u00D7" }))] }), _jsx("p", { className: "ah-scope", children: scope })] }));
8
+ }
@@ -0,0 +1,13 @@
1
+ import type { Spend } from "../lib/spend.js";
2
+ interface SummaryMetricsProps {
3
+ readonly sessionCount: number;
4
+ readonly messageCount: number;
5
+ readonly tokenCount: number;
6
+ readonly spend: Spend;
7
+ readonly pending: boolean;
8
+ /** Counts are lifetime totals; tokens and spend use this panel's window. */
9
+ readonly period: string;
10
+ }
11
+ /** Portfolio and project summaries use one row and one value renderer. */
12
+ export declare function SummaryMetrics({ sessionCount, messageCount, tokenCount, spend, pending, period, }: SummaryMetricsProps): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { tokenText } from "../lib/format.js";
3
+ import { coverage, spendDescription } from "../lib/spend.js";
4
+ import { SummaryMetric } from "./ui/SummaryMetric.js";
5
+ /** Portfolio and project summaries use one row and one value renderer. */
6
+ export function SummaryMetrics({ sessionCount, messageCount, tokenCount, spend, pending, period, }) {
7
+ const state = coverage(spend);
8
+ return (_jsxs("div", { className: "ah-stats", children: [_jsx(SummaryMetric, { label: "sessions", value: sessionCount, unknown: pending && sessionCount === 0, title: `${sessionCount.toLocaleString()} sessions · all time` }), _jsx(SummaryMetric, { label: "messages", value: messageCount, unknown: pending && messageCount === 0, title: `${messageCount.toLocaleString()} messages · all time` }), _jsx(SummaryMetric, { label: "tokens", value: tokenCount, unknown: pending && tokenCount === 0, title: `${tokenCount.toLocaleString()} tokens · ${period}` }), _jsx(SummaryMetric, { label: "estimated cost", value: spend.costMicroUsd, unit: "usd", estimated: true, lowerBound: state === "partial", emptyValue: state === "unavailable" ? "n/p" : "—", unknown: pending && tokenCount === 0, title: `Estimated cost · ${spendDescription(spend, tokenText)}${state === "partial" ? " · lower bound" : ""} · ${period}` })] }));
9
+ }
@@ -0,0 +1,35 @@
1
+ import type { UsageResponse } from "@vibefield/rosetta-protocol";
2
+ import type { ProjectViewModel } from "../lib/model.js";
3
+ import type { RoomAct } from "../host-inputs.js";
4
+ export interface ProjectSummaryPanelProps {
5
+ readonly project: ProjectViewModel;
6
+ readonly visibleSessionCount: number;
7
+ readonly usage: UsageResponse | null;
8
+ readonly activityGridStartTimestamp: number;
9
+ readonly currentTimestamp: number;
10
+ /** A backfill is running: figures for an unfinished project stay veiled.
11
+ * Once the phase is live a veil never descends again. */
12
+ readonly ingestActive: boolean;
13
+ /** The census itself is still running: the counts below this panel are
14
+ * incomplete, so its veil defers to the column's census veil instead of
15
+ * stacking a near-duplicate counting label on top of it. */
16
+ readonly censusRunning: boolean;
17
+ /** `null` means the browser build has no desktop worktree integration. */
18
+ readonly isWorktreeVisible: boolean | null;
19
+ readonly onToggleWorktree: () => void;
20
+ /** R5: the host's acts, after the head's own (New agent, the primary, last). */
21
+ readonly hostActs?: readonly RoomAct[] | null | undefined;
22
+ }
23
+ export declare function ProjectSummaryPanel({ project, visibleSessionCount, usage, activityGridStartTimestamp, currentTimestamp, ingestActive, censusRunning, isWorktreeVisible, onToggleWorktree, hostActs, }: ProjectSummaryPanelProps): import("react").JSX.Element;
24
+ export interface PortfolioSummaryPanelProps {
25
+ readonly projects: readonly ProjectViewModel[];
26
+ readonly selectedProjectId: string | null;
27
+ /** A backfill is running: the portfolio's totals are still counting, so
28
+ * the whole panel stays veiled. It unveils last — the finale. */
29
+ readonly ingestActive: boolean;
30
+ /** The census is still naming sessions: defer to the column's census veil
31
+ * rather than stacking a second counting label above it. */
32
+ readonly censusRunning: boolean;
33
+ readonly onProjectSelect: (projectId: string) => void;
34
+ }
35
+ export declare function PortfolioSummaryPanel({ projects, selectedProjectId, ingestActive, censusRunning, onProjectSelect, }: PortfolioSummaryPanelProps): import("react").JSX.Element;
@@ -0,0 +1,117 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Project and portfolio summary panels decompose the ledger's totals at two
3
+ // levels. The project panel heads column ②; the portfolio panel heads column
4
+ // ①. Every chart derives from the same series as the ledger, so their figures
5
+ // cannot disagree. When collapsed, each panel becomes its column header.
6
+ import { useEffect, useMemo, useState } from "react";
7
+ import { CalendarHeatmap, ProjectChartDialog, Streamgraph, Treemap } from "./charts/index.js";
8
+ import { ColumnHeading, SegmentedControl, Veil } from "./ui/index.js";
9
+ import { SummaryMetrics } from "./SummaryMetrics.js";
10
+ import { calculateActivityStats, createCalendarHeatmapData, createModelUsageStreamgraphData, } from "../lib/chart-data.js";
11
+ import { tokenText } from "../lib/format.js";
12
+ import { createModelColors } from "../lib/model-labels.js";
13
+ import { FullscreenGlyph, GitHubGlyph, StatsGlyph, TreeGlyph } from "../lib/icons.js";
14
+ import { getCalendarDayKey, getViewerUtcOffsetMinutes } from "../lib/model.js";
15
+ import { NO_SPEND, addSpend, coverage, usdText } from "../lib/spend.js";
16
+ import { useRoom } from "../room-context.js";
17
+ import { useHostInputs } from "../host-inputs.js";
18
+ import { HostAct } from "./HostAct.js";
19
+ import { RenameHeading } from "./RenameHeading.js";
20
+ const MAX_TREEMAP_PROJECT_COUNT = 10;
21
+ // Matches the project chart's 25px selector track, 9px gap, and 106px chart body.
22
+ const SUMMARY_CHART_CONTENT_HEIGHT = 140;
23
+ const PROJECT_CHART_OPTIONS = [
24
+ { value: "activity", label: "Overview" },
25
+ { value: "models", label: "Models" },
26
+ ];
27
+ /* ── project summary panel (column ②'s header) ──────────────────────────── */
28
+ function formatHourLabel(hour) {
29
+ if (hour === 0)
30
+ return "12 AM";
31
+ if (hour < 12)
32
+ return `${hour} AM`;
33
+ if (hour === 12)
34
+ return "12 PM";
35
+ return `${hour - 12} PM`;
36
+ }
37
+ export function ProjectSummaryPanel({ project, visibleSessionCount, usage, activityGridStartTimestamp, currentTimestamp, ingestActive, censusRunning, isWorktreeVisible, onToggleWorktree, hostActs = null, }) {
38
+ // Aggregate figures become available after canonical publication and
39
+ // their own requests finish, independently of transcript readiness.
40
+ const isVeiled = ingestActive || !project.statsReady;
41
+ const [isExpanded, setIsExpanded] = useState(true);
42
+ const [expandedChart, setExpandedChart] = useState(null);
43
+ useEffect(() => setExpandedChart(null), [project.row.id]);
44
+ const { initialSummaryTab } = useRoom();
45
+ const [activeChart, setActiveChart] = useState(initialSummaryTab);
46
+ const activityStats = useMemo(() => calculateActivityStats(project.dailyTokens, project.currentDayIndex), [project.currentDayIndex, project.dailyTokens]);
47
+ const heatmapData = useMemo(() => createCalendarHeatmapData(project.dailyTokens, activityGridStartTimestamp), [activityGridStartTimestamp, project.dailyTokens]);
48
+ const modelUsageData = useMemo(() => usage
49
+ ? createModelUsageStreamgraphData(usage, currentTimestamp)
50
+ : { domain: [], series: [] }, [currentTimestamp, usage]);
51
+ const peakHour = usage && usage.hours.length > 0
52
+ ? usage.hours.reduce((busiest, hour) => hour.tokens > busiest.tokens ? hour : busiest).hour
53
+ : null;
54
+ const primaryModelLabel = modelUsageData.series[0]?.label ?? null;
55
+ const modelColors = useMemo(() => createModelColors(usage?.models.map(row => row.model) ?? []), [usage]);
56
+ // The repo act opens a REMOTE. A git_repo that is a local path is a fact
57
+ // about discovery, not an address anyone can visit — no button for it.
58
+ // R9: a host that knows the address says it (null: no act).
59
+ const { repositoryUrl: hostRepositoryUrlOf, projectRename } = useHostInputs();
60
+ const hostRepositoryUrl = hostRepositoryUrlOf?.(project.row.id);
61
+ // H4: the host renames the project where its name is.
62
+ const rename = projectRename?.(project.row.id) ?? null;
63
+ const repositoryUrl = hostRepositoryUrl !== undefined
64
+ ? hostRepositoryUrl
65
+ : project.row.git_repo !== null && !project.row.git_repo.startsWith("/")
66
+ ? project.row.git_repo
67
+ : null;
68
+ return (_jsxs("div", { className: "ah-meta", style: { "--tint": project.tint }, children: [_jsxs("div", { className: "ah-meta__head", children: [rename === null ? (_jsx(ColumnHeading, { name: project.row.name, tint: project.tint, count: visibleSessionCount, countTitle: `${visibleSessionCount} sessions in this list` })) : (_jsx(RenameHeading, { name: project.row.name, tint: project.tint, count: visibleSessionCount, countTitle: `${visibleSessionCount} sessions in this list`, rename: rename }, project.row.id)), _jsxs("span", { className: "ah-meta__acts", children: [isWorktreeVisible !== null && (_jsx("button", { type: "button", className: "ah-iconbtn", "aria-pressed": isWorktreeVisible, title: isWorktreeVisible ? "Hide the worktree" : "Show the worktree", "aria-label": "Toggle the project worktree", onClick: onToggleWorktree, children: _jsx(TreeGlyph, {}) })), _jsx("button", { type: "button", className: "ah-iconbtn", "aria-pressed": isExpanded, title: isExpanded ? "Hide the figures" : "Show the figures", "aria-label": "Toggle the figures", onClick: () => setIsExpanded((current) => !current), children: _jsx(StatsGlyph, {}) }), repositoryUrl !== null && (_jsx("button", { type: "button", className: "ah-iconbtn", title: `Open ${repositoryUrl}`, "aria-label": "Open the git repository", onClick: () => window.open(repositoryUrl.includes("://")
69
+ ? repositoryUrl
70
+ : `https://${repositoryUrl}`), children: _jsx(GitHubGlyph, {}) })), hostActs?.map((act) => _jsx(HostAct, { act: act, place: "head" }, act.key))] })] }), isExpanded && (_jsxs("div", { className: "ah-meta__body ah-veilhost", children: [isVeiled && (_jsx(Veil, { label: ingestActive
71
+ ? censusRunning ? "Discovering conversations…" : "Preparing activity summaries…"
72
+ : "Loading activity summaries…", progress: null })), _jsx(SummaryMetrics, { sessionCount: project.rootSessionCount, messageCount: project.lifetimeMessages, tokenCount: project.tokensLast53Weeks, spend: project.spendLast53Weeks, pending: isVeiled, period: "53 weeks" }), _jsxs("div", { className: "ah-chartcard", children: [_jsx(SegmentedControl, { value: activeChart, options: PROJECT_CHART_OPTIONS, accessibleLabel: "Project chart", className: "ah-tabseg", onValueChange: setActiveChart }), _jsx("div", { className: "ah-tabbody", children: activeChart === "models" ? (_jsxs("div", { className: "ah-chart-launcher ah-chart-launcher--models", children: [_jsx(Streamgraph, { data: modelUsageData, title: "Tokens per day \u00B7 30 days", note: "no zero \u00B7 thickness is the total", ariaLabel: "Tokens per day by model over 30 days, shown as a wiggle-minimised streamgraph", emptyMessage: usage ? "No model-attributed usage in this window" : "Loading model usage…", formatValue: tokenText }), _jsx("button", { type: "button", className: "ah-chart-launcher__button", "aria-label": `Expand models chart for ${project.row.name}`, "aria-haspopup": "dialog", disabled: isVeiled || usage === null, onClick: () => setExpandedChart("models"), children: _jsxs("span", { className: "ah-chart-launcher__hint", children: [_jsx(FullscreenGlyph, {}), " Expand"] }) })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ah-chart-launcher", children: [_jsx(CalendarHeatmap, { data: heatmapData, color: project.tint, ariaLabel: `Daily token activity for ${project.row.name} over 53 weeks`, summary: `${isVeiled && activityStats.activeDayCount === 0
73
+ ? "—"
74
+ : activityStats.activeDayCount} active days · 53 weeks` }), _jsx("button", { type: "button", className: "ah-chart-launcher__button", "aria-label": `Expand activity chart for ${project.row.name}`, "aria-haspopup": "dialog", disabled: isVeiled, onClick: () => setExpandedChart("activity"), children: _jsxs("span", { className: "ah-chart-launcher__hint", children: [_jsx(FullscreenGlyph, {}), " Expand"] }) })] }), _jsxs("p", { className: "ah-meta__facts", children: [_jsx("b", { children: isVeiled && activityStats.longestStreakLength === 0
75
+ ? "—"
76
+ : `${activityStats.currentStreakLength}d` }), " ", "streak \u00B7", " ", _jsx("b", { children: isVeiled && activityStats.longestStreakLength === 0
77
+ ? "—"
78
+ : `${activityStats.longestStreakLength}d` }), " ", "best", peakHour !== null && (_jsxs(_Fragment, { children: [" ", "\u00B7 peak ", _jsx("b", { children: formatHourLabel(peakHour) })] })), primaryModelLabel !== null && (_jsxs(_Fragment, { children: [" ", "\u00B7 mostly ", _jsx("b", { children: primaryModelLabel })] }))] })] })) })] })] })), expandedChart && _jsx(ProjectChartDialog, { projectId: project.row.id, name: project.row.name, color: project.tint, initialView: expandedChart, usage: usage, data: heatmapData, today: getCalendarDayKey(currentTimestamp), offsetMinutes: getViewerUtcOffsetMinutes(), currentTimestamp: currentTimestamp, modelColors: modelColors, onClose: () => setExpandedChart(null) })] }));
79
+ }
80
+ export function PortfolioSummaryPanel({ projects, selectedProjectId, ingestActive, censusRunning, onProjectSelect, }) {
81
+ const [isExpanded, setIsExpanded] = useState(true);
82
+ const summariesPending = ingestActive || projects.some((project) => !project.statsReady);
83
+ const summary = useMemo(() => {
84
+ // Match the project list's lifetime spend ranking, tokens breaking ties.
85
+ const treemapProjects = [...projects]
86
+ .filter((project) => (project.lifetimeSpend.costMicroUsd ?? 0) > 0)
87
+ .sort((left, right) => (right.lifetimeSpend.costMicroUsd ?? 0) - (left.lifetimeSpend.costMicroUsd ?? 0)
88
+ || right.lifetimeTokens - left.lifetimeTokens)
89
+ .slice(0, MAX_TREEMAP_PROJECT_COUNT);
90
+ const treemapData = {
91
+ items: treemapProjects.map((project) => ({
92
+ id: project.row.id,
93
+ label: project.row.name,
94
+ value: project.lifetimeSpend.costMicroUsd ?? 0,
95
+ color: project.tint,
96
+ // A lower bound when part of the project's usage has no list price or
97
+ // no recorded output (§4.1.3: partial coverage is always visible).
98
+ partial: coverage(project.lifetimeSpend) === "partial",
99
+ })),
100
+ };
101
+ // Projects the treemap cannot size: usage, none of it priced.
102
+ const unpricedOnlyProjects = projects.filter((project) => coverage(project.lifetimeSpend) === "unavailable").length;
103
+ return {
104
+ unpricedOnlyProjects,
105
+ sessionCount: projects.reduce((total, project) => total + project.rootSessionCount, 0),
106
+ messageCount: projects.reduce((total, project) => total + project.lifetimeMessages, 0),
107
+ tokenCount: projects.reduce((total, project) => total + project.lifetimeTokens, 0),
108
+ spend: projects.reduce((total, project) => addSpend(total, project.lifetimeSpend), NO_SPEND),
109
+ treemapData,
110
+ };
111
+ }, [projects]);
112
+ return (_jsxs("div", { className: "ah-meta", children: [_jsxs("div", { className: "ah-meta__head", children: [_jsx(ColumnHeading, { name: "Projects", tint: "var(--vf-text-tertiary)", title: null, count: projects.length, countTitle: `${projects.length} projects in this list` }), _jsx("span", { className: "ah-meta__acts", children: _jsx("button", { type: "button", className: "ah-iconbtn", "aria-pressed": isExpanded, title: isExpanded ? "Hide the figures" : "Show the figures", "aria-label": "Toggle the figures", onClick: () => setIsExpanded((current) => !current), children: _jsx(StatsGlyph, {}) }) })] }), isExpanded && (_jsxs("div", { className: "ah-meta__body ah-veilhost", children: [summariesPending && (_jsx(Veil, { label: ingestActive
113
+ ? censusRunning ? "Discovering conversations…" : "Preparing activity summaries…"
114
+ : "Loading activity summaries…", progress: null })), _jsx(SummaryMetrics, { sessionCount: summary.sessionCount, messageCount: summary.messageCount, tokenCount: summary.tokenCount, spend: summary.spend, pending: summariesPending, period: "all time" }), _jsxs("div", { className: "ah-chartcard", children: [_jsx(Treemap, { data: summary.treemapData, ariaLabel: "Top projects by lifetime estimated spend, where area represents share among displayed projects", emptyMessage: "No priced project usage", showFooter: false, height: SUMMARY_CHART_CONTENT_HEIGHT, minimumVisibleShare: 0, selectedItemId: selectedProjectId, onItemSelect: (item) => onProjectSelect(item.id), formatValue: usdText, getItemAccessibleLabel: (item, context) => `${item.label} · ${usdText(item.value)}${item.partial ? "+" : ""} estimated cost${item.partial ? " (a lower bound)" : ""} · ${(context.share * 100).toFixed(1)}% of displayed lifetime spend` }), summary.unpricedOnlyProjects > 0 && (_jsx("p", { className: "ah-treemap__empty", children: summary.unpricedOnlyProjects === 1
115
+ ? "1 project has usage with no list price and is not shown"
116
+ : `${summary.unpricedOnlyProjects} projects have usage with no list price and are not shown` }))] })] }))] }));
117
+ }