@linxiraos/pi-tui 1.1.26 → 1.2.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/CHANGELOG.md +51 -491
- package/README.md +13 -7
- package/dist/types/active-terminal.d.ts +30 -0
- package/dist/types/app-keybindings.d.ts +7 -2
- package/dist/types/apps/cleanse-board.d.ts +1 -1
- package/dist/types/apps/debug/log-viewer.d.ts +4 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +2 -0
- package/dist/types/apps/git/git-tui.d.ts +5 -4
- package/dist/types/apps/git/help.d.ts +3 -1
- package/dist/types/apps/if-bench-board.d.ts +2 -2
- package/dist/types/apps/setup-model-picker.d.ts +1 -1
- package/dist/types/autocomplete.d.ts +5 -2
- package/dist/types/charts/chart-plan.d.ts +674 -0
- package/dist/types/charts/chart-svg.d.ts +59 -0
- package/dist/types/charts/table-data.d.ts +175 -0
- package/dist/types/chat/assistant-message.d.ts +11 -1
- package/dist/types/chat/chat-transcript-builder.d.ts +3 -0
- package/dist/types/chat/compaction-summary-message.d.ts +1 -0
- package/dist/types/chat/execution-shared.d.ts +6 -5
- package/dist/types/chat/fence-figure.d.ts +42 -0
- package/dist/types/chat/figure-markdown.d.ts +42 -0
- package/dist/types/chat/messages.d.ts +1 -1
- package/dist/types/chat/svg-figure.d.ts +33 -0
- package/dist/types/chat/svg-source.d.ts +49 -0
- package/dist/types/chat/table-chart.d.ts +89 -0
- package/dist/types/chat/tool-execution.d.ts +2 -0
- package/dist/types/chat/user-message.d.ts +17 -4
- package/dist/types/chrome/shared.d.ts +9 -0
- package/dist/types/chrome/status-notice.d.ts +15 -3
- package/dist/types/chrome/transcript-container.d.ts +6 -0
- package/dist/types/components/box.d.ts +1 -0
- package/dist/types/components/disclosure.d.ts +1 -0
- package/dist/types/components/editor.d.ts +23 -5
- package/dist/types/components/form.d.ts +1 -0
- package/dist/types/components/image.d.ts +26 -44
- package/dist/types/components/input.d.ts +2 -1
- package/dist/types/components/key-value-list.d.ts +1 -0
- package/dist/types/components/layout/row.d.ts +1 -0
- package/dist/types/components/layout/stack.d.ts +1 -0
- package/dist/types/components/loader.d.ts +5 -6
- package/dist/types/components/markdown.d.ts +47 -5
- package/dist/types/components/scroll-view.d.ts +1 -0
- package/dist/types/components/section.d.ts +1 -0
- package/dist/types/components/table.d.ts +1 -0
- package/dist/types/components/text.d.ts +1 -0
- package/dist/types/components/tree-view.d.ts +7 -0
- package/dist/types/components/truncated-text.d.ts +1 -0
- package/dist/types/fuzzy.d.ts +29 -1
- package/dist/types/key-hint-format.d.ts +9 -1
- package/dist/types/keybinding-matchers.d.ts +3 -0
- package/dist/types/keybindings.d.ts +1 -1
- package/dist/types/kitty-graphics.d.ts +2 -2
- package/dist/types/loop-watchdog.d.ts +8 -7
- package/dist/types/multiplexers/cmux.d.ts +16 -0
- package/dist/types/multiplexers/herdr.d.ts +26 -0
- package/dist/types/multiplexers/notify.d.ts +13 -0
- package/dist/types/multiplexers/orca.d.ts +12 -0
- package/dist/types/multiplexers/screen.d.ts +9 -0
- package/dist/types/multiplexers/tmux.d.ts +29 -0
- package/dist/types/multiplexers/types.d.ts +100 -0
- package/dist/types/multiplexers/wmux.d.ts +12 -0
- package/dist/types/multiplexers/zellij.d.ts +12 -0
- package/dist/types/native/apply.d.ts +4 -3
- package/dist/types/native/backend.d.ts +5 -4
- package/dist/types/native/blobs.d.ts +7 -3
- package/dist/types/native/encode.d.ts +8 -6
- package/dist/types/native/node.d.ts +36 -5
- package/dist/types/native/overlay.d.ts +8 -3
- package/dist/types/native/settle.d.ts +4 -3
- package/dist/types/overlays/agent-hub-projection.d.ts +6 -5
- package/dist/types/overlays/agent-hub-types.d.ts +9 -0
- package/dist/types/overlays/agent-hub.d.ts +3 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +12 -2
- package/dist/types/overlays/agents-hub.d.ts +9 -0
- package/dist/types/overlays/annotation-overlay.d.ts +19 -2
- package/dist/types/overlays/annotation-types.d.ts +2 -0
- package/dist/types/overlays/ask-dialog.d.ts +5 -2
- package/dist/types/overlays/btw-history-panel.d.ts +13 -1
- package/dist/types/overlays/copy-selector.d.ts +1 -0
- package/dist/types/overlays/history-search.d.ts +10 -0
- package/dist/types/overlays/hook-selector.d.ts +9 -4
- package/dist/types/overlays/hub-frame.d.ts +4 -1
- package/dist/types/overlays/jobs-panel.d.ts +1 -7
- package/dist/types/overlays/model-browser.d.ts +54 -7
- package/dist/types/overlays/model-hub.d.ts +37 -0
- package/dist/types/overlays/oauth-selector.d.ts +0 -1
- package/dist/types/overlays/plan-review-overlay.d.ts +3 -2
- package/dist/types/overlays/report-panel.d.ts +68 -0
- package/dist/types/overlays/rewind-selector.d.ts +1 -0
- package/dist/types/overlays/session-observer-registry.d.ts +2 -0
- package/dist/types/overlays/session-selector.d.ts +6 -2
- package/dist/types/overlays/settings-defs.d.ts +1 -0
- package/dist/types/overlays/thinking-selector.d.ts +2 -2
- package/dist/types/overlays/usage-dashboard.d.ts +12 -8
- package/dist/types/overlays/usage-display.d.ts +3 -1
- package/dist/types/prompt/composer-cache.d.ts +0 -16
- package/dist/types/prompt/composer.d.ts +18 -3
- package/dist/types/prompt/custom-editor.d.ts +25 -13
- package/dist/types/prompt/image-source.d.ts +2 -1
- package/dist/types/prompt/interactive-context-helpers.d.ts +5 -1
- package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
- package/dist/types/prompt/welcome.d.ts +7 -2
- package/dist/types/render/composite.d.ts +2 -0
- package/dist/types/render/output-pane.d.ts +1 -0
- package/dist/types/render/render-utils.d.ts +1 -0
- package/dist/types/render/tool-card.d.ts +6 -0
- package/dist/types/render/width-aware-text.d.ts +2 -0
- package/dist/types/setup/scenes/types.d.ts +1 -0
- package/dist/types/space-hold.d.ts +40 -25
- package/dist/types/status-line/component.d.ts +3 -0
- package/dist/types/status-line/context-usage.d.ts +7 -5
- package/dist/types/status-line/host.d.ts +4 -1
- package/dist/types/status-line/segments.d.ts +2 -0
- package/dist/types/status-line/types.d.ts +14 -3
- package/dist/types/terminal-capabilities.d.ts +41 -36
- package/dist/types/terminal-multiplexer.d.ts +127 -14
- package/dist/types/terminal.d.ts +23 -16
- package/dist/types/theme/active-symbols.d.ts +1 -1
- package/dist/types/theme/schema.d.ts +11 -2
- package/dist/types/theme/symbols.d.ts +1 -1
- package/dist/types/theme/theme-class.d.ts +7 -0
- package/dist/types/theme/theme.d.ts +1 -1
- package/dist/types/theme/tui-adapters.d.ts +3 -0
- package/dist/types/thinking.d.ts +1 -1
- package/dist/types/tmux.d.ts +11 -4
- package/dist/types/tools/bash.d.ts +7 -2
- package/dist/types/tools/daemon.d.ts +1 -1
- package/dist/types/tools/eval.d.ts +22 -3
- package/dist/types/tools/glob.d.ts +4 -0
- package/dist/types/tools/native-view.d.ts +47 -0
- package/dist/types/tools/output-meta.d.ts +11 -1
- package/dist/types/tools/renderer.d.ts +37 -2
- package/dist/types/tools/streaming-output.d.ts +20 -1
- package/dist/types/tools/task.d.ts +2 -3
- package/dist/types/tools/write.d.ts +9 -2
- package/dist/types/tools/yield.d.ts +22 -0
- package/dist/types/tui.d.ts +36 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/vim.d.ts +19 -5
- package/dist/types/windows-input-mode.d.ts +33 -1
- package/package.json +13 -9
- package/src/active-terminal.d.ts +30 -0
- package/src/active-terminal.ts +80 -0
- package/src/app-keybindings.d.ts +7 -2
- package/src/app-keybindings.ts +7 -2
- package/src/apps/autoresearch-dashboard.ts +7 -3
- package/src/apps/cleanse-board.ts +2 -2
- package/src/apps/cleanse-picker.ts +1 -1
- package/src/apps/debug/log-viewer.ts +188 -72
- package/src/apps/debug/raw-sse-buffer.ts +8 -0
- package/src/apps/debug/raw-sse.ts +39 -5
- package/src/apps/git/diff-pane.ts +96 -23
- package/src/apps/git/git-tui.ts +23 -16
- package/src/apps/git/help.ts +29 -20
- package/src/apps/git/sidebar.ts +8 -3
- package/src/apps/if-bench-board.ts +2 -2
- package/src/apps/ps-top.ts +2 -2
- package/src/apps/setup-model-picker.ts +1 -1
- package/src/autocomplete.d.ts +5 -2
- package/src/autocomplete.ts +67 -43
- package/src/bracketed-paste.ts +10 -3
- package/src/charts/chart-plan.d.ts +674 -0
- package/src/charts/chart-plan.ts +5081 -0
- package/src/charts/chart-svg.d.ts +59 -0
- package/src/charts/chart-svg.ts +4657 -0
- package/src/charts/table-data.d.ts +175 -0
- package/src/charts/table-data.ts +1478 -0
- package/src/chat/advisor-message.ts +11 -0
- package/src/chat/assistant-message.d.ts +11 -1
- package/src/chat/assistant-message.ts +245 -54
- package/src/chat/chat-transcript-builder.d.ts +3 -0
- package/src/chat/chat-transcript-builder.ts +9 -3
- package/src/chat/compaction-summary-message.d.ts +1 -0
- package/src/chat/compaction-summary-message.ts +8 -0
- package/src/chat/execution-shared.d.ts +6 -5
- package/src/chat/execution-shared.ts +42 -25
- package/src/chat/fence-figure.d.ts +42 -0
- package/src/chat/fence-figure.ts +80 -0
- package/src/chat/figure-markdown.d.ts +42 -0
- package/src/chat/figure-markdown.ts +174 -0
- package/src/chat/messages.d.ts +1 -1
- package/src/chat/messages.ts +1 -1
- package/src/chat/read-tool-group.ts +6 -4
- package/src/chat/skill-message.ts +6 -0
- package/src/chat/svg-figure.d.ts +33 -0
- package/src/chat/svg-figure.ts +399 -0
- package/src/chat/svg-source.d.ts +49 -0
- package/src/chat/svg-source.ts +188 -0
- package/src/chat/table-chart.d.ts +89 -0
- package/src/chat/table-chart.ts +294 -0
- package/src/chat/tool-execution.d.ts +2 -0
- package/src/chat/tool-execution.ts +86 -7
- package/src/chat/user-message.d.ts +17 -4
- package/src/chat/user-message.ts +71 -8
- package/src/chrome/shared.ts +53 -0
- package/src/chrome/status-notice.ts +25 -7
- package/src/chrome/transcript-container.d.ts +6 -0
- package/src/chrome/transcript-container.ts +162 -19
- package/src/components/box.d.ts +1 -0
- package/src/components/box.ts +5 -0
- package/src/components/disclosure.d.ts +1 -0
- package/src/components/disclosure.ts +8 -0
- package/src/components/editor.d.ts +23 -5
- package/src/components/editor.ts +316 -47
- package/src/components/form.d.ts +1 -0
- package/src/components/form.ts +8 -0
- package/src/components/image.d.ts +26 -44
- package/src/components/image.ts +115 -152
- package/src/components/input.d.ts +2 -1
- package/src/components/input.ts +17 -7
- package/src/components/key-value-list.d.ts +1 -0
- package/src/components/key-value-list.ts +4 -0
- package/src/components/layout/row.d.ts +1 -0
- package/src/components/layout/row.ts +7 -0
- package/src/components/layout/stack.d.ts +1 -0
- package/src/components/layout/stack.ts +7 -0
- package/src/components/loader.d.ts +5 -6
- package/src/components/loader.ts +10 -17
- package/src/components/markdown.d.ts +47 -5
- package/src/components/markdown.ts +786 -303
- package/src/components/scroll-view.d.ts +1 -0
- package/src/components/scroll-view.ts +5 -0
- package/src/components/section.d.ts +1 -0
- package/src/components/section.ts +5 -0
- package/src/components/settings-list.ts +2 -0
- package/src/components/table.d.ts +1 -0
- package/src/components/table.ts +4 -0
- package/src/components/text.d.ts +1 -0
- package/src/components/text.ts +7 -0
- package/src/components/tree-view.d.ts +7 -0
- package/src/components/tree-view.ts +38 -8
- package/src/components/truncated-text.d.ts +1 -0
- package/src/components/truncated-text.ts +5 -0
- package/src/desktop-notify.ts +3 -2
- package/src/fuzzy.d.ts +29 -1
- package/src/fuzzy.ts +115 -30
- package/src/hotkeys-markdown.ts +9 -2
- package/src/key-hint-format.d.ts +9 -1
- package/src/key-hint-format.ts +26 -11
- package/src/keybinding-matchers.d.ts +3 -0
- package/src/keybinding-matchers.ts +6 -2
- package/src/keybindings.d.ts +1 -1
- package/src/keybindings.ts +1 -1
- package/src/kitty-graphics.d.ts +2 -2
- package/src/kitty-graphics.ts +11 -5
- package/src/loop-watchdog.d.ts +8 -7
- package/src/loop-watchdog.ts +18 -13
- package/src/multiplexers/cmux.d.ts +16 -0
- package/src/multiplexers/cmux.ts +29 -0
- package/src/multiplexers/herdr.d.ts +26 -0
- package/src/multiplexers/herdr.ts +64 -0
- package/src/multiplexers/notify.d.ts +13 -0
- package/src/multiplexers/notify.ts +24 -0
- package/src/multiplexers/orca.d.ts +12 -0
- package/src/multiplexers/orca.ts +16 -0
- package/src/multiplexers/screen.d.ts +9 -0
- package/src/multiplexers/screen.ts +15 -0
- package/src/multiplexers/tmux.d.ts +29 -0
- package/src/multiplexers/tmux.ts +40 -0
- package/src/multiplexers/types.d.ts +100 -0
- package/src/multiplexers/types.ts +110 -0
- package/src/multiplexers/wmux.d.ts +12 -0
- package/src/multiplexers/wmux.ts +16 -0
- package/src/multiplexers/zellij.d.ts +12 -0
- package/src/multiplexers/zellij.ts +24 -0
- package/src/native/apply.d.ts +4 -3
- package/src/native/apply.ts +4 -3
- package/src/native/backend.d.ts +5 -4
- package/src/native/backend.ts +199 -22
- package/src/native/blobs.d.ts +7 -3
- package/src/native/blobs.ts +47 -12
- package/src/native/encode.d.ts +8 -6
- package/src/native/encode.ts +76 -34
- package/src/native/node.d.ts +36 -5
- package/src/native/node.ts +31 -5
- package/src/native/overlay.d.ts +8 -3
- package/src/native/overlay.ts +17 -4
- package/src/native/reconcile.ts +16 -4
- package/src/native/settle.d.ts +4 -3
- package/src/native/settle.ts +4 -3
- package/src/overlays/agent-hub-projection.d.ts +6 -5
- package/src/overlays/agent-hub-projection.ts +124 -13
- package/src/overlays/agent-hub-types.d.ts +9 -0
- package/src/overlays/agent-hub-types.ts +6 -0
- package/src/overlays/agent-hub.ts +48 -29
- package/src/overlays/agent-transcript-viewer.ts +93 -23
- package/src/overlays/agents-hub.ts +28 -8
- package/src/overlays/annotation-overlay.ts +293 -90
- package/src/overlays/annotation-types.ts +2 -0
- package/src/overlays/ask-dialog.ts +10 -17
- package/src/overlays/btw-history-panel.ts +136 -39
- package/src/overlays/copy-selector.d.ts +1 -0
- package/src/overlays/copy-selector.ts +32 -8
- package/src/overlays/extensions/extension-dashboard.ts +4 -4
- package/src/overlays/extensions/state-manager.ts +52 -12
- package/src/overlays/history-search.ts +100 -7
- package/src/overlays/hook-selector.ts +12 -5
- package/src/overlays/hub-frame.ts +19 -1
- package/src/overlays/jobs-panel.ts +33 -52
- package/src/overlays/model-browser.ts +367 -122
- package/src/overlays/model-hub.ts +435 -59
- package/src/overlays/move-overlay.ts +28 -14
- package/src/overlays/oauth-selector.ts +54 -70
- package/src/overlays/pause-screen.ts +2 -2
- package/src/overlays/plan-review-overlay.ts +208 -70
- package/src/overlays/plugin-settings.ts +3 -3
- package/src/overlays/report-panel.ts +191 -0
- package/src/overlays/rewind-selector.ts +88 -17
- package/src/overlays/session-observer-registry.d.ts +2 -0
- package/src/overlays/session-observer-registry.ts +10 -2
- package/src/overlays/session-selector.ts +64 -26
- package/src/overlays/settings-defs.ts +5 -4
- package/src/overlays/settings-selector.ts +33 -8
- package/src/overlays/snapcompact-shape-preview.ts +2 -3
- package/src/overlays/stats-notice.ts +1 -1
- package/src/overlays/thinking-selector.ts +11 -10
- package/src/overlays/tree-selector.ts +41 -20
- package/src/overlays/usage-dashboard.ts +117 -58
- package/src/overlays/usage-display.ts +10 -4
- package/src/overlays/usage-row.ts +22 -8
- package/src/prompt/attachment-chips.ts +15 -11
- package/src/prompt/composer-attachments.ts +6 -4
- package/src/prompt/composer-cache.ts +7 -86
- package/src/prompt/composer.ts +37 -26
- package/src/prompt/custom-editor.ts +282 -105
- package/src/prompt/image-source.ts +2 -1
- package/src/prompt/interactive-context-helpers.ts +32 -18
- package/src/prompt/macos-spelling.ts +7 -0
- package/src/prompt/magic-keywords.ts +11 -2
- package/src/prompt/model-mention-autocomplete.ts +14 -14
- package/src/prompt/queued-messages.ts +6 -4
- package/src/prompt/tips.txt +13 -9
- package/src/prompt/welcome.ts +64 -46
- package/src/prompt/word-completion.ts +38 -5
- package/src/render/composite.d.ts +2 -0
- package/src/render/composite.ts +64 -0
- package/src/render/output-pane.d.ts +1 -0
- package/src/render/output-pane.ts +6 -0
- package/src/render/render-utils.d.ts +1 -0
- package/src/render/render-utils.ts +16 -1
- package/src/render/tool-card.d.ts +6 -0
- package/src/render/tool-card.ts +15 -0
- package/src/render/width-aware-text.d.ts +2 -0
- package/src/render/width-aware-text.ts +5 -0
- package/src/setup/scenes/model.ts +2 -1
- package/src/setup/scenes/types.ts +1 -0
- package/src/space-hold.d.ts +40 -25
- package/src/space-hold.ts +156 -52
- package/src/status-line/component.ts +292 -78
- package/src/status-line/context-usage.ts +21 -46
- package/src/status-line/host.ts +4 -1
- package/src/status-line/segments.ts +40 -22
- package/src/status-line/types.ts +15 -3
- package/src/terminal-capabilities.d.ts +41 -36
- package/src/terminal-capabilities.ts +137 -213
- package/src/terminal-multiplexer.d.ts +127 -14
- package/src/terminal-multiplexer.ts +112 -33
- package/src/terminal.d.ts +23 -16
- package/src/terminal.ts +203 -99
- package/src/theme/active-symbols.d.ts +1 -1
- package/src/theme/active-symbols.ts +1 -1
- package/src/theme/schema-validation.ts +1 -0
- package/src/theme/schema.d.ts +11 -2
- package/src/theme/schema.ts +14 -1
- package/src/theme/session-color.ts +1 -7
- package/src/theme/symbols.d.ts +1 -1
- package/src/theme/symbols.ts +11 -4
- package/src/theme/theme-class.d.ts +7 -0
- package/src/theme/theme-class.ts +26 -1
- package/src/theme/theme-schema.json +5 -1
- package/src/theme/theme.d.ts +1 -1
- package/src/theme/theme.ts +8 -4
- package/src/theme/tui-adapters.d.ts +3 -0
- package/src/theme/tui-adapters.ts +68 -0
- package/src/thinking.d.ts +1 -1
- package/src/thinking.ts +1 -1
- package/src/tmux.d.ts +11 -4
- package/src/tmux.ts +47 -11
- package/src/tools/ast-edit.ts +59 -35
- package/src/tools/ast-grep.ts +35 -16
- package/src/tools/bash.d.ts +7 -2
- package/src/tools/bash.ts +116 -47
- package/src/tools/daemon.d.ts +1 -1
- package/src/tools/daemon.ts +1 -1
- package/src/tools/default-renderer.ts +35 -19
- package/src/tools/edit.ts +142 -120
- package/src/tools/eval-format/index.ts +28 -2
- package/src/tools/eval-format/javascript.ts +7 -5
- package/src/tools/eval.d.ts +22 -3
- package/src/tools/eval.ts +364 -208
- package/src/tools/fetch.ts +5 -6
- package/src/tools/glob.d.ts +4 -0
- package/src/tools/glob.ts +33 -65
- package/src/tools/grep.ts +81 -48
- package/src/tools/index.ts +2 -0
- package/src/tools/lsp.ts +81 -59
- package/src/tools/mcp.ts +111 -68
- package/src/tools/native-view.d.ts +47 -0
- package/src/tools/native-view.ts +102 -1
- package/src/tools/output-meta.d.ts +11 -1
- package/src/tools/output-meta.ts +23 -3
- package/src/tools/read.ts +7 -5
- package/src/tools/renderer.d.ts +37 -2
- package/src/tools/renderer.ts +42 -2
- package/src/tools/streaming-output.d.ts +20 -1
- package/src/tools/streaming-output.ts +154 -50
- package/src/tools/task.d.ts +2 -3
- package/src/tools/task.ts +115 -62
- package/src/tools/todo.ts +119 -30
- package/src/tools/wait.ts +34 -24
- package/src/tools/web-search.ts +1 -1
- package/src/tools/write.d.ts +9 -2
- package/src/tools/write.ts +147 -95
- package/src/tools/yield.d.ts +22 -0
- package/src/tools/yield.ts +225 -0
- package/src/tui.d.ts +36 -0
- package/src/tui.ts +666 -217
- package/src/utils.d.ts +6 -0
- package/src/utils.ts +19 -0
- package/src/vim.d.ts +19 -5
- package/src/vim.ts +333 -18
- package/src/windows-input-mode.d.ts +33 -1
- package/src/windows-input-mode.ts +212 -6
|
@@ -23,6 +23,68 @@ function finiteMetric(value: number | undefined): number {
|
|
|
23
23
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/** Message list a fallback metrics read was taken from; unchanged list ⇒ unchanged metrics. */
|
|
27
|
+
interface FallbackReadStamp {
|
|
28
|
+
messages: readonly unknown[];
|
|
29
|
+
length: number;
|
|
30
|
+
last: unknown;
|
|
31
|
+
/** Usage and block count of the last message, which a streaming turn mutates in place. */
|
|
32
|
+
lastShape: string;
|
|
33
|
+
/** Session model, whose context window the context gauge reports. */
|
|
34
|
+
model: unknown;
|
|
35
|
+
contextWindow: number | null | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Stamp of each cached fallback read, keyed by the cache entry so it cannot outlive that read. */
|
|
39
|
+
const fallbackReadStamps = new WeakMap<object, FallbackReadStamp>();
|
|
40
|
+
|
|
41
|
+
function lastMessageShape(last: unknown): string {
|
|
42
|
+
if (!last || typeof last !== "object") return "";
|
|
43
|
+
const { usage, content } = last as {
|
|
44
|
+
usage?: { input?: number; output?: number; cacheWrite?: number; cost?: { total?: number } };
|
|
45
|
+
content?: unknown;
|
|
46
|
+
};
|
|
47
|
+
const blocks = Array.isArray(content) ? content.length : -1;
|
|
48
|
+
return `${usage?.input}:${usage?.output}:${usage?.cacheWrite}:${usage?.cost?.total}:${blocks}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function fallbackReadStamp(session: NonNullable<AgentRecordLike["session"]>): FallbackReadStamp | undefined {
|
|
52
|
+
try {
|
|
53
|
+
const messages = session.agent?.state?.messages;
|
|
54
|
+
if (!Array.isArray(messages)) return undefined;
|
|
55
|
+
const last = messages[messages.length - 1];
|
|
56
|
+
return {
|
|
57
|
+
messages,
|
|
58
|
+
length: messages.length,
|
|
59
|
+
last,
|
|
60
|
+
lastShape: lastMessageShape(last),
|
|
61
|
+
model: session.model,
|
|
62
|
+
contextWindow: session.model?.contextWindow,
|
|
63
|
+
};
|
|
64
|
+
} catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Whether a cached fallback read still matches the session's message list
|
|
71
|
+
* (append, compaction, rewrite, streaming tail) and model (context window).
|
|
72
|
+
*/
|
|
73
|
+
function fallbackReadCurrent(entry: object, session: NonNullable<AgentRecordLike["session"]>): boolean {
|
|
74
|
+
const stamp = fallbackReadStamps.get(entry);
|
|
75
|
+
if (!stamp) return false;
|
|
76
|
+
const current = fallbackReadStamp(session);
|
|
77
|
+
return (
|
|
78
|
+
current !== undefined &&
|
|
79
|
+
current.messages === stamp.messages &&
|
|
80
|
+
current.length === stamp.length &&
|
|
81
|
+
current.last === stamp.last &&
|
|
82
|
+
current.lastShape === stamp.lastShape &&
|
|
83
|
+
current.model === stamp.model &&
|
|
84
|
+
current.contextWindow === stamp.contextWindow
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
26
88
|
/** Exact observer usage for one roster entry. */
|
|
27
89
|
export function progressMetrics(observed: ObservableSession | undefined): AgentMetrics | undefined {
|
|
28
90
|
const progress = observed?.progress;
|
|
@@ -60,12 +122,33 @@ export function progressMetrics(observed: ObservableSession | undefined): AgentM
|
|
|
60
122
|
};
|
|
61
123
|
}
|
|
62
124
|
|
|
125
|
+
/** Lifetime cost from the authoritative session index, excluding task-result child billing. */
|
|
126
|
+
function readSessionDirectCost(session: NonNullable<AgentRecordLike["session"]>): number | undefined {
|
|
127
|
+
try {
|
|
128
|
+
const usage = session.sessionManager?.getUsageStatistics();
|
|
129
|
+
if (
|
|
130
|
+
usage &&
|
|
131
|
+
Number.isFinite(usage.cost) &&
|
|
132
|
+
Number.isFinite(usage.subagentCost) &&
|
|
133
|
+
usage.cost >= usage.subagentCost
|
|
134
|
+
) {
|
|
135
|
+
return usage.cost - usage.subagentCost;
|
|
136
|
+
}
|
|
137
|
+
} catch {
|
|
138
|
+
// A session stopping during render may have already closed its stats host.
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
63
143
|
/**
|
|
64
144
|
* Read direct assistant usage from a live session. SessionStats also includes
|
|
65
145
|
* usage embedded in completed `task` tool results, so using it for a parent
|
|
66
146
|
* row would double-count child rows in the aggregate.
|
|
67
147
|
*/
|
|
68
|
-
function readSessionMetrics(
|
|
148
|
+
function readSessionMetrics(
|
|
149
|
+
session: NonNullable<AgentRecordLike["session"]>,
|
|
150
|
+
directCost: number | undefined,
|
|
151
|
+
): AgentMetrics | undefined {
|
|
69
152
|
try {
|
|
70
153
|
const stats = session.getSessionStats();
|
|
71
154
|
const messages = session.agent?.state?.messages;
|
|
@@ -74,7 +157,7 @@ function readSessionMetrics(session: NonNullable<AgentRecordLike["session"]>): A
|
|
|
74
157
|
tokens: stats.tokens.input + stats.tokens.output + stats.tokens.cacheWrite,
|
|
75
158
|
requests: stats.assistantMessages,
|
|
76
159
|
tools: stats.toolCalls,
|
|
77
|
-
cost: stats.cost,
|
|
160
|
+
cost: directCost ?? stats.cost,
|
|
78
161
|
durationMs: 0,
|
|
79
162
|
durationKind: "unknown",
|
|
80
163
|
contextTokens: stats.contextUsage?.tokens,
|
|
@@ -97,7 +180,7 @@ function readSessionMetrics(session: NonNullable<AgentRecordLike["session"]>): A
|
|
|
97
180
|
tokens,
|
|
98
181
|
requests,
|
|
99
182
|
tools,
|
|
100
|
-
cost,
|
|
183
|
+
cost: directCost ?? cost,
|
|
101
184
|
durationMs: 0,
|
|
102
185
|
durationKind: "unknown",
|
|
103
186
|
contextTokens: stats.contextUsage?.tokens,
|
|
@@ -110,29 +193,39 @@ function readSessionMetrics(session: NonNullable<AgentRecordLike["session"]>): A
|
|
|
110
193
|
}
|
|
111
194
|
}
|
|
112
195
|
|
|
113
|
-
/** Live session
|
|
196
|
+
/** Live session used to cache a row's direct assistant usage, including with observer progress. */
|
|
114
197
|
export function hubFallbackStatsSession<TRecord extends AgentRecordLike>(
|
|
115
198
|
ref: TRecord,
|
|
116
199
|
observed: ObservableSession | undefined,
|
|
117
200
|
): NonNullable<TRecord["session"]> | undefined {
|
|
118
|
-
|
|
201
|
+
void observed;
|
|
119
202
|
const session = ref.session;
|
|
120
203
|
return session && typeof session.getSessionStats === "function" ? session : undefined;
|
|
121
204
|
}
|
|
122
205
|
|
|
206
|
+
function withDirectCost(metrics: AgentMetrics | undefined, cost: number | undefined): AgentMetrics | undefined {
|
|
207
|
+
return metrics && cost !== undefined ? { ...metrics, cost } : metrics;
|
|
208
|
+
}
|
|
209
|
+
|
|
123
210
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
211
|
+
* Preserve progress/history for non-cost metrics, overlaying cumulative direct-session cost.
|
|
212
|
+
* Persisted `history.metrics.cost` is a leaf-scoped snapshot, so it never overrides live
|
|
213
|
+
* progress; only the cumulative direct-cost sources do.
|
|
126
214
|
*/
|
|
127
215
|
export function hubRowMetrics<TRecord extends AgentRecordLike>(
|
|
128
216
|
ref: TRecord,
|
|
129
217
|
observed: ObservableSession | undefined,
|
|
130
218
|
sessionMetrics: WeakMap<object, { metrics: AgentMetrics | undefined }>,
|
|
131
219
|
): AgentMetrics | undefined {
|
|
132
|
-
if (observed?.progress) return progressMetrics(observed);
|
|
133
|
-
if (ref.history?.metrics) return ref.history.metrics;
|
|
134
220
|
const session = hubFallbackStatsSession(ref, observed);
|
|
135
|
-
|
|
221
|
+
const liveEntry = session ? sessionMetrics.get(session) : undefined;
|
|
222
|
+
const retainedEntry = sessionMetrics.get(ref);
|
|
223
|
+
const historyMetrics = ref.history?.metrics;
|
|
224
|
+
const cost = liveEntry?.metrics?.cost ?? ref.history?.directCost ?? retainedEntry?.metrics?.cost;
|
|
225
|
+
if (observed?.progress) return withDirectCost(progressMetrics(observed), cost);
|
|
226
|
+
if (historyMetrics) return withDirectCost(historyMetrics, cost);
|
|
227
|
+
if (!session && retainedEntry?.metrics) return withDirectCost(retainedEntry.metrics, cost);
|
|
228
|
+
return withDirectCost(liveEntry?.metrics, cost);
|
|
136
229
|
}
|
|
137
230
|
|
|
138
231
|
export function aggregateMetrics<TRecord extends AgentRecordLike>(args: {
|
|
@@ -163,9 +256,21 @@ export function aggregateMetrics<TRecord extends AgentRecordLike>(args: {
|
|
|
163
256
|
const fallbackSession = args.fallbackStatsSession(ref, observed);
|
|
164
257
|
if (fallbackSession) {
|
|
165
258
|
hasFallbackLiveSessions = true;
|
|
166
|
-
|
|
167
|
-
|
|
259
|
+
let cached = args.sessionMetrics.get(fallbackSession);
|
|
260
|
+
const directCost = readSessionDirectCost(fallbackSession);
|
|
261
|
+
// Refresh cost independently from the message scan: model_usage entries
|
|
262
|
+
// are cumulative but do not alter the agent's live message list.
|
|
263
|
+
if (!cached || (args.refreshFallback && !fallbackReadCurrent(cached, fallbackSession))) {
|
|
264
|
+
const stamp = fallbackReadStamp(fallbackSession);
|
|
265
|
+
const entry = { metrics: readSessionMetrics(fallbackSession, directCost) };
|
|
266
|
+
if (stamp) fallbackReadStamps.set(entry, stamp);
|
|
267
|
+
args.sessionMetrics.set(fallbackSession, entry);
|
|
268
|
+
cached = entry;
|
|
269
|
+
} else if (cached.metrics && directCost !== undefined) {
|
|
270
|
+
cached.metrics.cost = directCost;
|
|
168
271
|
}
|
|
272
|
+
// Preserve valid direct-session snapshots through parking or a failed teardown read.
|
|
273
|
+
if (cached.metrics) args.sessionMetrics.set(ref, cached);
|
|
169
274
|
}
|
|
170
275
|
const metrics = args.metricsFor(ref, observed);
|
|
171
276
|
if (!metrics || (fallbackSession && countedFallbackSessions.has(fallbackSession))) continue;
|
|
@@ -183,9 +288,10 @@ export function aggregateMetrics<TRecord extends AgentRecordLike>(args: {
|
|
|
183
288
|
return { metrics: total, hasFallbackLiveSessions };
|
|
184
289
|
}
|
|
185
290
|
|
|
186
|
-
/** Parent-before-child projection preserving
|
|
291
|
+
/** Parent-before-child projection preserving initial subtree rank and prepending new siblings. */
|
|
187
292
|
export function projectAgentTree<TRecord extends AgentRecordLike>(
|
|
188
293
|
refs: readonly TRecord[],
|
|
294
|
+
rosterRank: ReadonlyMap<TRecord, number> | undefined,
|
|
189
295
|
): AgentTreeProjection<TRecord> {
|
|
190
296
|
const ids = new Set<string>();
|
|
191
297
|
const operationalIndex = new Map<string, number>();
|
|
@@ -218,7 +324,12 @@ export function projectAgentTree<TRecord extends AgentRecordLike>(
|
|
|
218
324
|
if (!current) continue;
|
|
219
325
|
if (current.expanded) {
|
|
220
326
|
let order = operationalIndex.get(current.ref.id) ?? Number.MAX_SAFE_INTEGER;
|
|
327
|
+
const parentRank = rosterRank?.get(current.ref);
|
|
221
328
|
for (const child of children.get(current.ref.id) ?? []) {
|
|
329
|
+
const childRank = rosterRank?.get(child);
|
|
330
|
+
// A child spawned later cannot move an existing parent's group.
|
|
331
|
+
if (parentRank !== undefined && childRank !== undefined && childRank < 0 && childRank < parentRank)
|
|
332
|
+
continue;
|
|
222
333
|
order = Math.min(order, subtreeOrder.get(child.id) ?? Number.MAX_SAFE_INTEGER);
|
|
223
334
|
}
|
|
224
335
|
subtreeOrder.set(current.ref.id, order);
|
|
@@ -28,6 +28,13 @@ export interface AgentHubSession {
|
|
|
28
28
|
messages: AgentMessage[];
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
+
/** Existing session ledger includes off-transcript model usage and nested-task attribution. */
|
|
32
|
+
readonly sessionManager?: {
|
|
33
|
+
getUsageStatistics(): {
|
|
34
|
+
cost: number;
|
|
35
|
+
subagentCost: number;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
31
38
|
getSessionStats(): {
|
|
32
39
|
tokens: {
|
|
33
40
|
input: number;
|
|
@@ -64,6 +71,8 @@ export interface AgentRecordLike {
|
|
|
64
71
|
resolvedModel?: string;
|
|
65
72
|
resolvedModelIsFallback?: boolean;
|
|
66
73
|
metrics?: AgentMetricsSummary;
|
|
74
|
+
/** Cumulative own-session assistant and model_usage cost, excluding nested task results. */
|
|
75
|
+
directCost?: number;
|
|
67
76
|
readOnly?: boolean;
|
|
68
77
|
outputPath?: string;
|
|
69
78
|
patchPath?: string;
|
|
@@ -22,6 +22,10 @@ export interface AgentHubSession {
|
|
|
22
22
|
readonly model: Model | undefined;
|
|
23
23
|
readonly servingModel?: { selector: string; isFallback: boolean };
|
|
24
24
|
readonly agent?: { state: { messages: AgentMessage[] } };
|
|
25
|
+
/** Existing session ledger includes off-transcript model usage and nested-task attribution. */
|
|
26
|
+
readonly sessionManager?: {
|
|
27
|
+
getUsageStatistics(): { cost: number; subagentCost: number };
|
|
28
|
+
};
|
|
25
29
|
getSessionStats(): {
|
|
26
30
|
tokens: { input: number; output: number; cacheWrite: number };
|
|
27
31
|
assistantMessages: number;
|
|
@@ -49,6 +53,8 @@ export interface AgentRecordLike {
|
|
|
49
53
|
resolvedModel?: string;
|
|
50
54
|
resolvedModelIsFallback?: boolean;
|
|
51
55
|
metrics?: AgentMetricsSummary;
|
|
56
|
+
/** Cumulative own-session assistant and model_usage cost, excluding nested task results. */
|
|
57
|
+
directCost?: number;
|
|
52
58
|
readOnly?: boolean;
|
|
53
59
|
outputPath?: string;
|
|
54
60
|
patchPath?: string;
|
|
@@ -200,6 +200,12 @@ const DATA_CHANGE_RENDER_COALESCE_MS = 100;
|
|
|
200
200
|
/** Double-tap window for the table's left-left "close hub" gesture. */
|
|
201
201
|
const LEFT_TAP_WINDOW_MS = 500;
|
|
202
202
|
|
|
203
|
+
function compareRosterAgents(a: AgentRecordLike, b: AgentRecordLike): number {
|
|
204
|
+
return (
|
|
205
|
+
STATUS_ORDER[a.status] - STATUS_ORDER[b.status] || b.lastActivity - a.lastActivity || a.id.localeCompare(b.id)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
203
209
|
function activityGlyph(row: AgentActivityRow): string {
|
|
204
210
|
if (row.status === "error") return theme.fg("error", theme.status.error);
|
|
205
211
|
if (row.status === "aborted") return theme.fg("warning", theme.status.aborted);
|
|
@@ -300,6 +306,7 @@ export interface AgentHubDeps<TRecord extends AgentRecordLike = AgentRecordLike>
|
|
|
300
306
|
/** Mirrors the main transcript's thinking-block visibility. */
|
|
301
307
|
hideThinkingBlock?: () => boolean;
|
|
302
308
|
proseOnlyThinking?: () => boolean;
|
|
309
|
+
expandThinkingBlocks?: () => boolean;
|
|
303
310
|
/** Keys toggling tool output expansion (app.tools.expand). */
|
|
304
311
|
expandKeys?: KeyId[];
|
|
305
312
|
/** Focus the main view on this agent's live session (ctx.focusAgentSession). When absent (collab guest, tests), Enter opens the in-hub chat view instead. */
|
|
@@ -357,11 +364,10 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
357
364
|
#rows: TRecord[] = [];
|
|
358
365
|
#statusCounts: Record<AgentStatus, number> = { running: 0, idle: 0, parked: 0, aborted: 0 };
|
|
359
366
|
#selectedRow = 0;
|
|
360
|
-
/**
|
|
361
|
-
*
|
|
362
|
-
* while the hub is open; newly appearing generations append at the end. */
|
|
367
|
+
/** Initial status/recency rank stays fixed while open; new generations
|
|
368
|
+
* prepend without changing the relative order of existing rows. */
|
|
363
369
|
#rowOrder: Map<TRecord, number> | undefined;
|
|
364
|
-
#
|
|
370
|
+
#nextNewRowOrder = 0;
|
|
365
371
|
#hoveredRow: number | null = null;
|
|
366
372
|
/** Per-render screen-line to agent-row map, shared by click and hover routing. */
|
|
367
373
|
#hitRows: Array<number | undefined> = [];
|
|
@@ -445,6 +451,7 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
445
451
|
#cwd: string;
|
|
446
452
|
#hideThinkingBlock: (() => boolean) | undefined;
|
|
447
453
|
#proseOnlyThinking: (() => boolean) | undefined;
|
|
454
|
+
#expandThinkingBlocks: (() => boolean) | undefined;
|
|
448
455
|
#expandKeys: KeyId[];
|
|
449
456
|
#focusAgent: ((id: string) => Promise<void>) | undefined;
|
|
450
457
|
|
|
@@ -490,6 +497,7 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
490
497
|
this.#cwd = deps.cwd ?? getProjectDir();
|
|
491
498
|
this.#hideThinkingBlock = deps.hideThinkingBlock;
|
|
492
499
|
this.#proseOnlyThinking = deps.proseOnlyThinking;
|
|
500
|
+
this.#expandThinkingBlocks = deps.expandThinkingBlocks;
|
|
493
501
|
this.#expandKeys = deps.expandKeys ?? ["ctrl+o"];
|
|
494
502
|
this.#focusAgent = deps.focusAgent;
|
|
495
503
|
|
|
@@ -613,6 +621,11 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
613
621
|
this.#lastLeftTap = Date.now();
|
|
614
622
|
}
|
|
615
623
|
|
|
624
|
+
/** Show `section`, as a slash-command deep link into an already-open hub does. */
|
|
625
|
+
showSection(section: AgentHubSection): void {
|
|
626
|
+
this.#switchSection(section);
|
|
627
|
+
}
|
|
628
|
+
|
|
616
629
|
/**
|
|
617
630
|
* Open the fullscreen transcript viewer for an agent id (public for table Enter
|
|
618
631
|
* and tests). Mounts {@link AgentTranscriptViewer} as a `fullscreen` overlay so it
|
|
@@ -639,6 +652,7 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
639
652
|
cwd: this.#cwd,
|
|
640
653
|
hideThinkingBlock: this.#hideThinkingBlock,
|
|
641
654
|
proseOnlyThinking: this.#proseOnlyThinking,
|
|
655
|
+
expandThinkingBlocks: this.#expandThinkingBlocks,
|
|
642
656
|
expandKeys: this.#expandKeys,
|
|
643
657
|
hubKeys: this.#hubKeys,
|
|
644
658
|
requestRender: this.#requestRender,
|
|
@@ -937,12 +951,16 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
937
951
|
return { ...item, depth, open: this.#childrenByParent.has(ref.id) ? true : undefined };
|
|
938
952
|
}
|
|
939
953
|
if (!metrics) return item;
|
|
954
|
+
// A running agent's active time ticks terminal-side from the age at send; a settled one
|
|
955
|
+
// is frozen text. Progress `durationMs` was current when its frame arrived, so age it to now
|
|
956
|
+
// — re-sending the stale value on every repaint rewinds Tern's clock. A first frame can
|
|
957
|
+
// report 0 ms, so a progress timestamp alone makes the row clockable.
|
|
958
|
+
const progressAt = observed?.progress ? observed.progressAt : undefined;
|
|
940
959
|
const facts: Record<string, string | number> = {
|
|
941
960
|
cost: formatCost(metrics.cost),
|
|
942
|
-
// A running agent's active time ticks terminal-side; a settled one is frozen text.
|
|
943
961
|
time:
|
|
944
|
-
ref.status === "running" && metrics.durationMs > 0
|
|
945
|
-
? metrics.durationMs
|
|
962
|
+
ref.status === "running" && (metrics.durationMs > 0 || progressAt !== undefined)
|
|
963
|
+
? metrics.durationMs + (progressAt === undefined ? 0 : Math.max(0, Date.now() - progressAt))
|
|
946
964
|
: formatDuration(metrics.durationMs),
|
|
947
965
|
req: metrics.requests,
|
|
948
966
|
tools: metrics.tools,
|
|
@@ -1515,35 +1533,35 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
1515
1533
|
const refs = this.#registry.list().filter(ref => ref.id !== MAIN_AGENT_ID);
|
|
1516
1534
|
this.#observedById = new Map();
|
|
1517
1535
|
for (const session of this.#observers.getSessions()) this.#observedById.set(session.id, session);
|
|
1518
|
-
//
|
|
1519
|
-
//
|
|
1520
|
-
//
|
|
1521
|
-
// Defer the capture until persisted-subagent discovery settles so a
|
|
1522
|
-
// mid-scan refresh cannot freeze a partial roster (the remaining agents
|
|
1523
|
-
// would otherwise append in readdir order instead of being ranked).
|
|
1536
|
+
// Capture the status+recency ranking once so keyboard navigation does
|
|
1537
|
+
// not jump on heartbeats. Defer until persisted-subagent discovery
|
|
1538
|
+
// settles so a partial roster is not frozen in readdir order.
|
|
1524
1539
|
const rowOrder = this.#rowOrder;
|
|
1525
1540
|
let ordered: TRecord[];
|
|
1526
1541
|
if (!rowOrder) {
|
|
1527
|
-
ordered = refs.sort(
|
|
1528
|
-
(a, b) =>
|
|
1529
|
-
STATUS_ORDER[a.status] - STATUS_ORDER[b.status] ||
|
|
1530
|
-
b.lastActivity - a.lastActivity ||
|
|
1531
|
-
a.id.localeCompare(b.id),
|
|
1532
|
-
);
|
|
1542
|
+
ordered = refs.sort(compareRosterAgents);
|
|
1533
1543
|
if (!this.#loadingPersistedSubagents && ordered.length > 0) {
|
|
1534
|
-
|
|
1535
|
-
for (const ref of ordered)
|
|
1544
|
+
const rowOrder = new Map<TRecord, number>();
|
|
1545
|
+
for (const [index, ref] of ordered.entries()) rowOrder.set(ref, index);
|
|
1546
|
+
this.#rowOrder = rowOrder;
|
|
1536
1547
|
}
|
|
1537
1548
|
} else {
|
|
1538
1549
|
for (const rankedRef of rowOrder.keys()) {
|
|
1539
1550
|
if (!refs.includes(rankedRef)) rowOrder.delete(rankedRef);
|
|
1540
1551
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
for (const ref of
|
|
1545
|
-
if (!rowOrder.has(ref))
|
|
1552
|
+
// Each batch of newly appearing generations uses the initial sort,
|
|
1553
|
+
// then takes ranks above every agent already on screen.
|
|
1554
|
+
let newcomers: TRecord[] | undefined;
|
|
1555
|
+
for (const ref of refs) {
|
|
1556
|
+
if (!rowOrder.has(ref)) (newcomers ??= []).push(ref);
|
|
1557
|
+
}
|
|
1558
|
+
if (newcomers) {
|
|
1559
|
+
newcomers.sort(compareRosterAgents);
|
|
1560
|
+
for (let i = newcomers.length - 1; i >= 0; i--) {
|
|
1561
|
+
rowOrder.set(newcomers[i]!, --this.#nextNewRowOrder);
|
|
1562
|
+
}
|
|
1546
1563
|
}
|
|
1564
|
+
ordered = refs.sort((a, b) => rowOrder.get(a)! - rowOrder.get(b)!);
|
|
1547
1565
|
}
|
|
1548
1566
|
const query = this.#agentFilter.getValue().trim();
|
|
1549
1567
|
const rosterRows =
|
|
@@ -1552,7 +1570,7 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
1552
1570
|
: ordered;
|
|
1553
1571
|
|
|
1554
1572
|
if (this.#viewMode === "tree") {
|
|
1555
|
-
const tree = projectAgentTree(rosterRows);
|
|
1573
|
+
const tree = projectAgentTree(rosterRows, rowOrder);
|
|
1556
1574
|
this.#rows = tree.rows;
|
|
1557
1575
|
this.#treeDepthById = tree.depthById;
|
|
1558
1576
|
this.#treeParentById = tree.parentById;
|
|
@@ -1585,7 +1603,8 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
1585
1603
|
for (const ref of rosterRows) this.#statusCounts[ref.status]++;
|
|
1586
1604
|
this.#refreshAggregate();
|
|
1587
1605
|
this.#refreshActivityData(rosterRows);
|
|
1588
|
-
|
|
1606
|
+
// The 2,000-row activity query only feeds the Activity tab; switching to it refreshes.
|
|
1607
|
+
if (this.#section === "activity") this.#refreshActivityRows();
|
|
1589
1608
|
}
|
|
1590
1609
|
|
|
1591
1610
|
#refreshActivityData(refs: readonly TRecord[]): void {
|
|
@@ -1616,7 +1635,7 @@ export class AgentHubOverlayComponent<TRecord extends AgentRecordLike = AgentRec
|
|
|
1616
1635
|
void Promise.all(pending)
|
|
1617
1636
|
.then(() => {
|
|
1618
1637
|
if (this.#disposed || generation !== this.#activitySyncGeneration) return;
|
|
1619
|
-
this.#refreshActivityRows();
|
|
1638
|
+
if (this.#section === "activity") this.#refreshActivityRows();
|
|
1620
1639
|
this.#requestRender();
|
|
1621
1640
|
})
|
|
1622
1641
|
.catch(() => {
|