@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.
- package/README.md +247 -2
- package/dist/HistoryRoom.d.ts +98 -0
- package/dist/HistoryRoom.js +440 -0
- package/dist/TranscriptReader.d.ts +22 -0
- package/dist/TranscriptReader.js +72 -0
- package/dist/components/ColdStart.d.ts +4 -0
- package/dist/components/ColdStart.js +5 -0
- package/dist/components/FilterChips.d.ts +4 -0
- package/dist/components/FilterChips.js +5 -0
- package/dist/components/HostAct.d.ts +9 -0
- package/dist/components/HostAct.js +16 -0
- package/dist/components/HostMenu.d.ts +41 -0
- package/dist/components/HostMenu.js +216 -0
- package/dist/components/IngestStatus.d.ts +4 -0
- package/dist/components/IngestStatus.js +20 -0
- package/dist/components/ListActivityNotice.d.ts +5 -0
- package/dist/components/ListActivityNotice.js +4 -0
- package/dist/components/ListSections.d.ts +20 -0
- package/dist/components/ListSections.js +39 -0
- package/dist/components/RenameHeading.d.ts +9 -0
- package/dist/components/RenameHeading.js +75 -0
- package/dist/components/SearchStrip.d.ts +5 -0
- package/dist/components/SearchStrip.js +8 -0
- package/dist/components/SummaryMetrics.d.ts +13 -0
- package/dist/components/SummaryMetrics.js +9 -0
- package/dist/components/SummaryPanels.d.ts +35 -0
- package/dist/components/SummaryPanels.js +117 -0
- package/dist/components/Transcript.d.ts +46 -0
- package/dist/components/Transcript.js +358 -0
- package/dist/components/charts/ActivityChartDetail.d.ts +13 -0
- package/dist/components/charts/ActivityChartDetail.js +78 -0
- package/dist/components/charts/CalendarHeatmap.d.ts +16 -0
- package/dist/components/charts/CalendarHeatmap.js +55 -0
- package/dist/components/charts/DayActivityChart.d.ts +8 -0
- package/dist/components/charts/DayActivityChart.js +71 -0
- package/dist/components/charts/ModelsChartDetail.d.ts +7 -0
- package/dist/components/charts/ModelsChartDetail.js +19 -0
- package/dist/components/charts/ProjectChartDialog.d.ts +19 -0
- package/dist/components/charts/ProjectChartDialog.js +39 -0
- package/dist/components/charts/Streamgraph.d.ts +16 -0
- package/dist/components/charts/Streamgraph.js +94 -0
- package/dist/components/charts/Treemap.d.ts +26 -0
- package/dist/components/charts/Treemap.js +81 -0
- package/dist/components/charts/index.d.ts +9 -0
- package/dist/components/charts/index.js +4 -0
- package/dist/components/charts/streamgraph-layout.d.ts +23 -0
- package/dist/components/charts/streamgraph-layout.js +114 -0
- package/dist/components/charts/treemap-layout.d.ts +32 -0
- package/dist/components/charts/treemap-layout.js +140 -0
- package/dist/components/charts/types.d.ts +65 -0
- package/dist/components/charts/types.js +8 -0
- package/dist/components/file-viewer/FileViewerBrowsers.d.ts +10 -0
- package/dist/components/file-viewer/FileViewerBrowsers.js +65 -0
- package/dist/components/file-viewer/FileViewerDialog.d.ts +33 -0
- package/dist/components/file-viewer/FileViewerDialog.js +82 -0
- package/dist/components/file-viewer/FileViewerHeader.d.ts +26 -0
- package/dist/components/file-viewer/FileViewerHeader.js +17 -0
- package/dist/components/file-viewer/ImageGalleryDialog.d.ts +14 -0
- package/dist/components/file-viewer/ImageGalleryDialog.js +98 -0
- package/dist/components/file-viewer/diff/index.d.ts +2 -0
- package/dist/components/file-viewer/diff/index.js +2 -0
- package/dist/components/file-viewer/diff/parse.d.ts +2 -0
- package/dist/components/file-viewer/diff/parse.js +164 -0
- package/dist/components/file-viewer/diff/types.d.ts +44 -0
- package/dist/components/file-viewer/diff/types.js +7 -0
- package/dist/components/file-viewer/gallery-source.d.ts +11 -0
- package/dist/components/file-viewer/gallery-source.js +75 -0
- package/dist/components/file-viewer/image-resource.d.ts +19 -0
- package/dist/components/file-viewer/image-resource.js +60 -0
- package/dist/components/file-viewer/index.d.ts +5 -0
- package/dist/components/file-viewer/index.js +8 -0
- package/dist/components/file-viewer/markdown/blocks.d.ts +2 -0
- package/dist/components/file-viewer/markdown/blocks.js +277 -0
- package/dist/components/file-viewer/markdown/index.d.ts +4 -0
- package/dist/components/file-viewer/markdown/index.js +35 -0
- package/dist/components/file-viewer/markdown/inline.d.ts +10 -0
- package/dist/components/file-viewer/markdown/inline.js +178 -0
- package/dist/components/file-viewer/markdown/render.d.ts +9 -0
- package/dist/components/file-viewer/markdown/render.js +78 -0
- package/dist/components/file-viewer/markdown/types.d.ts +57 -0
- package/dist/components/file-viewer/markdown/types.js +11 -0
- package/dist/components/file-viewer/minimap/CodeMinimap.d.ts +10 -0
- package/dist/components/file-viewer/minimap/CodeMinimap.js +296 -0
- package/dist/components/file-viewer/minimap/layout.d.ts +60 -0
- package/dist/components/file-viewer/minimap/layout.js +117 -0
- package/dist/components/file-viewer/minimap/palette.d.ts +2 -0
- package/dist/components/file-viewer/minimap/palette.js +73 -0
- package/dist/components/file-viewer/minimap/raster.d.ts +19 -0
- package/dist/components/file-viewer/minimap/raster.js +122 -0
- package/dist/components/file-viewer/registry.d.ts +25 -0
- package/dist/components/file-viewer/registry.js +182 -0
- package/dist/components/file-viewer/syntax/grammars.d.ts +16 -0
- package/dist/components/file-viewer/syntax/grammars.js +221 -0
- package/dist/components/file-viewer/syntax/index.d.ts +8 -0
- package/dist/components/file-viewer/syntax/index.js +9 -0
- package/dist/components/file-viewer/syntax/languages.d.ts +14 -0
- package/dist/components/file-viewer/syntax/languages.js +115 -0
- package/dist/components/file-viewer/syntax/tokenize-config.d.ts +2 -0
- package/dist/components/file-viewer/syntax/tokenize-config.js +132 -0
- package/dist/components/file-viewer/syntax/tokenize-css.d.ts +2 -0
- package/dist/components/file-viewer/syntax/tokenize-css.js +169 -0
- package/dist/components/file-viewer/syntax/tokenize-markup.d.ts +2 -0
- package/dist/components/file-viewer/syntax/tokenize-markup.js +124 -0
- package/dist/components/file-viewer/syntax/tokenize.d.ts +9 -0
- package/dist/components/file-viewer/syntax/tokenize.js +289 -0
- package/dist/components/file-viewer/syntax/types.d.ts +74 -0
- package/dist/components/file-viewer/syntax/types.js +13 -0
- package/dist/components/file-viewer/types.d.ts +111 -0
- package/dist/components/file-viewer/types.js +8 -0
- package/dist/components/file-viewer/use-file-content.d.ts +26 -0
- package/dist/components/file-viewer/use-file-content.js +144 -0
- package/dist/components/file-viewer/views/BinaryView.d.ts +2 -0
- package/dist/components/file-viewer/views/BinaryView.js +34 -0
- package/dist/components/file-viewer/views/CodeView.d.ts +2 -0
- package/dist/components/file-viewer/views/CodeView.js +46 -0
- package/dist/components/file-viewer/views/DiffBody.d.ts +7 -0
- package/dist/components/file-viewer/views/DiffBody.js +77 -0
- package/dist/components/file-viewer/views/DiffView.d.ts +2 -0
- package/dist/components/file-viewer/views/DiffView.js +11 -0
- package/dist/components/file-viewer/views/ImageView.d.ts +9 -0
- package/dist/components/file-viewer/views/ImageView.js +28 -0
- package/dist/components/file-viewer/views/MarkdownView.d.ts +9 -0
- package/dist/components/file-viewer/views/MarkdownView.js +20 -0
- package/dist/components/file-viewer/views/SvgView.d.ts +9 -0
- package/dist/components/file-viewer/views/SvgView.js +10 -0
- package/dist/components/git/ChangeTree.d.ts +20 -0
- package/dist/components/git/ChangeTree.js +35 -0
- package/dist/components/git/CommitViewer.d.ts +12 -0
- package/dist/components/git/CommitViewer.js +85 -0
- package/dist/components/git/GitChanges.d.ts +17 -0
- package/dist/components/git/GitChanges.js +70 -0
- package/dist/components/git/GitHistory.d.ts +9 -0
- package/dist/components/git/GitHistory.js +58 -0
- package/dist/components/git/co-author.d.ts +14 -0
- package/dist/components/git/co-author.js +55 -0
- package/dist/components/git/git-file-source.d.ts +18 -0
- package/dist/components/git/git-file-source.js +53 -0
- package/dist/components/git/git-host.d.ts +24 -0
- package/dist/components/git/git-host.js +130 -0
- package/dist/components/git/index.d.ts +10 -0
- package/dist/components/git/index.js +12 -0
- package/dist/components/git/path-tree.d.ts +23 -0
- package/dist/components/git/path-tree.js +73 -0
- package/dist/components/git/session-files.d.ts +9 -0
- package/dist/components/git/session-files.js +50 -0
- package/dist/components/git/types.d.ts +92 -0
- package/dist/components/git/types.js +9 -0
- package/dist/components/projects/ProjectActivitySparkline.d.ts +6 -0
- package/dist/components/projects/ProjectActivitySparkline.js +12 -0
- package/dist/components/projects/ProjectList.d.ts +25 -0
- package/dist/components/projects/ProjectList.js +43 -0
- package/dist/components/projects/ProjectListItem.d.ts +19 -0
- package/dist/components/projects/ProjectListItem.js +78 -0
- package/dist/components/projects/ProjectsColumn.d.ts +19 -0
- package/dist/components/projects/ProjectsColumn.js +36 -0
- package/dist/components/projects/index.d.ts +8 -0
- package/dist/components/projects/index.js +4 -0
- package/dist/components/search/MatchStepper.d.ts +9 -0
- package/dist/components/search/MatchStepper.js +14 -0
- package/dist/components/search/SearchLauncher.d.ts +12 -0
- package/dist/components/search/SearchLauncher.js +13 -0
- package/dist/components/search/SearchSheet.d.ts +29 -0
- package/dist/components/search/SearchSheet.js +230 -0
- package/dist/components/search/index.d.ts +8 -0
- package/dist/components/search/index.js +4 -0
- package/dist/components/search/shortcut.d.ts +25 -0
- package/dist/components/search/shortcut.js +32 -0
- package/dist/components/sessions/SessionList.d.ts +24 -0
- package/dist/components/sessions/SessionList.js +76 -0
- package/dist/components/sessions/SessionListItem.d.ts +13 -0
- package/dist/components/sessions/SessionListItem.js +58 -0
- package/dist/components/sessions/SessionsColumn.d.ts +26 -0
- package/dist/components/sessions/SessionsColumn.js +32 -0
- package/dist/components/sessions/index.d.ts +9 -0
- package/dist/components/sessions/index.js +4 -0
- package/dist/components/sessions/session-display.d.ts +8 -0
- package/dist/components/sessions/session-display.js +18 -0
- package/dist/components/sessions/types.d.ts +7 -0
- package/dist/components/sessions/types.js +1 -0
- package/dist/components/transcript/Activity.d.ts +45 -0
- package/dist/components/transcript/Activity.js +75 -0
- package/dist/components/transcript/Anchor.d.ts +8 -0
- package/dist/components/transcript/Anchor.js +23 -0
- package/dist/components/transcript/Attachments.d.ts +21 -0
- package/dist/components/transcript/Attachments.js +138 -0
- package/dist/components/transcript/AuthoredMessage.d.ts +19 -0
- package/dist/components/transcript/AuthoredMessage.js +17 -0
- package/dist/components/transcript/Compaction.d.ts +9 -0
- package/dist/components/transcript/Compaction.js +50 -0
- package/dist/components/transcript/DayPill.d.ts +38 -0
- package/dist/components/transcript/DayPill.js +68 -0
- package/dist/components/transcript/Document.d.ts +32 -0
- package/dist/components/transcript/Document.js +503 -0
- package/dist/components/transcript/Favicon.d.ts +32 -0
- package/dist/components/transcript/Favicon.js +71 -0
- package/dist/components/transcript/HeadOfDocument.d.ts +19 -0
- package/dist/components/transcript/HeadOfDocument.js +44 -0
- package/dist/components/transcript/Ledger.d.ts +53 -0
- package/dist/components/transcript/Ledger.js +182 -0
- package/dist/components/transcript/LineDetail.d.ts +24 -0
- package/dist/components/transcript/LineDetail.js +81 -0
- package/dist/components/transcript/Marker.d.ts +33 -0
- package/dist/components/transcript/Marker.js +21 -0
- package/dist/components/transcript/MessagePreview.d.ts +12 -0
- package/dist/components/transcript/MessagePreview.js +58 -0
- package/dist/components/transcript/Prompt.d.ts +20 -0
- package/dist/components/transcript/Prompt.js +55 -0
- package/dist/components/transcript/Prose.d.ts +19 -0
- package/dist/components/transcript/Prose.js +109 -0
- package/dist/components/transcript/ReceiptPill.d.ts +10 -0
- package/dist/components/transcript/ReceiptPill.js +10 -0
- package/dist/components/transcript/ResponseHead.d.ts +9 -0
- package/dist/components/transcript/ResponseHead.js +36 -0
- package/dist/components/transcript/Subthread.d.ts +19 -0
- package/dist/components/transcript/Subthread.js +96 -0
- package/dist/components/transcript/Team.d.ts +53 -0
- package/dist/components/transcript/Team.js +185 -0
- package/dist/components/transcript/Thinking.d.ts +24 -0
- package/dist/components/transcript/Thinking.js +50 -0
- package/dist/components/transcript/TimelineMeta.d.ts +9 -0
- package/dist/components/transcript/TimelineMeta.js +161 -0
- package/dist/components/transcript/TranscriptLoading.d.ts +10 -0
- package/dist/components/transcript/TranscriptLoading.js +10 -0
- package/dist/components/transcript/WebDetail.d.ts +8 -0
- package/dist/components/transcript/WebDetail.js +29 -0
- package/dist/components/transcript/Workflow.d.ts +12 -0
- package/dist/components/transcript/Workflow.js +208 -0
- package/dist/components/transcript/activity-plan.d.ts +84 -0
- package/dist/components/transcript/activity-plan.js +209 -0
- package/dist/components/transcript/attachment-file-source.d.ts +23 -0
- package/dist/components/transcript/attachment-file-source.js +103 -0
- package/dist/components/transcript/attachment-gallery.d.ts +12 -0
- package/dist/components/transcript/attachment-gallery.js +33 -0
- package/dist/components/transcript/detail-parts.d.ts +50 -0
- package/dist/components/transcript/detail-parts.js +295 -0
- package/dist/components/transcript/disclosure-state.d.ts +6 -0
- package/dist/components/transcript/disclosure-state.js +32 -0
- package/dist/components/transcript/disclosure-store.d.ts +8 -0
- package/dist/components/transcript/disclosure-store.js +31 -0
- package/dist/components/transcript/document-model.d.ts +15 -0
- package/dist/components/transcript/document-model.js +104 -0
- package/dist/components/transcript/document-plan.d.ts +28 -0
- package/dist/components/transcript/document-plan.js +145 -0
- package/dist/components/transcript/fold-preference.d.ts +17 -0
- package/dist/components/transcript/fold-preference.js +63 -0
- package/dist/components/transcript/glyphs.d.ts +15 -0
- package/dist/components/transcript/glyphs.js +47 -0
- package/dist/components/transcript/index.d.ts +23 -0
- package/dist/components/transcript/index.js +22 -0
- package/dist/components/transcript/message-file-source.d.ts +15 -0
- package/dist/components/transcript/message-file-source.js +31 -0
- package/dist/components/transcript/message-preview.d.ts +9 -0
- package/dist/components/transcript/message-preview.js +46 -0
- package/dist/components/transcript/read-file-source.d.ts +7 -0
- package/dist/components/transcript/read-file-source.js +34 -0
- package/dist/components/transcript/reader-context.d.ts +13 -0
- package/dist/components/transcript/reader-context.js +55 -0
- package/dist/components/transcript/reading-identity.d.ts +2 -0
- package/dist/components/transcript/reading-identity.js +52 -0
- package/dist/components/transcript/scroll-to-row.d.ts +2 -0
- package/dist/components/transcript/scroll-to-row.js +13 -0
- package/dist/components/transcript/thread-index.d.ts +14 -0
- package/dist/components/transcript/thread-index.js +40 -0
- package/dist/components/transcript/thread-navigation.d.ts +5 -0
- package/dist/components/transcript/thread-navigation.js +3 -0
- package/dist/components/transcript/timeline-meta-file-source.d.ts +6 -0
- package/dist/components/transcript/timeline-meta-file-source.js +55 -0
- package/dist/components/transcript/timeline-meta-state.d.ts +12 -0
- package/dist/components/transcript/timeline-meta-state.js +24 -0
- package/dist/components/ui/ColumnHeading.d.ts +27 -0
- package/dist/components/ui/ColumnHeading.js +7 -0
- package/dist/components/ui/ConfirmDialog.d.ts +14 -0
- package/dist/components/ui/ConfirmDialog.js +22 -0
- package/dist/components/ui/DialogShell.d.ts +18 -0
- package/dist/components/ui/DialogShell.js +40 -0
- package/dist/components/ui/EmptyState.d.ts +10 -0
- package/dist/components/ui/EmptyState.js +6 -0
- package/dist/components/ui/ListSummaryHeader.d.ts +9 -0
- package/dist/components/ui/ListSummaryHeader.js +6 -0
- package/dist/components/ui/ListToolbar.d.ts +6 -0
- package/dist/components/ui/ListToolbar.js +5 -0
- package/dist/components/ui/ResultGroupHeader.d.ts +9 -0
- package/dist/components/ui/ResultGroupHeader.js +5 -0
- package/dist/components/ui/SegmentedControl.d.ts +16 -0
- package/dist/components/ui/SegmentedControl.js +9 -0
- package/dist/components/ui/SummaryMetric.d.ts +13 -0
- package/dist/components/ui/SummaryMetric.js +10 -0
- package/dist/components/ui/Veil.d.ts +7 -0
- package/dist/components/ui/Veil.js +5 -0
- package/dist/components/ui/index.d.ts +20 -0
- package/dist/components/ui/index.js +10 -0
- package/dist/components/worktree/WorktreeColumn.d.ts +22 -0
- package/dist/components/worktree/WorktreeColumn.js +170 -0
- package/dist/components/worktree/WorktreeFileTree.d.ts +19 -0
- package/dist/components/worktree/WorktreeFileTree.js +60 -0
- package/dist/components/worktree/WorktreeHeader.d.ts +32 -0
- package/dist/components/worktree/WorktreeHeader.js +81 -0
- package/dist/components/worktree/WorktreeList.d.ts +8 -0
- package/dist/components/worktree/WorktreeList.js +12 -0
- package/dist/components/worktree/index.d.ts +12 -0
- package/dist/components/worktree/index.js +7 -0
- package/dist/components/worktree/types.d.ts +17 -0
- package/dist/components/worktree/types.js +3 -0
- package/dist/components/worktree/use-worktree-guest.d.ts +21 -0
- package/dist/components/worktree/use-worktree-guest.js +92 -0
- package/dist/components/worktree/worktree-file-commands.d.ts +19 -0
- package/dist/components/worktree/worktree-file-commands.js +112 -0
- package/dist/components/worktree/worktree-file-source.d.ts +15 -0
- package/dist/components/worktree/worktree-file-source.js +75 -0
- package/dist/components/worktree/worktree-host.d.ts +31 -0
- package/dist/components/worktree/worktree-host.js +242 -0
- package/dist/fixtures/index.d.ts +24 -0
- package/dist/fixtures/index.js +292 -0
- package/dist/host-inputs.d.ts +231 -0
- package/dist/host-inputs.js +35 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +14 -0
- package/dist/lib/activity-details.d.ts +23 -0
- package/dist/lib/activity-details.js +78 -0
- package/dist/lib/activity-order.d.ts +32 -0
- package/dist/lib/activity-order.js +86 -0
- package/dist/lib/agent-paths.d.ts +6 -0
- package/dist/lib/agent-paths.js +19 -0
- package/dist/lib/agents.d.ts +15 -0
- package/dist/lib/agents.js +60 -0
- package/dist/lib/catalog-status.d.ts +3 -0
- package/dist/lib/catalog-status.js +10 -0
- package/dist/lib/chart-data.d.ts +14 -0
- package/dist/lib/chart-data.js +151 -0
- package/dist/lib/day-activity.d.ts +21 -0
- package/dist/lib/day-activity.js +56 -0
- package/dist/lib/format.d.ts +24 -0
- package/dist/lib/format.js +116 -0
- package/dist/lib/hooks.d.ts +118 -0
- package/dist/lib/hooks.js +608 -0
- package/dist/lib/icons.d.ts +21 -0
- package/dist/lib/icons.js +49 -0
- package/dist/lib/image-media.d.ts +6 -0
- package/dist/lib/image-media.js +30 -0
- package/dist/lib/ingest-activity.d.ts +50 -0
- package/dist/lib/ingest-activity.js +151 -0
- package/dist/lib/ingest.d.ts +25 -0
- package/dist/lib/ingest.js +70 -0
- package/dist/lib/model-labels.d.ts +5 -0
- package/dist/lib/model-labels.js +28 -0
- package/dist/lib/model.d.ts +73 -0
- package/dist/lib/model.js +141 -0
- package/dist/lib/motion.d.ts +13 -0
- package/dist/lib/motion.js +80 -0
- package/dist/lib/room-storage.d.ts +13 -0
- package/dist/lib/room-storage.js +40 -0
- package/dist/lib/search-results.d.ts +27 -0
- package/dist/lib/search-results.js +83 -0
- package/dist/lib/search-sheet.d.ts +119 -0
- package/dist/lib/search-sheet.js +282 -0
- package/dist/lib/sections.d.ts +19 -0
- package/dist/lib/sections.js +36 -0
- package/dist/lib/session-activity.d.ts +5 -0
- package/dist/lib/session-activity.js +15 -0
- package/dist/lib/session-leases.d.ts +15 -0
- package/dist/lib/session-leases.js +61 -0
- package/dist/lib/spend.d.ts +42 -0
- package/dist/lib/spend.js +112 -0
- package/dist/lib/tint.d.ts +9 -0
- package/dist/lib/tint.js +53 -0
- package/dist/lib/transcript/collaboration.d.ts +97 -0
- package/dist/lib/transcript/collaboration.js +423 -0
- package/dist/lib/transcript/families.d.ts +212 -0
- package/dist/lib/transcript/families.js +906 -0
- package/dist/lib/transcript/favicons.d.ts +54 -0
- package/dist/lib/transcript/favicons.js +183 -0
- package/dist/lib/transcript/head-of-document.d.ts +27 -0
- package/dist/lib/transcript/head-of-document.js +274 -0
- package/dist/lib/transcript/head-state.d.ts +182 -0
- package/dist/lib/transcript/head-state.js +305 -0
- package/dist/lib/transcript/history-window.d.ts +13 -0
- package/dist/lib/transcript/history-window.js +52 -0
- package/dist/lib/transcript/images.d.ts +8 -0
- package/dist/lib/transcript/images.js +60 -0
- package/dist/lib/transcript/index.d.ts +15 -0
- package/dist/lib/transcript/index.js +8 -0
- package/dist/lib/transcript/ledger.d.ts +143 -0
- package/dist/lib/transcript/ledger.js +513 -0
- package/dist/lib/transcript/protocol.d.ts +23 -0
- package/dist/lib/transcript/protocol.js +1 -0
- package/dist/lib/transcript/sittings.d.ts +75 -0
- package/dist/lib/transcript/sittings.js +147 -0
- package/dist/lib/transcript/tail-scroll.d.ts +36 -0
- package/dist/lib/transcript/tail-scroll.js +167 -0
- package/dist/lib/transcript/tail-state.d.ts +17 -0
- package/dist/lib/transcript/tail-state.js +30 -0
- package/dist/lib/transcript/turns.d.ts +192 -0
- package/dist/lib/transcript/turns.js +576 -0
- package/dist/lib/transcript/use-transcript-opening.d.ts +12 -0
- package/dist/lib/transcript/use-transcript-opening.js +31 -0
- package/dist/lib/transcript/use-transcript-tail.d.ts +25 -0
- package/dist/lib/transcript/use-transcript-tail.js +158 -0
- package/dist/lib/transcript/vocabulary.d.ts +119 -0
- package/dist/lib/transcript/vocabulary.js +293 -0
- package/dist/lib/transcript/web-address.d.ts +6 -0
- package/dist/lib/transcript/web-address.js +18 -0
- package/dist/lib/transcript/workflow.d.ts +31 -0
- package/dist/lib/transcript/workflow.js +133 -0
- package/dist/lib/use-activity-order.d.ts +2 -0
- package/dist/lib/use-activity-order.js +23 -0
- package/dist/lib/use-day-usage.d.ts +8 -0
- package/dist/lib/use-day-usage.js +31 -0
- package/dist/lib/use-deferred-list-order.d.ts +26 -0
- package/dist/lib/use-deferred-list-order.js +142 -0
- package/dist/lib/use-ingest-activity.d.ts +2 -0
- package/dist/lib/use-ingest-activity.js +49 -0
- package/dist/lib/use-list-motion.d.ts +4 -0
- package/dist/lib/use-list-motion.js +67 -0
- package/dist/ports.d.ts +222 -0
- package/dist/ports.js +3 -0
- package/dist/room-context.d.ts +60 -0
- package/dist/room-context.js +87 -0
- package/dist/styles/activity-chart.css +127 -0
- package/dist/styles/attachments.css +29 -0
- package/dist/styles/favicon.css +73 -0
- package/dist/styles/history-room.css +18 -0
- package/dist/styles/host-inputs.css +250 -0
- package/dist/styles/image-gallery.css +30 -0
- package/dist/styles/ingest.css +51 -0
- package/dist/styles/message-preview.css +34 -0
- package/dist/styles/models-chart.css +66 -0
- package/dist/styles/project-chart.css +19 -0
- package/dist/styles/reader.css +33 -0
- package/dist/styles/room.css +1411 -0
- package/dist/styles/search.css +252 -0
- package/dist/styles/transcript-activity.css +70 -0
- package/dist/styles/transcript-head.css +220 -0
- package/dist/styles/transcript-loading.css +57 -0
- package/dist/styles/transcript.css +1226 -0
- package/package.json +61 -4
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
// The room's data spine: one meta subscription for who/what exists, REST for
|
|
2
|
+
// figures, and one session subscription for the transcript being read. Every
|
|
3
|
+
// hook reads through the port it is handed; none of them dials anything.
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { CursorExpiredError } from "@vibefield/rosetta-protocol";
|
|
6
|
+
import { getActivityGridStartTimestamp, getViewerUtcOffsetMinutes } from "./model.js";
|
|
7
|
+
import { conversationStart, readConversationPage } from "./transcript/history-window.js";
|
|
8
|
+
import { EARLIER_FAILED_MESSAGE, EARLIER_PAGE_SIZE, earlierAboveOf, earlierState, initialEarlierModel, reduceEarlier, } from "./transcript/head-state.js";
|
|
9
|
+
export function useMeta(catalog) {
|
|
10
|
+
const [feed, setFeed] = useState({
|
|
11
|
+
meta: null, snapshotVersion: 0,
|
|
12
|
+
});
|
|
13
|
+
const [status, setStatus] = useState("connecting");
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const sub = catalog.subscribeMeta({
|
|
17
|
+
onChange: (meta, source) => {
|
|
18
|
+
setFeed((previous) => ({
|
|
19
|
+
meta,
|
|
20
|
+
snapshotVersion: previous.snapshotVersion + (source === "snapshot" ? 1 : 0),
|
|
21
|
+
}));
|
|
22
|
+
setError(null);
|
|
23
|
+
},
|
|
24
|
+
onStatus: setStatus,
|
|
25
|
+
onError: setError,
|
|
26
|
+
});
|
|
27
|
+
return () => sub.close();
|
|
28
|
+
}, [catalog]);
|
|
29
|
+
return { ...feed, status, error };
|
|
30
|
+
}
|
|
31
|
+
/** The daemon's status surface. It answers from the daemon's first breath —
|
|
32
|
+
* before the projection is even readable — so it is the room's connectivity
|
|
33
|
+
* truth during a cold start. Polls fast through canonical publication and
|
|
34
|
+
* search preparation, then quietly once both are ready. */
|
|
35
|
+
export function useDaemonStatus(catalog) {
|
|
36
|
+
const [connectionRevision, setConnectionRevision] = useState(0);
|
|
37
|
+
useEffect(() => catalog.onConnectionChange?.(() => setConnectionRevision((value) => value + 1)), [catalog]);
|
|
38
|
+
const [feed, setFeed] = useState({
|
|
39
|
+
connectionError: null,
|
|
40
|
+
canonicalReady: null,
|
|
41
|
+
searchReadiness: null,
|
|
42
|
+
ingest: null,
|
|
43
|
+
searchProgress: null,
|
|
44
|
+
startedAt: null,
|
|
45
|
+
uptimeMs: 0,
|
|
46
|
+
receivedAt: null,
|
|
47
|
+
});
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
let cancelled = false;
|
|
50
|
+
let controller;
|
|
51
|
+
let timer;
|
|
52
|
+
let deadline;
|
|
53
|
+
const poll = async () => {
|
|
54
|
+
const request = new AbortController();
|
|
55
|
+
controller = request;
|
|
56
|
+
let delay = 1_000;
|
|
57
|
+
deadline = window.setTimeout(() => request.abort(), 5_000);
|
|
58
|
+
try {
|
|
59
|
+
const status = await catalog.status(request.signal);
|
|
60
|
+
if (cancelled)
|
|
61
|
+
return;
|
|
62
|
+
setFeed({
|
|
63
|
+
connectionError: null,
|
|
64
|
+
canonicalReady: status.canonicalReady,
|
|
65
|
+
searchReadiness: status.searchReadiness,
|
|
66
|
+
ingest: status.ingest,
|
|
67
|
+
searchProgress: status.searchProgress,
|
|
68
|
+
startedAt: status.startedAt,
|
|
69
|
+
uptimeMs: status.uptimeMs,
|
|
70
|
+
receivedAt: Date.now(),
|
|
71
|
+
});
|
|
72
|
+
const phase = status.ingest?.phase;
|
|
73
|
+
// Keep search visible after canonical publication. Audit/consent are
|
|
74
|
+
// intentional pauses; an unanswered first request retries promptly.
|
|
75
|
+
const paused = phase === "metadata_ready" || phase === "awaiting_consent";
|
|
76
|
+
const complete = status.canonicalReady && status.searchReadiness === "ready";
|
|
77
|
+
delay = complete ? 30_000 : paused ? 2_500 : 500;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (!cancelled)
|
|
81
|
+
setFeed((previous) => ({
|
|
82
|
+
...previous,
|
|
83
|
+
connectionError: catalog.unavailable?.() ??
|
|
84
|
+
(request.signal.aborted ? "Progress updates timed out. Reconnecting…" :
|
|
85
|
+
error instanceof Error ? error.message : "Unable to reach the background service."),
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
window.clearTimeout(deadline);
|
|
90
|
+
if (!cancelled)
|
|
91
|
+
timer = window.setTimeout(poll, delay);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
void poll();
|
|
95
|
+
return () => {
|
|
96
|
+
cancelled = true;
|
|
97
|
+
controller?.abort();
|
|
98
|
+
window.clearTimeout(deadline);
|
|
99
|
+
window.clearTimeout(timer);
|
|
100
|
+
};
|
|
101
|
+
}, [catalog, connectionRevision]);
|
|
102
|
+
return feed;
|
|
103
|
+
}
|
|
104
|
+
/** Per-project heatmaps and contributions. These are global derived reads,
|
|
105
|
+
* so they begin only after the daemon's canonical publication gate. Four
|
|
106
|
+
* workers hydrate the list progressively; unbounded Promise.all here once
|
|
107
|
+
* launched two full-corpus queries per project and starved cold ingestion. */
|
|
108
|
+
export function useProjectStats(catalog, projectIds, ready = false) {
|
|
109
|
+
const [stats, setStats] = useState(new Map());
|
|
110
|
+
const key = projectIds.join("\n");
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
let cancelled = false;
|
|
113
|
+
const controller = new AbortController();
|
|
114
|
+
let timer;
|
|
115
|
+
const ids = key === "" ? [] : key.split("\n");
|
|
116
|
+
if (!ready || ids.length === 0) {
|
|
117
|
+
setStats(new Map());
|
|
118
|
+
return () => {
|
|
119
|
+
cancelled = true;
|
|
120
|
+
controller.abort();
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async function loadAll() {
|
|
124
|
+
const sinceMs = getActivityGridStartTimestamp(Date.now());
|
|
125
|
+
const offsetMinutes = getViewerUtcOffsetMinutes();
|
|
126
|
+
// A host that answers every project at once is asked once.
|
|
127
|
+
if (catalog.projectStatsBatch !== undefined) {
|
|
128
|
+
let missing = true;
|
|
129
|
+
try {
|
|
130
|
+
const answer = await catalog.projectStatsBatch(ids, { sinceMs, offsetMinutes }, controller.signal);
|
|
131
|
+
missing = ids.some((id) => !answer.has(id));
|
|
132
|
+
if (!cancelled) {
|
|
133
|
+
setStats((current) => {
|
|
134
|
+
const next = new Map(current);
|
|
135
|
+
for (const id of ids) {
|
|
136
|
+
const figures = answer.get(id);
|
|
137
|
+
if (figures !== undefined)
|
|
138
|
+
next.set(id, figures);
|
|
139
|
+
}
|
|
140
|
+
return next;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// as below: unfigured projects degrade honestly and earn a retry
|
|
146
|
+
}
|
|
147
|
+
if (cancelled)
|
|
148
|
+
return;
|
|
149
|
+
timer = window.setTimeout(loadAll, missing ? 8_000 : 5 * 60_000);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const queue = [...ids];
|
|
153
|
+
let failed = false;
|
|
154
|
+
async function worker() {
|
|
155
|
+
while (!cancelled) {
|
|
156
|
+
const id = queue.shift();
|
|
157
|
+
if (id === undefined)
|
|
158
|
+
return;
|
|
159
|
+
try {
|
|
160
|
+
const figures = await catalog.projectStats(id, { sinceMs, offsetMinutes }, controller.signal);
|
|
161
|
+
if (!cancelled) {
|
|
162
|
+
setStats((current) => {
|
|
163
|
+
const next = new Map(current);
|
|
164
|
+
next.set(id, figures);
|
|
165
|
+
return next;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// an unfigured project degrades honestly — and earns a retry
|
|
171
|
+
failed = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
await Promise.all(Array.from({ length: Math.min(4, ids.length) }, () => worker()));
|
|
176
|
+
if (cancelled)
|
|
177
|
+
return;
|
|
178
|
+
// A failed figure (a daemon mid-restart, a dropped socket) retries in
|
|
179
|
+
// seconds. Stable canonical figures need only a quiet periodic refresh.
|
|
180
|
+
timer = window.setTimeout(loadAll, failed ? 8_000 : 5 * 60_000);
|
|
181
|
+
}
|
|
182
|
+
loadAll();
|
|
183
|
+
return () => {
|
|
184
|
+
cancelled = true;
|
|
185
|
+
controller.abort();
|
|
186
|
+
window.clearTimeout(timer);
|
|
187
|
+
};
|
|
188
|
+
}, [catalog, key, ready]);
|
|
189
|
+
return stats;
|
|
190
|
+
}
|
|
191
|
+
/** The selected project's usage decomposition — per-model days and the
|
|
192
|
+
* hour-of-day profile, over the same 53-week window the heatmap draws. */
|
|
193
|
+
export function useProjectUsage(catalog, projectId, ready = false) {
|
|
194
|
+
const [usage, setUsage] = useState(null);
|
|
195
|
+
useEffect(() => {
|
|
196
|
+
setUsage(null);
|
|
197
|
+
if (projectId === null || !ready)
|
|
198
|
+
return;
|
|
199
|
+
let cancelled = false;
|
|
200
|
+
const controller = new AbortController();
|
|
201
|
+
const load = () => {
|
|
202
|
+
catalog
|
|
203
|
+
.usage(projectId, {
|
|
204
|
+
sinceMs: getActivityGridStartTimestamp(Date.now()),
|
|
205
|
+
offsetMinutes: getViewerUtcOffsetMinutes(),
|
|
206
|
+
}, controller.signal)
|
|
207
|
+
.then((res) => {
|
|
208
|
+
if (!cancelled)
|
|
209
|
+
setUsage(res);
|
|
210
|
+
})
|
|
211
|
+
.catch(() => {
|
|
212
|
+
// the summary panel degrades to what the heatmap alone can say
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
load();
|
|
216
|
+
const timer = setInterval(load, 60_000);
|
|
217
|
+
return () => {
|
|
218
|
+
cancelled = true;
|
|
219
|
+
controller.abort();
|
|
220
|
+
clearInterval(timer);
|
|
221
|
+
};
|
|
222
|
+
}, [catalog, projectId, ready]);
|
|
223
|
+
return usage;
|
|
224
|
+
}
|
|
225
|
+
export function useTimeline(sessions, sessionId) {
|
|
226
|
+
const [owner, setOwner] = useState(sessionId);
|
|
227
|
+
const [attempt, setAttempt] = useState(0);
|
|
228
|
+
const [error, setError] = useState(null);
|
|
229
|
+
const [tail, setTail] = useState([]);
|
|
230
|
+
const [windowStart, setWindowStart] = useState(null);
|
|
231
|
+
const [anchors, setAnchors] = useState(new Set());
|
|
232
|
+
const subscription = useRef(null);
|
|
233
|
+
const [timelineMeta, setTimelineMeta] = useState(null);
|
|
234
|
+
const [status, setStatus] = useState("connecting");
|
|
235
|
+
const [snapshotReady, setSnapshotReady] = useState(false);
|
|
236
|
+
const [watermark, setWatermark] = useState(null);
|
|
237
|
+
const sawSnapshot = useRef(false);
|
|
238
|
+
// The head of the document is a state machine, not a boolean: it holds a
|
|
239
|
+
// page beside the document until the reader pulls (§08, Q7 B). The ref is
|
|
240
|
+
// the authority so a listener firing between commits reduces against the
|
|
241
|
+
// current model; the state mirrors it for rendering.
|
|
242
|
+
const modelRef = useRef(initialEarlierModel());
|
|
243
|
+
const [model, setModel] = useState(modelRef.current);
|
|
244
|
+
const ctx = useMemo(() => ({
|
|
245
|
+
tailIds: new Set(tail.map((row) => row.timeline_id)),
|
|
246
|
+
pageSize: EARLIER_PAGE_SIZE,
|
|
247
|
+
}), [tail]);
|
|
248
|
+
// A pure mirror, so holdEarlier() called from a scroll frame reduces against
|
|
249
|
+
// the tail the reader can actually see.
|
|
250
|
+
const ctxRef = useRef(ctx);
|
|
251
|
+
ctxRef.current = ctx;
|
|
252
|
+
const apply = useCallback((action) => {
|
|
253
|
+
const previous = modelRef.current;
|
|
254
|
+
const next = reduceEarlier(previous, action, ctxRef.current);
|
|
255
|
+
if (next === previous)
|
|
256
|
+
return;
|
|
257
|
+
modelRef.current = next;
|
|
258
|
+
setModel(next);
|
|
259
|
+
// The head owns reveal intent and counts. Canonical values live only in
|
|
260
|
+
// the subscription, which patches held pages and visible history together.
|
|
261
|
+
if (next.older !== previous.older && next.older.length > 0) {
|
|
262
|
+
const sub = subscription.current;
|
|
263
|
+
const combined = [...new Map([...next.older, ...(sub?.entries() ?? [])]
|
|
264
|
+
.map(row => [row.timeline_id, row])).values()].sort((a, b) => a.ordinal - b.ordinal);
|
|
265
|
+
const start = conversationStart(combined, next.cursor !== null);
|
|
266
|
+
// Live arrivals must never move the start forward and hide a visible run.
|
|
267
|
+
setWindowStart(previous => previous === null ? start : Math.min(previous, start ?? previous));
|
|
268
|
+
sub?.reveal(next.older);
|
|
269
|
+
}
|
|
270
|
+
}, []);
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
setOwner(sessionId);
|
|
273
|
+
setError(null);
|
|
274
|
+
setTail([]);
|
|
275
|
+
setWindowStart(null);
|
|
276
|
+
setAnchors(new Set());
|
|
277
|
+
setTimelineMeta(null);
|
|
278
|
+
setWatermark(null);
|
|
279
|
+
setStatus("connecting");
|
|
280
|
+
setSnapshotReady(false);
|
|
281
|
+
sawSnapshot.current = false;
|
|
282
|
+
// A held page belongs to the session it was fetched for.
|
|
283
|
+
apply({ type: "reset" });
|
|
284
|
+
if (sessionId === null)
|
|
285
|
+
return;
|
|
286
|
+
let active = true;
|
|
287
|
+
let sub = null;
|
|
288
|
+
const lease = sessions.acquire(sessionId);
|
|
289
|
+
const start = (client) => {
|
|
290
|
+
sub = client.subscribeSession(sessionId, {
|
|
291
|
+
onReset: () => {
|
|
292
|
+
if (!active)
|
|
293
|
+
return;
|
|
294
|
+
setTail([]);
|
|
295
|
+
setWindowStart(null);
|
|
296
|
+
setAnchors(new Set());
|
|
297
|
+
setTimelineMeta(null);
|
|
298
|
+
setSnapshotReady(false);
|
|
299
|
+
setWatermark(null);
|
|
300
|
+
setError(null);
|
|
301
|
+
sawSnapshot.current = false;
|
|
302
|
+
apply({ type: "reset" });
|
|
303
|
+
},
|
|
304
|
+
onSnapshot: (page) => {
|
|
305
|
+
if (!active)
|
|
306
|
+
return;
|
|
307
|
+
setWindowStart(conversationStart(page.entries, page.cursor !== null));
|
|
308
|
+
apply({ type: "snapshot", cursor: page.cursor });
|
|
309
|
+
},
|
|
310
|
+
onChange: (entries) => {
|
|
311
|
+
if (!active)
|
|
312
|
+
return;
|
|
313
|
+
setTail(entries);
|
|
314
|
+
setSnapshotReady(true);
|
|
315
|
+
setError(null);
|
|
316
|
+
if (!sawSnapshot.current) {
|
|
317
|
+
sawSnapshot.current = true;
|
|
318
|
+
// Everything in the snapshot is the past; the line goes after it.
|
|
319
|
+
setWatermark(entries.length ? Math.max(...entries.map((entry) => entry.ordinal)) : null);
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
onTimelineMetaChange: (meta) => { if (active)
|
|
323
|
+
setTimelineMeta(meta); },
|
|
324
|
+
onStatus: (status) => {
|
|
325
|
+
if (!active)
|
|
326
|
+
return;
|
|
327
|
+
setStatus(status);
|
|
328
|
+
if (status === "closed")
|
|
329
|
+
setError(previous => previous ?? "The message connection closed.");
|
|
330
|
+
},
|
|
331
|
+
onError: (error) => {
|
|
332
|
+
if (!active)
|
|
333
|
+
return;
|
|
334
|
+
if (error.code === "cursor_expired")
|
|
335
|
+
apply({ type: "expired", seq: modelRef.current.fetchSeq });
|
|
336
|
+
else if (error.code !== "not_ready")
|
|
337
|
+
setError(error.message);
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
subscription.current = sub;
|
|
341
|
+
};
|
|
342
|
+
// A port that answers at once subscribes in this effect, exactly as a
|
|
343
|
+
// bare client did; one that must ask first subscribes when it answers.
|
|
344
|
+
if (lease.client !== null)
|
|
345
|
+
start(lease.client);
|
|
346
|
+
else {
|
|
347
|
+
lease.ready.then((client) => {
|
|
348
|
+
if (active)
|
|
349
|
+
start(client);
|
|
350
|
+
}, (error) => {
|
|
351
|
+
if (!active)
|
|
352
|
+
return;
|
|
353
|
+
setStatus("closed");
|
|
354
|
+
setError(error instanceof Error ? error.message : "This session could not be opened.");
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
return () => {
|
|
358
|
+
active = false;
|
|
359
|
+
subscription.current = null;
|
|
360
|
+
sub?.close();
|
|
361
|
+
lease.release();
|
|
362
|
+
};
|
|
363
|
+
}, [sessions, sessionId, attempt, apply]);
|
|
364
|
+
const retry = useCallback(() => setAttempt(value => value + 1), []);
|
|
365
|
+
/** One fetch of the page above, held rather than inserted. */
|
|
366
|
+
const startFetch = useCallback(() => {
|
|
367
|
+
if (sessionId === null)
|
|
368
|
+
return;
|
|
369
|
+
const before = modelRef.current.fetchSeq;
|
|
370
|
+
apply({ type: "hold" });
|
|
371
|
+
const started = modelRef.current;
|
|
372
|
+
if (started.phase !== "fetching" || started.fetchSeq === before)
|
|
373
|
+
return;
|
|
374
|
+
const seq = started.fetchSeq;
|
|
375
|
+
const from = started.cursor;
|
|
376
|
+
const sub = subscription.current;
|
|
377
|
+
if (typeof from !== "string" || sub === null)
|
|
378
|
+
return;
|
|
379
|
+
void readConversationPage(async (cursor, limit) => {
|
|
380
|
+
if (subscription.current !== sub || modelRef.current.fetchSeq !== seq)
|
|
381
|
+
throw new DOMException("The session changed", "AbortError");
|
|
382
|
+
return sub.fetchPage(cursor, limit);
|
|
383
|
+
}, from, EARLIER_PAGE_SIZE).then((page) => {
|
|
384
|
+
if (subscription.current === sub)
|
|
385
|
+
apply({ type: "page", seq, entries: page.entries, cursor: page.cursor });
|
|
386
|
+
}, (error) => {
|
|
387
|
+
if (subscription.current !== sub)
|
|
388
|
+
return;
|
|
389
|
+
if (error instanceof CursorExpiredError)
|
|
390
|
+
apply({ type: "expired", seq });
|
|
391
|
+
else
|
|
392
|
+
apply({ type: "fail", seq, message: EARLIER_FAILED_MESSAGE });
|
|
393
|
+
});
|
|
394
|
+
}, [sessionId, apply]);
|
|
395
|
+
const revealEarlier = useCallback(() => apply({ type: "reveal" }), [apply]);
|
|
396
|
+
const dismissEarlierNotice = useCallback(() => apply({ type: "clearNotice" }), [apply]);
|
|
397
|
+
const loadEarlier = useCallback(() => {
|
|
398
|
+
startFetch();
|
|
399
|
+
apply({ type: "reveal" });
|
|
400
|
+
}, [startFetch, apply]);
|
|
401
|
+
const loadAnchor = useCallback(async (timelineId) => {
|
|
402
|
+
const sub = subscription.current;
|
|
403
|
+
if (sub === null)
|
|
404
|
+
return false;
|
|
405
|
+
setAnchors(previous => new Set([...previous, timelineId]));
|
|
406
|
+
try {
|
|
407
|
+
return await sub.loadEntry(timelineId);
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
if (error instanceof DOMException && error.name === "AbortError")
|
|
411
|
+
return false;
|
|
412
|
+
throw error;
|
|
413
|
+
}
|
|
414
|
+
}, []);
|
|
415
|
+
const rows = useMemo(() => windowStart === null ? tail : tail.filter(row => row.ordinal >= windowStart || anchors.has(row.timeline_id)), [tail, windowStart, anchors]);
|
|
416
|
+
const earlier = useMemo(() => earlierState(model, ctx), [model, ctx]);
|
|
417
|
+
// Nothing in the protocol carries a per-session entry total — SessionRow has
|
|
418
|
+
// no count and TimelinePage returns only entries and a cursor — so the head
|
|
419
|
+
// line says the word without the number (§08: "when it is not, the word
|
|
420
|
+
// stands alone"). The arithmetic waits here for the day a total lands.
|
|
421
|
+
const earlierAbove = earlierAboveOf(null, rows.length);
|
|
422
|
+
// Effects replace the subscription after commit. Never render the old
|
|
423
|
+
// session's rows, metadata or readiness under the newly selected title.
|
|
424
|
+
const current = owner === sessionId;
|
|
425
|
+
return {
|
|
426
|
+
rows: current ? rows : [],
|
|
427
|
+
snapshotReady: current && snapshotReady,
|
|
428
|
+
error: current ? error : null,
|
|
429
|
+
retry,
|
|
430
|
+
timelineMeta: current ? timelineMeta : null,
|
|
431
|
+
status: current ? status : "connecting",
|
|
432
|
+
watermark: current ? watermark : null,
|
|
433
|
+
earlier: current ? earlier : { kind: "none" },
|
|
434
|
+
earlierNotice: current ? model.notice : null,
|
|
435
|
+
earlierAbove: current ? earlierAbove : null,
|
|
436
|
+
landed: current ? model.landing : null,
|
|
437
|
+
holdEarlier: startFetch,
|
|
438
|
+
revealEarlier,
|
|
439
|
+
retryEarlier: startFetch,
|
|
440
|
+
dismissEarlierNotice,
|
|
441
|
+
canLoadEarlier: current && earlier.kind !== "none",
|
|
442
|
+
loadEarlier,
|
|
443
|
+
loadAnchor,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
/** Team conversation is distributed across member transcripts, so one parent
|
|
447
|
+
* document owns a small subscription set. Unlike ordinary Agent subthreads it
|
|
448
|
+
* is eager: delivered boundary messages belong in shared chronology even when
|
|
449
|
+
* no disclosure is open. */
|
|
450
|
+
export function useTeamTimelines(sessions, sessionIds) {
|
|
451
|
+
const key = [...new Set(sessionIds)].sort().join("\n");
|
|
452
|
+
const ids = useMemo(() => (key === "" ? [] : key.split("\n")), [key]);
|
|
453
|
+
const records = useRef(new Map());
|
|
454
|
+
const [revision, setRevision] = useState(0);
|
|
455
|
+
useEffect(() => {
|
|
456
|
+
const wanted = new Set(ids);
|
|
457
|
+
for (const [id, record] of records.current) {
|
|
458
|
+
if (!wanted.has(id)) {
|
|
459
|
+
records.current.delete(id);
|
|
460
|
+
record.sub?.close();
|
|
461
|
+
record.release();
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
for (const id of ids) {
|
|
465
|
+
if (records.current.has(id))
|
|
466
|
+
continue;
|
|
467
|
+
const lease = sessions.acquire(id);
|
|
468
|
+
const record = {
|
|
469
|
+
sub: null,
|
|
470
|
+
history: null,
|
|
471
|
+
error: null,
|
|
472
|
+
release: () => lease.release(),
|
|
473
|
+
};
|
|
474
|
+
records.current.set(id, record);
|
|
475
|
+
const start = (client) => {
|
|
476
|
+
if (records.current.get(id) !== record)
|
|
477
|
+
return;
|
|
478
|
+
record.sub = client.subscribeCollaboration(id, {
|
|
479
|
+
onReset: () => {
|
|
480
|
+
if (records.current.get(id) !== record)
|
|
481
|
+
return;
|
|
482
|
+
record.history = null;
|
|
483
|
+
setRevision((value) => value + 1);
|
|
484
|
+
},
|
|
485
|
+
onChange: (history) => {
|
|
486
|
+
if (records.current.get(id) !== record)
|
|
487
|
+
return;
|
|
488
|
+
record.history = history;
|
|
489
|
+
record.error = null;
|
|
490
|
+
setRevision((value) => value + 1);
|
|
491
|
+
},
|
|
492
|
+
onError: error => {
|
|
493
|
+
if (records.current.get(id) !== record)
|
|
494
|
+
return;
|
|
495
|
+
record.error = error.message;
|
|
496
|
+
setRevision(value => value + 1);
|
|
497
|
+
},
|
|
498
|
+
onStatus: status => {
|
|
499
|
+
if (records.current.get(id) !== record || record.history !== null)
|
|
500
|
+
return;
|
|
501
|
+
if (status === "closed")
|
|
502
|
+
record.error = "Could not load team messages";
|
|
503
|
+
setRevision(value => value + 1);
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
if (lease.client !== null)
|
|
508
|
+
start(lease.client);
|
|
509
|
+
else {
|
|
510
|
+
lease.ready.then(start, (error) => {
|
|
511
|
+
if (records.current.get(id) !== record)
|
|
512
|
+
return;
|
|
513
|
+
record.error = error instanceof Error ? error.message : "Could not load team messages";
|
|
514
|
+
setRevision(value => value + 1);
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
setRevision((value) => value + 1);
|
|
519
|
+
}, [sessions, ids]);
|
|
520
|
+
useEffect(() => () => {
|
|
521
|
+
const previous = [...records.current.values()];
|
|
522
|
+
records.current.clear();
|
|
523
|
+
previous.forEach((record) => {
|
|
524
|
+
record.sub?.close();
|
|
525
|
+
record.release();
|
|
526
|
+
});
|
|
527
|
+
}, []);
|
|
528
|
+
const retry = useCallback(() => {
|
|
529
|
+
for (const record of records.current.values()) {
|
|
530
|
+
if (record.history !== null && record.error === null)
|
|
531
|
+
continue;
|
|
532
|
+
record.error = null;
|
|
533
|
+
record.sub?.restart();
|
|
534
|
+
}
|
|
535
|
+
setRevision(value => value + 1);
|
|
536
|
+
}, []);
|
|
537
|
+
return useMemo(() => {
|
|
538
|
+
const rowsBySession = new Map();
|
|
539
|
+
const responseRuntimesBySession = new Map();
|
|
540
|
+
let historyReady = true;
|
|
541
|
+
let historyError = null;
|
|
542
|
+
for (const id of ids) {
|
|
543
|
+
const record = records.current.get(id);
|
|
544
|
+
const history = record?.history;
|
|
545
|
+
historyError ??= record?.error ?? null;
|
|
546
|
+
if (!history) {
|
|
547
|
+
historyReady = false;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
rowsBySession.set(id, history.entries);
|
|
551
|
+
responseRuntimesBySession.set(id, history.response_runtimes);
|
|
552
|
+
}
|
|
553
|
+
return { rowsBySession, responseRuntimesBySession, historyReady, historyError, retry };
|
|
554
|
+
}, [ids, revision, retry]);
|
|
555
|
+
}
|
|
556
|
+
export const SEARCH_LIMIT = 200;
|
|
557
|
+
/**
|
|
558
|
+
* One ranked search per settled query. The previous response stays on screen
|
|
559
|
+
* while its successor is in flight — a list that blanks on every keystroke
|
|
560
|
+
* reads as a search that keeps failing — and only the newest request may
|
|
561
|
+
* land: a superseded one is aborted and its late result ignored.
|
|
562
|
+
*/
|
|
563
|
+
export function useSearch(catalog, query, facets = {}) {
|
|
564
|
+
const [response, setResponse] = useState(null);
|
|
565
|
+
const [error, setError] = useState(null);
|
|
566
|
+
const [searching, setSearching] = useState(false);
|
|
567
|
+
const project = facets.project ?? null;
|
|
568
|
+
const kind = facets.kind ?? null;
|
|
569
|
+
const agent = facets.agent ?? null;
|
|
570
|
+
useEffect(() => {
|
|
571
|
+
const q = query.trim();
|
|
572
|
+
if (q === "") {
|
|
573
|
+
setResponse(null);
|
|
574
|
+
setError(null);
|
|
575
|
+
setSearching(false);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
const controller = new AbortController();
|
|
579
|
+
let cancelled = false;
|
|
580
|
+
setSearching(true);
|
|
581
|
+
const timer = setTimeout(() => {
|
|
582
|
+
catalog
|
|
583
|
+
.search({ q, limit: SEARCH_LIMIT, project, kind, agent }, controller.signal)
|
|
584
|
+
.then((res) => {
|
|
585
|
+
if (cancelled)
|
|
586
|
+
return;
|
|
587
|
+
setResponse(res);
|
|
588
|
+
setError(null);
|
|
589
|
+
})
|
|
590
|
+
.catch((err) => {
|
|
591
|
+
if (cancelled)
|
|
592
|
+
return;
|
|
593
|
+
setResponse(null);
|
|
594
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
595
|
+
})
|
|
596
|
+
.finally(() => {
|
|
597
|
+
if (!cancelled)
|
|
598
|
+
setSearching(false);
|
|
599
|
+
});
|
|
600
|
+
}, 180);
|
|
601
|
+
return () => {
|
|
602
|
+
cancelled = true;
|
|
603
|
+
clearTimeout(timer);
|
|
604
|
+
controller.abort();
|
|
605
|
+
};
|
|
606
|
+
}, [catalog, query, project, kind, agent]);
|
|
607
|
+
return { query: query.trim(), response, error, searching };
|
|
608
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare function SunGlyph(): import("react").JSX.Element;
|
|
2
|
+
export declare function MoonGlyph(): import("react").JSX.Element;
|
|
3
|
+
export declare function SearchGlyph(): import("react").JSX.Element;
|
|
4
|
+
/** GitHub's monochrome mark from @lobehub/icons-static-svg v1.94.0,
|
|
5
|
+
* the same set as the bundled agent marks. */
|
|
6
|
+
export declare function GitHubGlyph(): import("react").JSX.Element;
|
|
7
|
+
/** Root and two branches — the worktree toggle, on mille's 16-unit grid. */
|
|
8
|
+
export declare function TreeGlyph(): import("react").JSX.Element;
|
|
9
|
+
/** Three ascending bars — the figures toggle. */
|
|
10
|
+
export declare function StatsGlyph(): import("react").JSX.Element;
|
|
11
|
+
export declare function ChevronGlyph(): import("react").JSX.Element;
|
|
12
|
+
/** Copy — two sheets, the front one offset. */
|
|
13
|
+
export declare function CopyGlyph(): import("react").JSX.Element;
|
|
14
|
+
/** Leaving the app — an arrow out of a frame that is deliberately open on the
|
|
15
|
+
* side it leaves by. */
|
|
16
|
+
export declare function ExternalGlyph(): import("react").JSX.Element;
|
|
17
|
+
/** Four outward corners: let the current surface occupy the viewport. */
|
|
18
|
+
export declare function FullscreenGlyph(): import("react").JSX.Element;
|
|
19
|
+
/** The inverse fullscreen mark: four corners returning toward the centre. */
|
|
20
|
+
export declare function ExitFullscreenGlyph(): import("react").JSX.Element;
|
|
21
|
+
export declare function CloseGlyph(): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// The room's own glyphs, drawn on mille's 16-unit grid at stroke 1.5 (or the
|
|
3
|
+
// strip's 24-grid where the proto drew them there) — transcribed from
|
|
4
|
+
// protos/agent-history-proto.
|
|
5
|
+
export function SunGlyph() {
|
|
6
|
+
return (_jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "8", cy: "8", r: "3" }), _jsx("path", { d: "M8 1v1M8 14v1M1 8h1M14 8h1M3.05 3.05l.7.7M12.25 12.25l.7.7M3.05 12.95l.7-.7M12.25 3.75l.7-.7" })] }));
|
|
7
|
+
}
|
|
8
|
+
export function MoonGlyph() {
|
|
9
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M13.6 9.1A5.8 5.8 0 0 1 6.9 2.4a5.8 5.8 0 1 0 6.7 6.7Z" }) }));
|
|
10
|
+
}
|
|
11
|
+
export function SearchGlyph() {
|
|
12
|
+
return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.9", strokeLinecap: "round", "aria-hidden": "true", children: [_jsx("circle", { cx: "10.8", cy: "10.8", r: "6.3" }), _jsx("path", { d: "m15.4 15.4 4.1 4.1" })] }));
|
|
13
|
+
}
|
|
14
|
+
/** GitHub's monochrome mark from @lobehub/icons-static-svg v1.94.0,
|
|
15
|
+
* the same set as the bundled agent marks. */
|
|
16
|
+
export function GitHubGlyph() {
|
|
17
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", fillRule: "evenodd", "aria-hidden": "true", children: _jsx("path", { d: "M12 0c6.63 0 12 5.276 12 11.79-.001 5.067-3.29 9.567-8.175 11.187-.6.118-.825-.25-.825-.56 0-.398.015-1.665.015-3.242 0-1.105-.375-1.813-.81-2.181 2.67-.295 5.475-1.297 5.475-5.822 0-1.297-.465-2.344-1.23-3.169.12-.295.54-1.503-.12-3.125 0 0-1.005-.324-3.3 1.209a11.32 11.32 0 00-3-.398c-1.02 0-2.04.133-3 .398-2.295-1.518-3.3-1.209-3.3-1.209-.66 1.622-.24 2.83-.12 3.125-.765.825-1.23 1.887-1.23 3.169 0 4.51 2.79 5.527 5.46 5.822-.345.294-.66.81-.765 1.577-.69.31-2.415.81-3.495-.973-.225-.354-.9-1.223-1.845-1.209-1.005.015-.405.56.015.781.51.28 1.095 1.327 1.23 1.666.24.663 1.02 1.93 4.035 1.385 0 .988.015 1.916.015 2.196 0 .31-.225.664-.825.56C3.303 21.374-.003 16.867 0 11.791 0 5.276 5.37 0 12 0z" }) }));
|
|
18
|
+
}
|
|
19
|
+
/** Root and two branches — the worktree toggle, on mille's 16-unit grid. */
|
|
20
|
+
export function TreeGlyph() {
|
|
21
|
+
return (_jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M4.3 4.6v6.9" }), _jsx("path", { d: "M4.3 7.6h3.3M4.3 11.5h3.3" }), _jsx("circle", { cx: "4.3", cy: "3.2", r: "1.5", fill: "currentColor", stroke: "none" }), _jsx("circle", { cx: "9.3", cy: "7.6", r: "1.5", fill: "currentColor", stroke: "none" }), _jsx("circle", { cx: "9.3", cy: "11.5", r: "1.5", fill: "currentColor", stroke: "none" })] }));
|
|
22
|
+
}
|
|
23
|
+
/** Three ascending bars — the figures toggle. */
|
|
24
|
+
export function StatsGlyph() {
|
|
25
|
+
return (_jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M3.7 12.1V9.3" }), _jsx("path", { d: "M8 12.1V6.5" }), _jsx("path", { d: "M12.3 12.1V4.1" })] }));
|
|
26
|
+
}
|
|
27
|
+
export function ChevronGlyph() {
|
|
28
|
+
return (_jsx("svg", { viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4.5 2.5 8 6 4.5 9.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
29
|
+
}
|
|
30
|
+
/** Copy — two sheets, the front one offset. */
|
|
31
|
+
export function CopyGlyph() {
|
|
32
|
+
return (_jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "5.5", y: "5.5", width: "8", height: "8", rx: "2" }), _jsx("path", { d: "M10.5 3.5v-.5a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 3v5A1.5 1.5 0 0 0 4 9.5h.5" })] }));
|
|
33
|
+
}
|
|
34
|
+
/** Leaving the app — an arrow out of a frame that is deliberately open on the
|
|
35
|
+
* side it leaves by. */
|
|
36
|
+
export function ExternalGlyph() {
|
|
37
|
+
return (_jsxs("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M13 9.5V13a1.5 1.5 0 0 1-1.5 1.5H3A1.5 1.5 0 0 1 1.5 13V4.5A1.5 1.5 0 0 1 3 3h3.5" }), _jsx("path", { d: "M9.5 1.5h5v5" }), _jsx("path", { d: "m14.5 1.5-6.5 6.5" })] }));
|
|
38
|
+
}
|
|
39
|
+
/** Four outward corners: let the current surface occupy the viewport. */
|
|
40
|
+
export function FullscreenGlyph() {
|
|
41
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M6 2.5H2.5V6M10 2.5h3.5V6M6 13.5H2.5V10M10 13.5h3.5V10" }) }));
|
|
42
|
+
}
|
|
43
|
+
/** The inverse fullscreen mark: four corners returning toward the centre. */
|
|
44
|
+
export function ExitFullscreenGlyph() {
|
|
45
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M2.5 6H6V2.5M13.5 6H10V2.5M2.5 10H6v3.5M13.5 10H10v3.5" }) }));
|
|
46
|
+
}
|
|
47
|
+
export function CloseGlyph() {
|
|
48
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", "aria-hidden": "true", children: _jsx("path", { d: "m4.5 4.5 7 7M11.5 4.5l-7 7" }) }));
|
|
49
|
+
}
|