@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,576 @@
|
|
|
1
|
+
import { ledgerLines, runSummary } from "./ledger.js";
|
|
2
|
+
import { withinPromptCluster } from "./sittings.js";
|
|
3
|
+
import { canonicalText, citationLabel, noticeText, stampSpan, } from "./vocabulary.js";
|
|
4
|
+
function mediaShortName(mediaType, name) {
|
|
5
|
+
if (mediaType !== null && mediaType !== "") {
|
|
6
|
+
const subtype = mediaType.split("/").at(-1) ?? mediaType;
|
|
7
|
+
return subtype.replace(/^x-/, "").toUpperCase();
|
|
8
|
+
}
|
|
9
|
+
const extension = name === null ? null : /\.([A-Za-z0-9]{1,5})$/.exec(name);
|
|
10
|
+
if (extension === null)
|
|
11
|
+
return null;
|
|
12
|
+
const upper = extension[1].toUpperCase();
|
|
13
|
+
return upper === "JPG" ? "JPEG" : upper;
|
|
14
|
+
}
|
|
15
|
+
function caption(width, height, type) {
|
|
16
|
+
const size = width !== null && height !== null ? `${width}×${height}` : null;
|
|
17
|
+
return [size, type].filter((piece) => piece !== null).join(" · ");
|
|
18
|
+
}
|
|
19
|
+
function factFromRef(ref) {
|
|
20
|
+
const name = ref.name;
|
|
21
|
+
const type = mediaShortName(ref.media_type, name);
|
|
22
|
+
return {
|
|
23
|
+
key: ref.id,
|
|
24
|
+
kind: ref.kind,
|
|
25
|
+
name,
|
|
26
|
+
mediaType: ref.media_type,
|
|
27
|
+
byteLen: ref.byte_len,
|
|
28
|
+
width: ref.dimensions?.width ?? null,
|
|
29
|
+
height: ref.dimensions?.height ?? null,
|
|
30
|
+
missing: ref.source.type !== "asset",
|
|
31
|
+
ref,
|
|
32
|
+
caption: caption(ref.dimensions?.width ?? null, ref.dimensions?.height ?? null, type),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Native wrappers and image grammar belong to adapters, never the renderer. */
|
|
36
|
+
export function readAttachments(text, refs) {
|
|
37
|
+
return { text: text?.trim() ? text : null, attachments: refs.map(factFromRef) };
|
|
38
|
+
}
|
|
39
|
+
/** Exact canonical Unicode-scalar spans, converted once to JS string offsets.
|
|
40
|
+
* Missing images retain their link; undocumented numbering stays plain text. */
|
|
41
|
+
export function attachmentMentions(text, attachments) {
|
|
42
|
+
if (!attachments.some(fact => fact.ref?.message_ranges?.length))
|
|
43
|
+
return [];
|
|
44
|
+
const offsets = [0];
|
|
45
|
+
let offset = 0;
|
|
46
|
+
for (const char of text) {
|
|
47
|
+
offset += char.length;
|
|
48
|
+
offsets.push(offset);
|
|
49
|
+
}
|
|
50
|
+
const mentions = [];
|
|
51
|
+
for (const target of attachments) {
|
|
52
|
+
if (target.kind !== "image")
|
|
53
|
+
continue;
|
|
54
|
+
for (const range of target.ref?.message_ranges ?? []) {
|
|
55
|
+
if (!Number.isInteger(range.start) || !Number.isInteger(range.end) || range.start < 0 || range.end <= range.start || range.end >= offsets.length)
|
|
56
|
+
continue;
|
|
57
|
+
mentions.push({ start: offsets[range.start], end: offsets[range.end], target });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
mentions.sort((a, b) => a.start - b.start);
|
|
61
|
+
return mentions.filter((mention, index) => !mentions.some((other, otherIndex) => index !== otherIndex && other.start < mention.end && mention.start < other.end));
|
|
62
|
+
}
|
|
63
|
+
/* ── the prompt ──────────────────────────────────────────────────────────── */
|
|
64
|
+
// A local command as the reader typed it: one line, a leading slash, a name.
|
|
65
|
+
const LOCAL_COMMAND = /^\/[A-Za-z][\w:.-]*(?:\s+\S.*)?$/;
|
|
66
|
+
function looksLocalCommand(text) {
|
|
67
|
+
if (text === null)
|
|
68
|
+
return false;
|
|
69
|
+
const trimmed = text.trim();
|
|
70
|
+
return !trimmed.includes("\n") && LOCAL_COMMAND.test(trimmed);
|
|
71
|
+
}
|
|
72
|
+
/** Project a normalized setting value into the two words the reader needs.
|
|
73
|
+
* Diagnostics deliberately fail this predicate and retain the generic command
|
|
74
|
+
* treatment, so compact presentation never conceals a rejected command. */
|
|
75
|
+
export function localSetting(command, output) {
|
|
76
|
+
if (command === null || output === null)
|
|
77
|
+
return null;
|
|
78
|
+
const value = output.trim();
|
|
79
|
+
if (value === "" || value.includes("\n") || value.length > 96)
|
|
80
|
+
return null;
|
|
81
|
+
const name = command.trim().split(/\s+/, 1)[0]?.toLowerCase();
|
|
82
|
+
if (name === "/effort") {
|
|
83
|
+
return /^[a-z][\w-]*$/i.test(value)
|
|
84
|
+
? { kind: "effort", label: "Effort", value }
|
|
85
|
+
: null;
|
|
86
|
+
}
|
|
87
|
+
if (name === "/model") {
|
|
88
|
+
return /^(?:set|invalid|unknown|error|failed|usage)\b/i.test(value)
|
|
89
|
+
? null
|
|
90
|
+
: { kind: "model", label: "Model", value };
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
function opensTurn(row, options) {
|
|
95
|
+
if (row.body.type === "user")
|
|
96
|
+
return true;
|
|
97
|
+
if (row.body.type === "collaboration" &&
|
|
98
|
+
options.sharedCollaborationSessionIds?.has(row.session_id) === true) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return row.body.type === "collaboration" &&
|
|
102
|
+
(row.group.kind === "human_turn" || row.group.kind === "parent_invocation");
|
|
103
|
+
}
|
|
104
|
+
function isAgentAuthored(row) {
|
|
105
|
+
switch (row.body.type) {
|
|
106
|
+
case "agent":
|
|
107
|
+
case "thinking":
|
|
108
|
+
case "tool_use":
|
|
109
|
+
return true;
|
|
110
|
+
case "summary":
|
|
111
|
+
return row.body.purpose !== "compaction";
|
|
112
|
+
case "collaboration":
|
|
113
|
+
case "user":
|
|
114
|
+
case "notice":
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Every usage record in the reply, summed. A record sits on exactly one row
|
|
119
|
+
* (a response's usage on its first projectable row, a multi-step message's
|
|
120
|
+
* steps each on their own), and the six buckets are mutually exclusive
|
|
121
|
+
* (ARCHITECTURE §4.1.3), so the sum is the reply's total and the heads add up
|
|
122
|
+
* to the same figure as every aggregate. */
|
|
123
|
+
function reportedTokens(rows) {
|
|
124
|
+
let total = 0;
|
|
125
|
+
let reported = false;
|
|
126
|
+
for (const row of rows) {
|
|
127
|
+
const parts = [
|
|
128
|
+
row.usage.input,
|
|
129
|
+
row.usage.output,
|
|
130
|
+
row.usage.cache_read,
|
|
131
|
+
row.usage.cache_write,
|
|
132
|
+
row.usage.cache_write_1h,
|
|
133
|
+
row.usage.thinking,
|
|
134
|
+
];
|
|
135
|
+
if (parts.every((value) => value === null || value === undefined))
|
|
136
|
+
continue;
|
|
137
|
+
reported = true;
|
|
138
|
+
total += parts.reduce((sum, value) => sum + (value ?? 0), 0);
|
|
139
|
+
}
|
|
140
|
+
return reported ? total : null;
|
|
141
|
+
}
|
|
142
|
+
/** A record whose prompt was recorded but whose output never was: its price
|
|
143
|
+
* is a lower bound (a streamed reply that never got its final usage record). */
|
|
144
|
+
function outputUnrecorded(row) {
|
|
145
|
+
const usage = row.usage;
|
|
146
|
+
const prompt = [usage.input, usage.cache_read, usage.cache_write, usage.cache_write_1h];
|
|
147
|
+
return prompt.some((value) => value !== null && value !== undefined)
|
|
148
|
+
&& (usage.output === null || usage.output === undefined);
|
|
149
|
+
}
|
|
150
|
+
/** The reply's list-price cost from each row's read-time `cost`. Partial when
|
|
151
|
+
* any usage-bearing row could not be priced or its output was never recorded;
|
|
152
|
+
* null when no row carried usage. */
|
|
153
|
+
function reportedCost(rows) {
|
|
154
|
+
let microUsd = null;
|
|
155
|
+
let partial = false;
|
|
156
|
+
let reported = false;
|
|
157
|
+
for (const row of rows) {
|
|
158
|
+
const cost = row.cost;
|
|
159
|
+
if (cost === undefined || cost === null)
|
|
160
|
+
continue;
|
|
161
|
+
reported = true;
|
|
162
|
+
if (cost.status === "priced") {
|
|
163
|
+
microUsd = (microUsd ?? 0) + cost.micro_usd;
|
|
164
|
+
if (outputUnrecorded(row))
|
|
165
|
+
partial = true;
|
|
166
|
+
}
|
|
167
|
+
else
|
|
168
|
+
partial = true;
|
|
169
|
+
}
|
|
170
|
+
return reported ? { microUsd, partial } : null;
|
|
171
|
+
}
|
|
172
|
+
function buildPrompt(row, outputRow) {
|
|
173
|
+
const body = row.body;
|
|
174
|
+
const collaboration = body.type === "collaboration" ? body.event : null;
|
|
175
|
+
const rawText = body.type === "user" && body.text !== null
|
|
176
|
+
? canonicalText(body.text)
|
|
177
|
+
: collaboration?.body !== null && collaboration?.body !== undefined
|
|
178
|
+
? canonicalText(collaboration.body)
|
|
179
|
+
: (collaboration?.summary ?? null);
|
|
180
|
+
const refs = body.type === "user" ? body.attachments : [];
|
|
181
|
+
const { text, attachments } = readAttachments(rawText, refs);
|
|
182
|
+
const isCommand = body.type === "user" && attachments.length === 0 && looksLocalCommand(text);
|
|
183
|
+
const output = outputRow !== null && outputRow.body.type === "notice"
|
|
184
|
+
? canonicalText(outputRow.body.notice.type === "command_output"
|
|
185
|
+
? outputRow.body.notice.output
|
|
186
|
+
: { type: "inline", text: "" })
|
|
187
|
+
: null;
|
|
188
|
+
const command = isCommand && text !== null ? text.trim() : null;
|
|
189
|
+
const commandOutput = output === null || output === "" ? null : output;
|
|
190
|
+
return {
|
|
191
|
+
key: row.timeline_id,
|
|
192
|
+
row,
|
|
193
|
+
rows: outputRow === null ? [row] : [row, outputRow],
|
|
194
|
+
at: row.at,
|
|
195
|
+
text,
|
|
196
|
+
attachments,
|
|
197
|
+
isCommand,
|
|
198
|
+
command,
|
|
199
|
+
commandOutput,
|
|
200
|
+
commandOutputRow: outputRow,
|
|
201
|
+
setting: localSetting(command, commandOutput),
|
|
202
|
+
fromParent: row.group.kind === "parent_invocation",
|
|
203
|
+
machine: collaboration === null
|
|
204
|
+
? null
|
|
205
|
+
: {
|
|
206
|
+
label: collaboration.kind === "assignment"
|
|
207
|
+
? "Assignment"
|
|
208
|
+
: collaboration.channel === "coordinator"
|
|
209
|
+
? "Coordinator follow-up"
|
|
210
|
+
: collaboration.channel === "peer"
|
|
211
|
+
? "Peer message"
|
|
212
|
+
: "Team message",
|
|
213
|
+
sender: collaboration.sender,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function thinkingSegment(row, nextAtOf) {
|
|
218
|
+
if (row.body.type !== "thinking")
|
|
219
|
+
return null;
|
|
220
|
+
const text = canonicalText(row.body.text);
|
|
221
|
+
if (text.trim() === "")
|
|
222
|
+
return null;
|
|
223
|
+
const next = nextAtOf(row);
|
|
224
|
+
return {
|
|
225
|
+
kind: "thinking",
|
|
226
|
+
key: row.timeline_id,
|
|
227
|
+
row,
|
|
228
|
+
at: row.at,
|
|
229
|
+
text,
|
|
230
|
+
spanMs: row.at !== null && next !== null && next > row.at ? next - row.at : null,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function markerSegment(row) {
|
|
234
|
+
if (row.body.type !== "notice")
|
|
235
|
+
return null;
|
|
236
|
+
const notice = row.body.notice;
|
|
237
|
+
return {
|
|
238
|
+
kind: "marker",
|
|
239
|
+
key: row.timeline_id,
|
|
240
|
+
row,
|
|
241
|
+
at: row.at,
|
|
242
|
+
notice,
|
|
243
|
+
text: noticeText(notice),
|
|
244
|
+
tone: notice.type === "runtime_error" ||
|
|
245
|
+
(notice.type === "async_task" && ["failed", "denied", "timed_out"].includes(notice.status))
|
|
246
|
+
? "failed"
|
|
247
|
+
: "plain",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function summarySegment(row) {
|
|
251
|
+
if (row.body.type !== "summary")
|
|
252
|
+
return null;
|
|
253
|
+
const text = canonicalText(row.body.text);
|
|
254
|
+
if (text.trim() === "")
|
|
255
|
+
return null;
|
|
256
|
+
return {
|
|
257
|
+
kind: "summary",
|
|
258
|
+
key: row.timeline_id,
|
|
259
|
+
row,
|
|
260
|
+
at: row.at,
|
|
261
|
+
purpose: row.body.purpose,
|
|
262
|
+
text,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function runOther(member) {
|
|
266
|
+
switch (member.kind) {
|
|
267
|
+
case "line":
|
|
268
|
+
return null;
|
|
269
|
+
case "thinking":
|
|
270
|
+
return { kind: "thinking", row: member.row };
|
|
271
|
+
case "marker":
|
|
272
|
+
return { kind: "marker", row: member.row, failed: member.tone === "failed" };
|
|
273
|
+
case "summary":
|
|
274
|
+
return { kind: "summary", row: member.row };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/** Combine only a direct native parent/child pair. Reversed timestamps are
|
|
278
|
+
* common after compaction; proximity to `/compact` is not evidence of a link.
|
|
279
|
+
* A page or sitting boundary leaves each record independently drawable. */
|
|
280
|
+
function compactionPairs(rows, cutBefore) {
|
|
281
|
+
const pairs = new Map();
|
|
282
|
+
// index runs from 1 below rows.length, so index - 1 and index are rows.
|
|
283
|
+
const rowAt = (index) => rows[index];
|
|
284
|
+
for (let index = 1; index < rows.length; index += 1) {
|
|
285
|
+
const previous = rowAt(index - 1);
|
|
286
|
+
const current = rowAt(index);
|
|
287
|
+
if (cutBefore.has(current.timeline_id) || previous.session_id !== current.session_id
|
|
288
|
+
|| current.ordinal !== previous.ordinal + 1)
|
|
289
|
+
continue;
|
|
290
|
+
const summary = previous.body.type === "summary" ? previous : current;
|
|
291
|
+
const boundary = summary === previous ? current : previous;
|
|
292
|
+
if (summary.body.type !== "summary" || summary.body.purpose !== "compaction"
|
|
293
|
+
|| boundary.body.type !== "notice" || boundary.body.notice.type !== "compaction"
|
|
294
|
+
|| boundary.native_id === null || summary.parent_native_id !== boundary.native_id
|
|
295
|
+
|| pairs.has(summary.timeline_id) || pairs.has(boundary.timeline_id))
|
|
296
|
+
continue;
|
|
297
|
+
const pair = [previous, current];
|
|
298
|
+
pairs.set(summary.timeline_id, pair);
|
|
299
|
+
pairs.set(boundary.timeline_id, pair);
|
|
300
|
+
}
|
|
301
|
+
return pairs;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* The reply's segments. R-1: speech is the boundary — a prose row or a team
|
|
305
|
+
* message closes the run, and everything between two of them (tool rows,
|
|
306
|
+
* thoughts, notices, summaries) is ONE run, in order. Even a lone tool line
|
|
307
|
+
* gets the run's summary fold. A lone thought stays a `thinking` segment,
|
|
308
|
+
* a lone notice a `marker`. A run that holds only notices and summaries has
|
|
309
|
+
* no sentence to close to, so its members stand as
|
|
310
|
+
* their own segments. Compaction recaps (and their paired boundary) stay
|
|
311
|
+
* outside activity folds. A sitting boundary (`cutBefore`) also closes a run,
|
|
312
|
+
* so no run straddles a pill.
|
|
313
|
+
*/
|
|
314
|
+
function buildSegments(rows, nextAtOf, context, cutBefore) {
|
|
315
|
+
const segments = [];
|
|
316
|
+
const pairs = compactionPairs(rows, cutBefore);
|
|
317
|
+
let members = [];
|
|
318
|
+
let runRows = [];
|
|
319
|
+
let tools = [];
|
|
320
|
+
const flushTools = () => {
|
|
321
|
+
if (tools.length === 0)
|
|
322
|
+
return;
|
|
323
|
+
for (const line of ledgerLines(tools, context)) {
|
|
324
|
+
members.push({ kind: "line", key: line.key, line });
|
|
325
|
+
}
|
|
326
|
+
tools = [];
|
|
327
|
+
};
|
|
328
|
+
const flushRun = () => {
|
|
329
|
+
flushTools();
|
|
330
|
+
if (members.length === 0)
|
|
331
|
+
return;
|
|
332
|
+
const folds = members.some((member) => member.kind === "line" || member.kind === "thinking");
|
|
333
|
+
if (!folds || (members.length === 1 && members[0].kind !== "line")) {
|
|
334
|
+
// R-2: a lone thought stays a thinking segment, and notices or
|
|
335
|
+
// summaries with nothing to fold around stand as their own markers.
|
|
336
|
+
for (const member of members)
|
|
337
|
+
if (member.kind !== "line")
|
|
338
|
+
segments.push(member);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
const lines = members.flatMap((member) => (member.kind === "line" ? [member.line] : []));
|
|
342
|
+
const others = members.flatMap((member) => {
|
|
343
|
+
const other = runOther(member);
|
|
344
|
+
return other === null ? [] : [other];
|
|
345
|
+
});
|
|
346
|
+
segments.push({
|
|
347
|
+
kind: "ledger",
|
|
348
|
+
key: runRows[0].timeline_id,
|
|
349
|
+
at: firstStamp(runRows),
|
|
350
|
+
rows: runRows,
|
|
351
|
+
lines,
|
|
352
|
+
members,
|
|
353
|
+
summary: runSummary(lines, others),
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
members = [];
|
|
357
|
+
runRows = [];
|
|
358
|
+
};
|
|
359
|
+
for (const row of rows) {
|
|
360
|
+
if (cutBefore.has(row.timeline_id))
|
|
361
|
+
flushRun();
|
|
362
|
+
switch (row.body.type) {
|
|
363
|
+
case "tool_use":
|
|
364
|
+
if (row.body.tool.action.type === "question") {
|
|
365
|
+
// A question to the reader, and their answer, is speech (R-1): it
|
|
366
|
+
// closes the run before it and stands alone, open, as §04 draws it.
|
|
367
|
+
flushRun();
|
|
368
|
+
tools.push(row);
|
|
369
|
+
runRows.push(row);
|
|
370
|
+
flushRun();
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
tools.push(row);
|
|
374
|
+
runRows.push(row);
|
|
375
|
+
continue;
|
|
376
|
+
case "thinking": {
|
|
377
|
+
const segment = thinkingSegment(row, nextAtOf);
|
|
378
|
+
if (segment === null)
|
|
379
|
+
continue;
|
|
380
|
+
flushTools();
|
|
381
|
+
members.push(segment);
|
|
382
|
+
runRows.push(row);
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
case "notice": {
|
|
386
|
+
if (pairs.has(row.timeline_id)) {
|
|
387
|
+
flushRun();
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
const segment = markerSegment(row);
|
|
391
|
+
if (segment === null)
|
|
392
|
+
continue;
|
|
393
|
+
flushTools();
|
|
394
|
+
members.push(segment);
|
|
395
|
+
runRows.push(row);
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
case "summary": {
|
|
399
|
+
if (row.body.purpose === "compaction") {
|
|
400
|
+
flushRun();
|
|
401
|
+
const paired = pairs.get(row.timeline_id) ?? [row];
|
|
402
|
+
segments.push({
|
|
403
|
+
kind: "compaction",
|
|
404
|
+
key: row.timeline_id,
|
|
405
|
+
row,
|
|
406
|
+
rows: paired,
|
|
407
|
+
at: firstStamp(paired),
|
|
408
|
+
text: row.body.text,
|
|
409
|
+
});
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const segment = summarySegment(row);
|
|
413
|
+
if (segment === null)
|
|
414
|
+
continue;
|
|
415
|
+
flushTools();
|
|
416
|
+
members.push(segment);
|
|
417
|
+
runRows.push(row);
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
case "agent": {
|
|
421
|
+
const text = row.body.text === null ? null : canonicalText(row.body.text);
|
|
422
|
+
const { text: prose, attachments } = readAttachments(text, row.body.attachments);
|
|
423
|
+
// A blank agent row said nothing, so it closes nothing (R-1).
|
|
424
|
+
if (prose === null && attachments.length === 0 && row.body.citations.length === 0)
|
|
425
|
+
continue;
|
|
426
|
+
flushRun();
|
|
427
|
+
segments.push({
|
|
428
|
+
kind: "prose",
|
|
429
|
+
key: row.timeline_id,
|
|
430
|
+
row,
|
|
431
|
+
at: row.at,
|
|
432
|
+
text: prose,
|
|
433
|
+
attachments,
|
|
434
|
+
citations: row.body.citations,
|
|
435
|
+
citationLabels: row.body.citations.map(citationLabel),
|
|
436
|
+
});
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
case "collaboration":
|
|
440
|
+
flushRun();
|
|
441
|
+
segments.push({
|
|
442
|
+
kind: "collaboration",
|
|
443
|
+
key: row.timeline_id,
|
|
444
|
+
row,
|
|
445
|
+
at: row.at,
|
|
446
|
+
event: row.body.event,
|
|
447
|
+
});
|
|
448
|
+
continue;
|
|
449
|
+
case "user":
|
|
450
|
+
// Unreachable: a user row always opens its own turn.
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
flushRun();
|
|
455
|
+
return segments;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Fold an ordered timeline into turns. Pure: no clock, no IO. The rows behind
|
|
459
|
+
* every prompt, segment and ledger line stay reachable, so the anchors, the
|
|
460
|
+
* focus landing and the live watermark all keep working off `timeline_id` and
|
|
461
|
+
* `ordinal` exactly as they do today.
|
|
462
|
+
*/
|
|
463
|
+
export function documentTurns(rows, options = {}) {
|
|
464
|
+
const context = options.context ?? {};
|
|
465
|
+
// The next stamped row, for a reasoning segment's span.
|
|
466
|
+
const nextAt = new Map();
|
|
467
|
+
// index and ahead both stay below rows.length.
|
|
468
|
+
const rowAt = (index) => rows[index];
|
|
469
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
470
|
+
let found = null;
|
|
471
|
+
for (let ahead = index + 1; ahead < rows.length; ahead += 1) {
|
|
472
|
+
if (rowAt(ahead).at !== null) {
|
|
473
|
+
found = rowAt(ahead).at;
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
nextAt.set(rowAt(index).timeline_id, found);
|
|
478
|
+
}
|
|
479
|
+
const nextAtOf = (row) => nextAt.get(row.timeline_id) ?? null;
|
|
480
|
+
// Group the rows into turns, absorbing a command prompt's `command_output`
|
|
481
|
+
// notice as we go — the pair is one object, decided by adjacency and nothing
|
|
482
|
+
// else, so the notice never also draws as a marker.
|
|
483
|
+
const groups = [];
|
|
484
|
+
for (const row of rows) {
|
|
485
|
+
if (opensTurn(row, options)) {
|
|
486
|
+
groups.push({ prompt: row, output: null, body: [] });
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
const current = groups.at(-1);
|
|
490
|
+
if (current === undefined) {
|
|
491
|
+
groups.push({ prompt: null, output: null, body: [row] });
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
const promptRow = current.prompt;
|
|
495
|
+
if (promptRow !== null &&
|
|
496
|
+
!options.cutBefore?.has(row.timeline_id) &&
|
|
497
|
+
current.output === null &&
|
|
498
|
+
current.body.length === 0 &&
|
|
499
|
+
row.body.type === "notice" &&
|
|
500
|
+
row.body.notice.type === "command_output" &&
|
|
501
|
+
looksLocalCommand(promptRow.body.type === "user" && promptRow.body.text !== null
|
|
502
|
+
? canonicalText(promptRow.body.text)
|
|
503
|
+
: null)) {
|
|
504
|
+
current.output = row;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
current.body.push(row);
|
|
508
|
+
}
|
|
509
|
+
const turns = [];
|
|
510
|
+
let previousPromptAt = null;
|
|
511
|
+
let previousHadReply = true;
|
|
512
|
+
let previousWasHumanSetting = false;
|
|
513
|
+
for (const group of groups) {
|
|
514
|
+
const promptRow = group.prompt;
|
|
515
|
+
const outputRow = group.output;
|
|
516
|
+
const body = group.body;
|
|
517
|
+
const prompt = promptRow === null ? null : buildPrompt(promptRow, outputRow);
|
|
518
|
+
const segments = buildSegments(body, nextAtOf, context, options.cutBefore ?? new Set());
|
|
519
|
+
const agentRows = body.filter(isAgentAuthored);
|
|
520
|
+
const head = agentRows.length === 0
|
|
521
|
+
? null
|
|
522
|
+
: {
|
|
523
|
+
model: agentRows.find((row) => row.model !== null)?.model ?? null,
|
|
524
|
+
effort: agentRows.find((row) => row.effort !== null)?.effort ?? null,
|
|
525
|
+
tokens: reportedTokens(agentRows),
|
|
526
|
+
cost: reportedCost(agentRows),
|
|
527
|
+
startedAt: firstStamp(body),
|
|
528
|
+
endedAt: lastStamp(body),
|
|
529
|
+
spanMs: stampSpan(body),
|
|
530
|
+
};
|
|
531
|
+
const headIndex = Math.max(0, segments.findIndex((segment) => segment.kind !== "marker" && segment.kind !== "compaction"));
|
|
532
|
+
const at = promptRow?.at ?? firstStamp(body);
|
|
533
|
+
const clusteredWithPrevious = prompt !== null &&
|
|
534
|
+
prompt.setting !== null &&
|
|
535
|
+
!prompt.fromParent &&
|
|
536
|
+
previousWasHumanSetting &&
|
|
537
|
+
!previousHadReply &&
|
|
538
|
+
withinPromptCluster(previousPromptAt, prompt.at);
|
|
539
|
+
const allRows = [
|
|
540
|
+
...(prompt === null ? [] : prompt.rows),
|
|
541
|
+
...body,
|
|
542
|
+
];
|
|
543
|
+
turns.push({
|
|
544
|
+
key: prompt?.key ?? allRows[0]?.timeline_id ?? `turn-${turns.length}`,
|
|
545
|
+
prompt,
|
|
546
|
+
head,
|
|
547
|
+
segments,
|
|
548
|
+
headIndex,
|
|
549
|
+
rows: allRows,
|
|
550
|
+
at,
|
|
551
|
+
clusteredWithPrevious,
|
|
552
|
+
});
|
|
553
|
+
if (prompt !== null) {
|
|
554
|
+
previousPromptAt = prompt.at;
|
|
555
|
+
previousHadReply = agentRows.length > 0;
|
|
556
|
+
previousWasHumanSetting = prompt.setting !== null && !prompt.fromParent;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return turns;
|
|
560
|
+
}
|
|
561
|
+
function firstStamp(rows) {
|
|
562
|
+
for (const row of rows)
|
|
563
|
+
if (row.at !== null)
|
|
564
|
+
return row.at;
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
function lastStamp(rows) {
|
|
568
|
+
// index walks rows from its last index down to 0.
|
|
569
|
+
const rowAt = (index) => rows[index];
|
|
570
|
+
for (let index = rows.length - 1; index >= 0; index -= 1) {
|
|
571
|
+
const at = rowAt(index).at;
|
|
572
|
+
if (at !== null)
|
|
573
|
+
return at;
|
|
574
|
+
}
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TimelineLayout } from "./use-transcript-tail.js";
|
|
2
|
+
/** The selected session owns this hook (its column is keyed by session id).
|
|
3
|
+
* Mount and measure the real document under a stationary loading surface.
|
|
4
|
+
* Readiness comes from the snapshot and initial team reads; two render frames
|
|
5
|
+
* let preview measurement, disclosure layout and scroll placement finish.
|
|
6
|
+
* There is no minimum spinner time and image downloads never block reading. */
|
|
7
|
+
export declare function useTranscriptOpening(snapshotReady: boolean, seeking: boolean): {
|
|
8
|
+
visible: boolean;
|
|
9
|
+
onLayout: (layout: TimelineLayout) => void;
|
|
10
|
+
continueReading: () => void;
|
|
11
|
+
waitingForTeam: boolean;
|
|
12
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useCallback, useLayoutEffect, useState } from "react";
|
|
2
|
+
/** The selected session owns this hook (its column is keyed by session id).
|
|
3
|
+
* Mount and measure the real document under a stationary loading surface.
|
|
4
|
+
* Readiness comes from the snapshot and initial team reads; two render frames
|
|
5
|
+
* let preview measurement, disclosure layout and scroll placement finish.
|
|
6
|
+
* There is no minimum spinner time and image downloads never block reading. */
|
|
7
|
+
export function useTranscriptOpening(snapshotReady, seeking) {
|
|
8
|
+
const [layoutReady, setLayoutReady] = useState(false);
|
|
9
|
+
const [revealed, setRevealed] = useState(false);
|
|
10
|
+
const [readAvailable, setReadAvailable] = useState(false);
|
|
11
|
+
const visible = !snapshotReady || !revealed;
|
|
12
|
+
const onLayout = useCallback((layout) => {
|
|
13
|
+
setLayoutReady(layout.ready && layout.initialReady !== false);
|
|
14
|
+
}, []);
|
|
15
|
+
const continueReading = useCallback(() => setReadAvailable(true), []);
|
|
16
|
+
useLayoutEffect(() => {
|
|
17
|
+
if (!snapshotReady) {
|
|
18
|
+
setRevealed(false);
|
|
19
|
+
setReadAvailable(false);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Once readable, roster changes and ordinary reconnects stay inline.
|
|
23
|
+
if (revealed || seeking || (!layoutReady && !readAvailable))
|
|
24
|
+
return;
|
|
25
|
+
let frame = requestAnimationFrame(() => {
|
|
26
|
+
frame = requestAnimationFrame(() => setRevealed(true));
|
|
27
|
+
});
|
|
28
|
+
return () => cancelAnimationFrame(frame);
|
|
29
|
+
}, [snapshotReady, layoutReady, revealed, seeking, readAvailable]);
|
|
30
|
+
return { visible, onLayout, continueReading, waitingForTeam: snapshotReady && !layoutReady };
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TimelineEntry } from "@vibefield/rosetta-protocol";
|
|
2
|
+
export interface TimelineLayout {
|
|
3
|
+
readonly sessionId: string;
|
|
4
|
+
readonly rows: readonly TimelineEntry[];
|
|
5
|
+
/** Full observed boundary histories establish arrival baselines even while
|
|
6
|
+
* older entries remain outside the displayed parent window. */
|
|
7
|
+
readonly observedRows?: readonly TimelineEntry[];
|
|
8
|
+
readonly ready: boolean;
|
|
9
|
+
/** First covered chronology is complete, or failed with an inline retry.
|
|
10
|
+
* Later team roster changes must not hide an already readable document. */
|
|
11
|
+
readonly initialReady?: boolean;
|
|
12
|
+
readonly readySessionIds: readonly string[];
|
|
13
|
+
readonly elementForRow: (row: TimelineEntry) => HTMLElement | null;
|
|
14
|
+
/** Ownership/coalescing in the displayed chronology may differ from the source page. */
|
|
15
|
+
readonly elementForAnchor?: (timelineId: string) => HTMLElement | null;
|
|
16
|
+
}
|
|
17
|
+
export declare function useTranscriptTail(scrollerRef: {
|
|
18
|
+
current: HTMLElement | null;
|
|
19
|
+
}, sessionId: string | null, enabled: boolean, seeking: boolean, opening?: boolean): {
|
|
20
|
+
onLayout: (next: TimelineLayout) => void;
|
|
21
|
+
pause: () => void | undefined;
|
|
22
|
+
latest: () => void | undefined;
|
|
23
|
+
away: boolean;
|
|
24
|
+
unseen: number;
|
|
25
|
+
};
|