@deepseek-harness-tui/dsh-tui 0.10.2 → 0.11.1
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 +175 -123
- package/bin/dsh-tui.js +748 -22
- package/cordis.patch.yml +42 -13
- package/cordis.yml +5 -2
- package/lib/types/activityPrefs.d.ts +24 -0
- package/lib/types/activityPrefs.d.ts.map +1 -1
- package/lib/types/activityPrefs.js +50 -1
- package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
- package/lib/types/adapter/channel/session-projection.js +2 -0
- package/lib/types/adapter/channel/state.d.ts.map +1 -1
- package/lib/types/adapter/channel/state.js +3 -1
- package/lib/types/adapter/channel/ui-policy.d.ts +4 -1
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +6 -2
- package/lib/types/adapter/kernel/host-facade.d.ts.map +1 -1
- package/lib/types/adapter/kernel/host-facade.js +1 -0
- package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
- package/lib/types/adapter/kernel/replay.js +3 -0
- package/lib/types/adapter/kernel/runtime.d.ts.map +1 -1
- package/lib/types/adapter/kernel/runtime.js +2 -0
- package/lib/types/adapter/kernel/slices/workspace.d.ts.map +1 -1
- package/lib/types/adapter/kernel/slices/workspace.js +1 -0
- package/lib/types/adapter/ports/channel-ui.d.ts +29 -5
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +66 -12
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-workspace.d.ts +23 -0
- package/lib/types/adapter/ports/channel-workspace.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel.d.ts +4 -1
- package/lib/types/adapter/ports/channel.d.ts.map +1 -1
- package/lib/types/adapter/ports/workspace.d.ts +2 -0
- package/lib/types/adapter/ports/workspace.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.js +10 -2
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +1 -0
- package/lib/types/components/ActivityLine.d.ts +7 -2
- package/lib/types/components/ActivityLine.d.ts.map +1 -1
- package/lib/types/components/ActivityLine.js +0 -8
- package/lib/types/components/ContextBarView.d.ts +15 -7
- package/lib/types/components/ContextBarView.d.ts.map +1 -1
- package/lib/types/components/ContextBarView.js +26 -22
- package/lib/types/components/ImagePreviewOverlay.d.ts.map +1 -1
- package/lib/types/components/ImagePreviewOverlay.js +11 -5
- package/lib/types/components/Markdown.d.ts +11 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +20 -2
- package/lib/types/components/MermaidDiagram.d.ts +13 -0
- package/lib/types/components/MermaidDiagram.d.ts.map +1 -0
- package/lib/types/components/MermaidDiagram.js +61 -0
- package/lib/types/components/MessageList.d.ts +26 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +74 -8
- package/lib/types/components/PageMargin.d.ts +1 -1
- package/lib/types/components/PromptInput.d.ts +37 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +291 -30
- package/lib/types/components/ScrollbarGutter.d.ts +20 -5
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
- package/lib/types/components/ScrollbarGutter.js +88 -10
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +2 -1
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +30 -28
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +12 -6
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +8 -3
- package/lib/types/components/Tooltip.d.ts.map +1 -1
- package/lib/types/components/Tooltip.js +45 -7
- package/lib/types/components/design-system/HintLine.d.ts +1 -2
- package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
- package/lib/types/components/design-system/HintLine.js +1 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +30 -26
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +5 -7
- package/lib/types/components/messages/useImageInspection.d.ts.map +1 -1
- package/lib/types/components/messages/useImageInspection.js +19 -9
- package/lib/types/components/promptDraftCache.d.ts +102 -0
- package/lib/types/components/promptDraftCache.d.ts.map +1 -0
- package/lib/types/components/promptDraftCache.js +76 -0
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +17 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +40 -7
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts +12 -0
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts.map +1 -0
- package/lib/types/components/questions/QuestionMinimizedBar.js +43 -0
- package/lib/types/components/sessions/SessionListRow.d.ts +23 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +52 -5
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts +49 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts.map +1 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.js +50 -0
- package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
- package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
- package/lib/types/dsh-adapter/activity-store.js +359 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts +10 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -0
- package/lib/types/dsh-adapter/bundled-presets.js +80 -0
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.js +3 -0
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.js +19 -2
- package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +53 -29
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -6
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +5 -4
- package/lib/types/dsh-adapter/channel/binding.d.ts +19 -2
- package/lib/types/dsh-adapter/channel/binding.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding.js +78 -18
- package/lib/types/dsh-adapter/channel/compaction.d.ts +0 -1
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +0 -2
- package/lib/types/dsh-adapter/channel/composer-images.d.ts +5 -0
- package/lib/types/dsh-adapter/channel/composer-images.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/composer-images.js +105 -6
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts +8 -0
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/context-bookkeeping.js +3 -2
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts +58 -0
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/ide-selection.js +226 -0
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/input-delivery.js +9 -1
- package/lib/types/dsh-adapter/channel/local-actions.d.ts +3 -19
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +2 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-actions.js +82 -6
- package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +49 -31
- package/lib/types/dsh-adapter/channel/projection.d.ts +4 -0
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +29 -19
- package/lib/types/dsh-adapter/channel/reports.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/reports.js +4 -12
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
- package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-fork.js +26 -2
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.js +2 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +10 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +6 -4
- package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.js +0 -1
- package/lib/types/dsh-adapter/channel/session-resume.d.ts +12 -3
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +292 -94
- package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-rewind.js +34 -16
- package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.js +19 -3
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +4 -3
- package/lib/types/dsh-adapter/channel/state.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +3 -3
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +21 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +173 -6
- package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/transcript.js +6 -12
- package/lib/types/dsh-adapter/channel/types.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.js +41 -1
- package/lib/types/dsh-adapter/channel.d.ts +1 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +82 -20
- package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +1 -1
- package/lib/types/dsh-adapter/compat/messages.d.ts +15 -0
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/messages.js +15 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
- package/lib/types/dsh-adapter/compat/settings.d.ts +35 -0
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/settings.js +57 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts +25 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/shell.js +11 -0
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +17 -6
- package/lib/types/dsh-adapter/ide-channel.d.ts +224 -0
- package/lib/types/dsh-adapter/ide-channel.d.ts.map +1 -0
- package/lib/types/dsh-adapter/ide-channel.js +556 -0
- package/lib/types/dsh-adapter/index.d.ts +18 -3
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +32 -5
- package/lib/types/dsh-adapter/plugin.d.ts +4 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +197 -49
- package/lib/types/dsh-adapter/preset-resolution.d.ts +8 -0
- package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/preset-resolution.js +10 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts +53 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts.map +1 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.js +100 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessionTree.js +3 -2
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +7 -4
- package/lib/types/dsh-adapter/subagents.d.ts +16 -3
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +92 -29
- package/lib/types/dsh-adapter/workspaces.d.ts +46 -3
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +116 -0
- package/lib/types/effortPrefs.d.ts +15 -3
- package/lib/types/effortPrefs.d.ts.map +1 -1
- package/lib/types/effortPrefs.js +37 -3
- package/lib/types/history.d.ts +13 -1
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +15 -2
- package/lib/types/homePrefs.d.ts +15 -0
- package/lib/types/homePrefs.d.ts.map +1 -0
- package/lib/types/homePrefs.js +53 -0
- package/lib/types/i18n.d.ts +347 -297
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +133 -85
- package/lib/types/ink/colorize.d.ts +10 -0
- package/lib/types/ink/colorize.d.ts.map +1 -1
- package/lib/types/ink/colorize.js +21 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +12 -1
- package/lib/types/ink/dom.d.ts +1 -0
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts +5 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.js +15 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +36 -1
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +19 -1
- package/lib/types/ink/output.d.ts +10 -1
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +109 -17
- package/lib/types/ink/render-border.d.ts +6 -1
- package/lib/types/ink/render-border.d.ts.map +1 -1
- package/lib/types/ink/render-border.js +25 -9
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +48 -6
- package/lib/types/ink/renderer.d.ts +6 -0
- package/lib/types/ink/renderer.d.ts.map +1 -1
- package/lib/types/ink/renderer.js +2 -1
- package/lib/types/ink/selection.d.ts +88 -0
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +164 -0
- package/lib/types/ink/sixel-graphics.d.ts +19 -1
- package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
- package/lib/types/ink/sixel-graphics.js +124 -12
- package/lib/types/ink/terminal-image.d.ts +18 -1
- package/lib/types/ink/terminal-image.d.ts.map +1 -1
- package/lib/types/ink/terminal.d.ts +17 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +20 -1
- package/lib/types/screens/Chat.d.ts +20 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +296 -76
- package/lib/types/screens/SessionSupervisor.d.ts +84 -0
- package/lib/types/screens/SessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/SessionSupervisor.js +350 -0
- package/lib/types/screens/SessionTree.js +2 -2
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +32 -9
- package/lib/types/screens/StatusLine.d.ts +18 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +38 -19
- package/lib/types/screens/StatusMetrics.d.ts +79 -22
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
- package/lib/types/screens/StatusMetrics.js +153 -88
- package/lib/types/screens/sessionSupervisor/model.d.ts +83 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/model.js +69 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +120 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +593 -0
- package/lib/types/sessionMounts.d.ts +272 -0
- package/lib/types/sessionMounts.d.ts.map +1 -0
- package/lib/types/sessionMounts.js +706 -0
- package/lib/types/sessions/format.d.ts.map +1 -1
- package/lib/types/sessions/format.js +4 -1
- package/lib/types/sessions/resumeFailure.d.ts +38 -0
- package/lib/types/sessions/resumeFailure.d.ts.map +1 -0
- package/lib/types/sessions/resumeFailure.js +58 -0
- package/lib/types/terminal-utils/mermaid.d.ts +44 -0
- package/lib/types/terminal-utils/mermaid.d.ts.map +1 -0
- package/lib/types/terminal-utils/mermaid.js +83 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +175 -19
- package/lib/types/tuiDisplayPrefs.d.ts +7 -9
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +31 -28
- package/lib/types/update.d.ts +61 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +194 -0
- package/lib/types/utils/fold-long-lines.d.ts +1 -1
- package/lib/types/utils/fold-long-lines.js +1 -1
- package/lib/types/utils/imageResize.d.ts +90 -0
- package/lib/types/utils/imageResize.d.ts.map +1 -0
- package/lib/types/utils/imageResize.js +272 -0
- package/lib/types/utils/keymap.d.ts +5 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +23 -0
- package/lib/types/working-activity.d.ts +10 -9
- package/lib/types/working-activity.d.ts.map +1 -1
- package/lib/types/working-activity.js +17 -10
- package/lib/types/workspaces.d.ts +2 -1
- package/lib/types/workspaces.d.ts.map +1 -1
- package/lib/types/workspaces.js +1 -1
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +10 -10
- package/package.json +126 -105
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/agent.cordis.yml +15 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
- package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
- package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
- package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
- package/lib/types/dsh-adapter/channel/activity.js +0 -113
- package/lib/types/screens/AgentView.d.ts +0 -23
- package/lib/types/screens/AgentView.d.ts.map +0 -1
- package/lib/types/screens/AgentView.js +0 -546
- package/lib/types/screens/SessionBrowser.d.ts +0 -42
- package/lib/types/screens/SessionBrowser.d.ts.map +0 -1
- package/lib/types/screens/SessionBrowser.js +0 -911
- package/lib/types/terminal-utils/terminal.d.ts +0 -18
- package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
- package/lib/types/terminal-utils/terminal.js +0 -96
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
3
3
|
import type { ContextMenuEvent } from '../../ink/events/context-menu-event.js';
|
|
4
4
|
import type { SessionSummary } from '../../dsh-adapter/sessions/index.js';
|
|
5
|
+
import type { AgentViewStatus } from '../../adapter/ports/channel-view.js';
|
|
5
6
|
/**
|
|
6
7
|
* One session in the browser's list: a title line and a metadata line.
|
|
7
8
|
*
|
|
@@ -15,7 +16,7 @@ import type { SessionSummary } from '../../dsh-adapter/sessions/index.js';
|
|
|
15
16
|
* stay exactly two lines at every terminal width, and a row that wraps
|
|
16
17
|
* destroys the alignment that lets the eye scan a list at all.
|
|
17
18
|
*/
|
|
18
|
-
export declare function SessionListRow({ session, width, depth, focused, pinned, now, onClick, onContextMenu, onTogglePin, }: {
|
|
19
|
+
export declare function SessionListRow({ session, width, depth, focused, pinned, now, onClick, onContextMenu, onTogglePin, liveStatus, current, occupiedPid, spinner, }: {
|
|
19
20
|
session: SessionSummary;
|
|
20
21
|
/** Columns available to the row, indentation included. */
|
|
21
22
|
width: number;
|
|
@@ -32,5 +33,26 @@ export declare function SessionListRow({ session, width, depth, focused, pinned,
|
|
|
32
33
|
onContextMenu?(event: ContextMenuEvent): void;
|
|
33
34
|
/** 点击行内 ★/☆(fullscreen):切换固定状态,不冒泡成"打开会话"。 */
|
|
34
35
|
onTogglePin?(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Live status of an agent THIS terminal is running, when there is one.
|
|
38
|
+
* `working` animates instead of holding a static glyph, so a busy session
|
|
39
|
+
* is legible at a glance — the same vocabulary the session overview uses,
|
|
40
|
+
* which is what lets the two surfaces read as one feature.
|
|
41
|
+
*/
|
|
42
|
+
liveStatus?: AgentViewStatus;
|
|
43
|
+
/** True when this is the session the terminal is attached to. */
|
|
44
|
+
current?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The pid of ANOTHER TUI terminal holding this session, when one does. The
|
|
47
|
+
* row turns red and says so: the session stays visible but cannot be
|
|
48
|
+
* entered, which is the honest presentation of a claim this process must
|
|
49
|
+
* not break. Undefined means free, or already ours.
|
|
50
|
+
*/
|
|
51
|
+
occupiedPid?: number;
|
|
52
|
+
/** Shared animation clock for the working glyph. */
|
|
53
|
+
spinner?: {
|
|
54
|
+
frame: number;
|
|
55
|
+
time: number;
|
|
56
|
+
};
|
|
35
57
|
}): React.ReactNode;
|
|
36
58
|
//# sourceMappingURL=SessionListRow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionListRow.d.ts","sourceRoot":"","sources":["../../../../src/components/sessions/SessionListRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;
|
|
1
|
+
{"version":3,"file":"SessionListRow.d.ts","sourceRoot":"","sources":["../../../../src/components/sessions/SessionListRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;AAY9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AA0B1E;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,GAAG,EACH,OAAO,EACP,aAAa,EACb,WAAW,EACX,UAAU,EACV,OAAO,EACP,WAAW,EACX,OAAO,GACR,EAAE;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,sEAAsE;IACtE,MAAM,EAAE,OAAO,CAAA;IACf,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,4CAA4C;IAC5C,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC,gDAAgD;IAChD,aAAa,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC7C,8CAA8C;IAC9C,WAAW,CAAC,IAAI,IAAI,CAAA;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAC1C,GAAG,KAAK,CAAC,SAAS,CA6HlB"}
|
|
@@ -3,7 +3,31 @@ import { useState } from 'react';
|
|
|
3
3
|
import { Box, Text } from '../../ui.js';
|
|
4
4
|
import { t } from '../../i18n.js';
|
|
5
5
|
import { useTooltip } from '../Tooltip.js';
|
|
6
|
+
import { SpinnerGlyph } from '../Spinner/SpinnerGlyph.js';
|
|
7
|
+
import { stringWidth } from '../../ink/stringWidth.js';
|
|
6
8
|
import { formatAbsolute, formatBytes, formatWhen, kindMark, titleColor, truncateWidth, } from '../../sessions/format.js';
|
|
9
|
+
/**
|
|
10
|
+
* State presentation for a session this terminal is running: one glyph and one
|
|
11
|
+
* theme colour per status, matching the session overview's own vocabulary so
|
|
12
|
+
* the same session never looks like two different things on two screens.
|
|
13
|
+
* `stopped` is the "not running here" spelling and draws dim.
|
|
14
|
+
*/
|
|
15
|
+
const LIVE_STATUS_GLYPH = {
|
|
16
|
+
'needs-input': '✻',
|
|
17
|
+
working: '✽',
|
|
18
|
+
completed: '✓',
|
|
19
|
+
failed: '✕',
|
|
20
|
+
idle: '∙',
|
|
21
|
+
stopped: '∙',
|
|
22
|
+
};
|
|
23
|
+
const LIVE_STATUS_COLOR = {
|
|
24
|
+
'needs-input': 'warning',
|
|
25
|
+
working: 'suggestion',
|
|
26
|
+
completed: 'success',
|
|
27
|
+
failed: 'error',
|
|
28
|
+
idle: undefined,
|
|
29
|
+
stopped: undefined,
|
|
30
|
+
};
|
|
7
31
|
/**
|
|
8
32
|
* One session in the browser's list: a title line and a metadata line.
|
|
9
33
|
*
|
|
@@ -17,7 +41,7 @@ import { formatAbsolute, formatBytes, formatWhen, kindMark, titleColor, truncate
|
|
|
17
41
|
* stay exactly two lines at every terminal width, and a row that wraps
|
|
18
42
|
* destroys the alignment that lets the eye scan a list at all.
|
|
19
43
|
*/
|
|
20
|
-
export function SessionListRow({ session, width, depth, focused, pinned, now, onClick, onContextMenu, onTogglePin, }) {
|
|
44
|
+
export function SessionListRow({ session, width, depth, focused, pinned, now, onClick, onContextMenu, onTogglePin, liveStatus, current, occupiedPid, spinner, }) {
|
|
21
45
|
const indent = depth * 2;
|
|
22
46
|
// Two cells for the focus marker, plus the indent for a nested run.
|
|
23
47
|
const body = Math.max(8, width - 2 - indent);
|
|
@@ -30,10 +54,28 @@ export function SessionListRow({ session, width, depth, focused, pinned, now, on
|
|
|
30
54
|
// and never the working directory, so that pair is always new information
|
|
31
55
|
// for telling look-alike sessions apart.
|
|
32
56
|
const titleText = session.label ?? session.title.text;
|
|
33
|
-
|
|
34
|
-
|
|
57
|
+
/**
|
|
58
|
+
* The state cell holds EXACTLY two columns on every row, occupied or not,
|
|
59
|
+
* for the same reason the pin slot does: a column that appears only when a
|
|
60
|
+
* session is busy would shift every title on screen each time one starts or
|
|
61
|
+
* stops working.
|
|
62
|
+
*/
|
|
63
|
+
const occupied = occupiedPid !== undefined;
|
|
64
|
+
const stateGlyph = occupied ? '⊘' : LIVE_STATUS_GLYPH[liveStatus ?? 'stopped'];
|
|
65
|
+
const stateColor = occupied
|
|
66
|
+
? 'error'
|
|
67
|
+
: liveStatus === undefined
|
|
68
|
+
? undefined
|
|
69
|
+
: LIVE_STATUS_COLOR[liveStatus];
|
|
70
|
+
const occupiedText = occupied ? ` ${t('supervisor-occupied-badge', { pid: occupiedPid })}` : '';
|
|
71
|
+
const currentText = current === true ? ` ${t('supervisor-current')}` : '';
|
|
72
|
+
const titleBudget = body - 2 - (mark === undefined ? 0 : 2) - 2
|
|
73
|
+
- stringWidth(occupiedText) - stringWidth(currentText);
|
|
74
|
+
const shownTitle = truncateWidth(titleText, Math.max(4, titleBudget));
|
|
35
75
|
const titleTooltip = useTooltip(() => {
|
|
36
76
|
const parts = [];
|
|
77
|
+
if (occupied)
|
|
78
|
+
parts.push(t('session-mount-occupied-short', { pid: occupiedPid }));
|
|
37
79
|
if (shownTitle !== titleText)
|
|
38
80
|
parts.push(titleText);
|
|
39
81
|
parts.push(formatAbsolute(session.updatedAt));
|
|
@@ -52,10 +94,15 @@ export function SessionListRow({ session, width, depth, focused, pinned, now, on
|
|
|
52
94
|
if (session.childCount > 0 && depth === 0) {
|
|
53
95
|
facts.push(t('session-children', { n: session.childCount }));
|
|
54
96
|
}
|
|
55
|
-
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, onClick: onClick, onContextMenu: onContextMenu, onMouseEnter: onClick !== undefined || onContextMenu !== undefined ? () => setHovered(true) : undefined, onMouseLeave: onClick !== undefined || onContextMenu !== undefined ? () => setHovered(false) : undefined,
|
|
97
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, onClick: onClick, onContextMenu: onContextMenu, onMouseEnter: onClick !== undefined || onContextMenu !== undefined ? () => setHovered(true) : undefined, onMouseLeave: onClick !== undefined || onContextMenu !== undefined ? () => setHovered(false) : undefined,
|
|
98
|
+
// Hover is the BLUE prompt — pointer feedback and nothing else. Selection
|
|
99
|
+
// is green and never blue: a row the keyboard cursor is on must not look
|
|
100
|
+
// like a row the mouse happens to be over, so the two never share a
|
|
101
|
+
// background and a selected row keeps its own colour while hovered.
|
|
102
|
+
backgroundColor: hovered && !focused ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { children: [_jsx(Text, { color: focused ? 'success' : 'subtle', children: `${' '.repeat(indent)}${focused ? '❯ ' : ' '}` }), _jsx(Box, { ...pinTooltip, onClick: onTogglePin === undefined ? undefined : (event) => {
|
|
56
103
|
// The star is a control on the row, not the row: a click here
|
|
57
104
|
// toggles the pin and must never fall through to resume.
|
|
58
105
|
event.stopImmediatePropagation();
|
|
59
106
|
onTogglePin();
|
|
60
|
-
}, children: _jsx(Text, { color: pinned ? 'remember' : undefined, dimColor: !pinned, children: pinned ? '★ ' : '☆ ' }) }), mark !== undefined && _jsx(Text, { color: mark.color, children: `${mark.glyph} ` }), _jsx(Box, { ...titleTooltip, children: _jsx(Text, { color: titleColor(session.title.source, focused), bold: focused, children: shownTitle }) })] }), _jsx(Box, { children: _jsx(Text, { dimColor:
|
|
107
|
+
}, children: _jsx(Text, { color: pinned ? 'remember' : undefined, dimColor: !pinned, children: pinned ? '★ ' : '☆ ' }) }), _jsx(Box, { children: liveStatus === 'working' && !occupied && spinner !== undefined ? (_jsx(SpinnerGlyph, { frame: spinner.frame, messageColor: "suggestion", reducedMotion: false, time: spinner.time })) : (_jsx(Text, { color: stateColor, dimColor: liveStatus === undefined && !occupied, children: `${stateGlyph} ` })) }), mark !== undefined && _jsx(Text, { color: mark.color, children: `${mark.glyph} ` }), _jsx(Box, { ...titleTooltip, children: _jsx(Text, { color: occupied ? 'error' : titleColor(session.title.source, focused), bold: focused, children: shownTitle }) }), occupiedText !== '' && _jsx(Text, { color: "error", children: occupiedText }), currentText !== '' && _jsx(Text, { color: "success", children: currentText })] }), _jsx(Box, { children: _jsx(Text, { color: focused ? 'success' : undefined, dimColor: !focused, children: `${' '.repeat(indent + 2)}${truncateWidth(facts.join(' · '), body)}` }) })] }));
|
|
61
108
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ClickEvent } from '../../ink/events/click-event.js';
|
|
3
|
+
import type { ContextMenuEvent } from '../../ink/events/context-menu-event.js';
|
|
4
|
+
/**
|
|
5
|
+
* One workspace in the home screen's left rail.
|
|
6
|
+
*
|
|
7
|
+
* Two lines, like every other navigable row in this app: the name line is what
|
|
8
|
+
* the user named it, the detail line is where it actually is and how much is in
|
|
9
|
+
* it. The path is not decoration — two workspaces can carry the same basename
|
|
10
|
+
* (`.../a/work` and `.../b/work`), and the ledger allows duplicate titles, so
|
|
11
|
+
* the path is the only thing that tells them apart.
|
|
12
|
+
*
|
|
13
|
+
* Widths are resolved here rather than left to flexbox for the same reason the
|
|
14
|
+
* session rows resolve them: a row must be exactly two lines at every terminal
|
|
15
|
+
* width, and a wrapped row destroys the alignment a list is scanned by.
|
|
16
|
+
*/
|
|
17
|
+
export declare function HomeWorkspaceRow({ title, path, home, sessionCount, present, selected, focused, width, onSelect, onMenu, }: {
|
|
18
|
+
title: string;
|
|
19
|
+
/** Canonical directory path recorded in the ledger. */
|
|
20
|
+
path: string;
|
|
21
|
+
/** Home directory, for collapsing the path to `~`. */
|
|
22
|
+
home: string;
|
|
23
|
+
sessionCount: number;
|
|
24
|
+
/** False when the recorded directory no longer exists. */
|
|
25
|
+
present: boolean;
|
|
26
|
+
/** Whether this workspace's sessions are the ones on the right. */
|
|
27
|
+
selected: boolean;
|
|
28
|
+
/** Keyboard cursor. */
|
|
29
|
+
focused: boolean;
|
|
30
|
+
/** Columns available to the row. */
|
|
31
|
+
width: number;
|
|
32
|
+
/** Left click: show this workspace's sessions (same path as Enter). */
|
|
33
|
+
onSelect?(event: ClickEvent): void;
|
|
34
|
+
/** Right click: open the workspace action menu. */
|
|
35
|
+
onMenu?(event: ContextMenuEvent): void;
|
|
36
|
+
}): React.ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* The `+` row that opens the directory picker.
|
|
39
|
+
*
|
|
40
|
+
* Deliberately the FIRST row of the rail and always clickable: adding a
|
|
41
|
+
* workspace is the rail's only creation action, and a control that is only
|
|
42
|
+
* reachable by keyboard is a control most users never find in a terminal.
|
|
43
|
+
*/
|
|
44
|
+
export declare function HomeAddWorkspaceRow({ focused, width, onOpen, }: {
|
|
45
|
+
focused: boolean;
|
|
46
|
+
width: number;
|
|
47
|
+
onOpen?(event: ClickEvent): void;
|
|
48
|
+
}): React.ReactNode;
|
|
49
|
+
//# sourceMappingURL=HomeWorkspaceRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HomeWorkspaceRow.d.ts","sourceRoot":"","sources":["../../../../src/components/workspaces/HomeWorkspaceRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAGvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;AAG9E;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,OAAO,EACP,KAAK,EACL,QAAQ,EACR,MAAM,GACP,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAA;IAChB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAA;IACjB,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,QAAQ,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IAClC,mDAAmD;IACnD,MAAM,CAAC,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAA;CACvC,GAAG,KAAK,CAAC,SAAS,CAuClB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,KAAK,EACL,MAAM,GACP,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;CACjC,GAAG,KAAK,CAAC,SAAS,CAoBlB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text } from '../../ui.js';
|
|
4
|
+
import { t } from '../../i18n.js';
|
|
5
|
+
import { formatProject, spreadRow, truncateWidth } from '../../sessions/format.js';
|
|
6
|
+
/**
|
|
7
|
+
* One workspace in the home screen's left rail.
|
|
8
|
+
*
|
|
9
|
+
* Two lines, like every other navigable row in this app: the name line is what
|
|
10
|
+
* the user named it, the detail line is where it actually is and how much is in
|
|
11
|
+
* it. The path is not decoration — two workspaces can carry the same basename
|
|
12
|
+
* (`.../a/work` and `.../b/work`), and the ledger allows duplicate titles, so
|
|
13
|
+
* the path is the only thing that tells them apart.
|
|
14
|
+
*
|
|
15
|
+
* Widths are resolved here rather than left to flexbox for the same reason the
|
|
16
|
+
* session rows resolve them: a row must be exactly two lines at every terminal
|
|
17
|
+
* width, and a wrapped row destroys the alignment a list is scanned by.
|
|
18
|
+
*/
|
|
19
|
+
export function HomeWorkspaceRow({ title, path, home, sessionCount, present, selected, focused, width, onSelect, onMenu, }) {
|
|
20
|
+
const [hovered, setHovered] = useState(false);
|
|
21
|
+
const body = Math.max(8, width - 4);
|
|
22
|
+
// The presence marker leads the badge on purpose: `spreadRow` may truncate
|
|
23
|
+
// the right-hand segment, and "this directory is gone" is the one fact that
|
|
24
|
+
// must never be the part that gets cut (the session count is also visible in
|
|
25
|
+
// the pane, the missing directory is not).
|
|
26
|
+
const count = t('home-sessions-count', { n: sessionCount });
|
|
27
|
+
const badge = present ? count : `${t('home-workspace-missing')} · ${count}`;
|
|
28
|
+
const heading = spreadRow(`${selected ? '▣' : '▢'} ${title}`, `${selected ? '✓ ' : ''}${badge}`, body);
|
|
29
|
+
const detail = formatProject(path, home);
|
|
30
|
+
// The cursor (green) outranks the selection ring (green); both outrank the
|
|
31
|
+
// idle colour. Blue is not part of this ladder at all — see the background.
|
|
32
|
+
const headingColor = (focused || selected) ? 'success' : present ? 'text' : 'inactive';
|
|
33
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, paddingX: 1, onClick: onSelect, onContextMenu: onMenu, onMouseEnter: onSelect === undefined && onMenu === undefined ? undefined : () => setHovered(true), onMouseLeave: onSelect === undefined && onMenu === undefined ? undefined : () => setHovered(false),
|
|
34
|
+
// Hover is the BLUE prompt — pointer feedback and nothing else, so it
|
|
35
|
+
// never marks the focused or the selected row. Selection itself is green
|
|
36
|
+
// in the text, which is why this row draws no box while selected.
|
|
37
|
+
backgroundColor: hovered && !focused ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Text, { color: focused ? 'success' : 'subtle', children: focused ? '❯ ' : ' ' }), _jsx(Text, { color: headingColor, bold: focused || selected, children: heading.left }), _jsx(Text, { dimColor: !focused, children: `${' '.repeat(heading.gap)}${heading.right}` })] }), _jsx(Text, { color: (focused || selected) ? 'success' : undefined, dimColor: !(focused || selected), wrap: "truncate-end", children: ` ${truncateWidth(detail, body - 2)}` })] }));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The `+` row that opens the directory picker.
|
|
41
|
+
*
|
|
42
|
+
* Deliberately the FIRST row of the rail and always clickable: adding a
|
|
43
|
+
* workspace is the rail's only creation action, and a control that is only
|
|
44
|
+
* reachable by keyboard is a control most users never find in a terminal.
|
|
45
|
+
*/
|
|
46
|
+
export function HomeAddWorkspaceRow({ focused, width, onOpen, }) {
|
|
47
|
+
const [hovered, setHovered] = useState(false);
|
|
48
|
+
const body = Math.max(8, width - 4);
|
|
49
|
+
return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, paddingX: 1, onClick: onOpen, onMouseEnter: onOpen === undefined ? undefined : () => setHovered(true), onMouseLeave: onOpen === undefined ? undefined : () => setHovered(false), backgroundColor: focused || hovered ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { height: 1, flexShrink: 0, overflow: "hidden", children: [_jsx(Text, { color: focused ? 'suggestion' : 'subtle', children: focused ? '❯ ' : ' ' }), _jsx(Text, { color: "remember", bold: true, children: `+ ${t('home-add-workspace')}` })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: ` ${truncateWidth(t('home-add-hint'), body - 2)}` })] }));
|
|
50
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped activity snapshots for the working-status line.
|
|
3
|
+
*
|
|
4
|
+
* The line's *semantics* belong to the `dsh-working-activity` plugin: it folds
|
|
5
|
+
* durable session events and live model frames into a **session projection**
|
|
6
|
+
* (`workingActivity`) that any client can read — the browser reads it, and so
|
|
7
|
+
* does this TUI. Consuming the projection is what removes the second tracker
|
|
8
|
+
* this app used to run: one semantic owner, and a value that arrives already
|
|
9
|
+
* scoped to a session, so a background session can no longer overwrite the line
|
|
10
|
+
* of the session on screen.
|
|
11
|
+
*
|
|
12
|
+
* Two properties of the transport shape this module:
|
|
13
|
+
*
|
|
14
|
+
* 1. **It is event-driven.** A value changes when a committed event folds, never
|
|
15
|
+
* on its own. `updatedAt` is the timestamp of the last folded event (session
|
|
16
|
+
* time, so it survives a restart) and `live` says whether `line` counts
|
|
17
|
+
* elapsed time. A renderer that wants the counter to move must derive it from
|
|
18
|
+
* `turnStartedAt` / `phaseStartedAt` instead of re-rendering `line`.
|
|
19
|
+
* 2. **The value is host data, not plugin API.** The shape below is a local
|
|
20
|
+
* structural copy of the plugin's wire value, the same discipline the channel
|
|
21
|
+
* port already applies to the activity state: this app must not import the
|
|
22
|
+
* plugin's internals to display a line.
|
|
23
|
+
* @module dsh-tui/dsh-adapter/activity-store
|
|
24
|
+
*/
|
|
25
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
26
|
+
/** The projection key the activity plugin publishes. */
|
|
27
|
+
export declare const ACTIVITY_PROJECTION_KEY = "workingActivity";
|
|
28
|
+
/** Phases the plugin's line can be in (`idle` renders nothing). */
|
|
29
|
+
export type ActivityPhase = 'idle' | 'waiting' | 'thinking' | 'tool' | 'done';
|
|
30
|
+
/**
|
|
31
|
+
* One session's activity value, as the plugin publishes it.
|
|
32
|
+
*
|
|
33
|
+
* Structural copy of `dsh-working-activity`'s `WorkingActivityView`.
|
|
34
|
+
*/
|
|
35
|
+
export interface ActivityView {
|
|
36
|
+
readonly phase: ActivityPhase;
|
|
37
|
+
/** The line as the host rendered it at `updatedAt`. */
|
|
38
|
+
readonly line: string;
|
|
39
|
+
/** Whether `line` counts elapsed time (a renderer ticks it from the stamps). */
|
|
40
|
+
readonly live: boolean;
|
|
41
|
+
/** Tool action verb, when the line describes a running tool. */
|
|
42
|
+
readonly label?: string;
|
|
43
|
+
/** Tool detail fragment (path / command / pattern), when there is one. */
|
|
44
|
+
readonly detail?: string;
|
|
45
|
+
/** The playful phrase or `⏵` self-narration currently shown, when any. */
|
|
46
|
+
readonly phrase?: string;
|
|
47
|
+
/** Tools completed in the current turn. */
|
|
48
|
+
readonly toolCount: number;
|
|
49
|
+
/** Wall clock the current phase began. */
|
|
50
|
+
readonly phaseStartedAt: number;
|
|
51
|
+
/** Wall clock the current turn began (0 when no turn has started). */
|
|
52
|
+
readonly turnStartedAt: number;
|
|
53
|
+
/** Timestamp of the last folded event — the value's freshness signal. */
|
|
54
|
+
readonly updatedAt: number;
|
|
55
|
+
/** Language the line was rendered in. */
|
|
56
|
+
readonly lang: 'zh' | 'en';
|
|
57
|
+
}
|
|
58
|
+
/** The slice of the host projection registry this module uses. */
|
|
59
|
+
export interface ProjectionRegistryLike {
|
|
60
|
+
onChanged(listener: (session: {
|
|
61
|
+
readonly id: unknown;
|
|
62
|
+
}, key: string, value: unknown, seq: number) => void): () => void;
|
|
63
|
+
snapshot(session: unknown, keys?: readonly string[]): {
|
|
64
|
+
readonly values: Record<string, unknown>;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Narrow one projection value: anything that is not an activity view is
|
|
69
|
+
* dropped rather than rendered half-formed.
|
|
70
|
+
* @param value - Raw projection value.
|
|
71
|
+
* @returns the value as an activity view, or `undefined`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function asActivityView(value: unknown): ActivityView | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* The latest activity value for the session on screen, with a subscription
|
|
76
|
+
* for renderers.
|
|
77
|
+
*
|
|
78
|
+
* The store is effectively single-current: binding a session ({@link
|
|
79
|
+
* ActivityStore.seed}) names the session the UI is showing, and every other
|
|
80
|
+
* id is dropped — values, session objects and read-failure counts alike. A
|
|
81
|
+
* registry-less store (the UI's fallback, test rigs) has no current session
|
|
82
|
+
* and keeps today's accept-all behavior.
|
|
83
|
+
*/
|
|
84
|
+
export declare class ActivityStore {
|
|
85
|
+
private readonly values;
|
|
86
|
+
/** Session objects seen for each id, so a live value can be re-read. */
|
|
87
|
+
private readonly sessions;
|
|
88
|
+
/** Consecutive failed reads per session id; reset by a successful read. */
|
|
89
|
+
private readonly readFailures;
|
|
90
|
+
/** Sessions already warned about (see {@link noteReadFailure}): once each. */
|
|
91
|
+
private readonly warned;
|
|
92
|
+
private readonly listeners;
|
|
93
|
+
/** The session the UI is showing (the last {@link seed}); the only id kept. */
|
|
94
|
+
private currentId;
|
|
95
|
+
/** Host registry, remembered so a bind can read a baseline on demand. */
|
|
96
|
+
private registry;
|
|
97
|
+
/** Warn sink (see {@link noteReadFailure}); injected by the composition root. */
|
|
98
|
+
private readonly warn;
|
|
99
|
+
constructor(warn?: (message: string) => void);
|
|
100
|
+
/** Remember the host registry (see {@link seed} and {@link refreshLive}). */
|
|
101
|
+
attachRegistry(registry: ProjectionRegistryLike): void;
|
|
102
|
+
/**
|
|
103
|
+
* Seed one session from the registry's current snapshot and make it the
|
|
104
|
+
* current one.
|
|
105
|
+
*
|
|
106
|
+
* A value only *arrives* when it changes, so a session opened after its last
|
|
107
|
+
* change — a resume, or a window reattached to a running agent — would show
|
|
108
|
+
* nothing until the next event without this read. The bind also defines the
|
|
109
|
+
* session on screen: every other id is pruned, so a later event — or the
|
|
110
|
+
* tick — for a session the user switched away from can no longer fill this
|
|
111
|
+
* store or keep a timer armed.
|
|
112
|
+
* @param session - Session being bound.
|
|
113
|
+
*/
|
|
114
|
+
seed(session: unknown): void;
|
|
115
|
+
/**
|
|
116
|
+
* Note the session object behind an id, so a live value can be re-read.
|
|
117
|
+
* Dropped for any id other than the current one (see {@link seed}). */
|
|
118
|
+
remember(sessionId: string, session: unknown): void;
|
|
119
|
+
/**
|
|
120
|
+
* Re-read the current session's value while it is still counting time.
|
|
121
|
+
*
|
|
122
|
+
* The host renders the value when it is *read*, so this is what makes the
|
|
123
|
+
* elapsed seconds advance between committed events — with the host's own copy
|
|
124
|
+
* and language, since nothing is re-rendered here. A value that has settled
|
|
125
|
+
* (`live` false: idle, or a finished turn) is deliberately skipped: its text
|
|
126
|
+
* cannot change on its own. Only the current session can be live (see
|
|
127
|
+
* {@link seed}), so the tick never polls a session the user left.
|
|
128
|
+
*/
|
|
129
|
+
refreshLive(): void;
|
|
130
|
+
/** Whether the current session's value is still counting time (see {@link refreshLive}). */
|
|
131
|
+
hasLive(): boolean;
|
|
132
|
+
/** The current value for one session, stable between updates. */
|
|
133
|
+
get(sessionId: string | undefined): ActivityView | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Record one projection value. Dropped for any id other than the current
|
|
136
|
+
* one (see {@link seed}).
|
|
137
|
+
* @param sessionId - Session the value belongs to.
|
|
138
|
+
* @param view - The published value.
|
|
139
|
+
*/
|
|
140
|
+
update(sessionId: string, view: ActivityView): void;
|
|
141
|
+
/** Forget one session (disposed, or left behind by a reset). */
|
|
142
|
+
clear(sessionId: string): void;
|
|
143
|
+
/** A read succeeded: this session's consecutive-failure count restarts. */
|
|
144
|
+
noteReadSuccess(sessionId: string): void;
|
|
145
|
+
/**
|
|
146
|
+
* A read failed. The failure is reported to the warn sink ONCE per session
|
|
147
|
+
* (the sink is the composition root's logger — this module stays free of
|
|
148
|
+
* cordis types), and after {@link MAX_READ_FAILURES} consecutive failures
|
|
149
|
+
* the value is cleared so the tick disarms instead of polling a registry
|
|
150
|
+
* that will never answer.
|
|
151
|
+
* @param sessionId - Session whose read failed.
|
|
152
|
+
* @param detail - What the failed read threw.
|
|
153
|
+
*/
|
|
154
|
+
noteReadFailure(sessionId: string, detail: string): void;
|
|
155
|
+
/** Drop every id that is not the current one; emit when a value went. */
|
|
156
|
+
private pruneToCurrent;
|
|
157
|
+
/** Subscribe to value changes; returns the unsubscribe function. */
|
|
158
|
+
subscribe(listener: () => void): () => void;
|
|
159
|
+
private emit;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The change-feed listener for one store.
|
|
163
|
+
*
|
|
164
|
+
* Only this plugin's key is read, and only values that narrow to an activity
|
|
165
|
+
* view are accepted: the feed is host-wide, so every other unit's change and
|
|
166
|
+
* every malformed value must be dropped here rather than inside a renderer.
|
|
167
|
+
* @param store - Store to fill.
|
|
168
|
+
* @returns the listener to hand to `ProjectionRegistry.onChanged`.
|
|
169
|
+
*/
|
|
170
|
+
export declare function createActivityFeed(store: ActivityStore): (session: {
|
|
171
|
+
readonly id: unknown;
|
|
172
|
+
}, key: string, value: unknown) => void;
|
|
173
|
+
/** How often a value that is still counting time is re-read from the host. */
|
|
174
|
+
export declare const LIVE_TICK_MS = 500;
|
|
175
|
+
/**
|
|
176
|
+
* Wire one store to the host's projection registry.
|
|
177
|
+
*
|
|
178
|
+
* Registration is deferred through `inject` because the plugin that *publishes*
|
|
179
|
+
* the unit is mounted alongside this one: the registry may not exist yet, and
|
|
180
|
+
* the unit may not be registered until later still. Both absences are normal —
|
|
181
|
+
* a composition without the activity plugin simply never fills the store, and
|
|
182
|
+
* the line falls back to whatever else the UI has.
|
|
183
|
+
*
|
|
184
|
+
* The feed is event-driven, so a value only lands when a committed event folds;
|
|
185
|
+
* its elapsed text would therefore freeze for the length of a long tool. The
|
|
186
|
+
* host renders a value when it is READ, so a timer re-reads the live ones: the
|
|
187
|
+
* seconds advance, the copy and language stay the plugin's, and a settled value
|
|
188
|
+
* (idle, or a finished turn) stops the timer instead of being polled forever.
|
|
189
|
+
* @param ctx - Host context of the composition root.
|
|
190
|
+
* @param store - Store to fill.
|
|
191
|
+
*/
|
|
192
|
+
export declare function attachActivityProjection(ctx: Context, store: ActivityStore): void;
|
|
193
|
+
/**
|
|
194
|
+
* Create the composition root's activity store and wire it to the host.
|
|
195
|
+
* @param ctx - Host context of the composition root.
|
|
196
|
+
* @param enabled - Whether the working line is shown at all (cordis.yml
|
|
197
|
+
* `activity`; a static, config-time switch — the runtime `/activity` command
|
|
198
|
+
* only changes the preset). With the line off, nothing attaches: no feed,
|
|
199
|
+
* no registry, and therefore no 500ms tick for a line nobody renders.
|
|
200
|
+
* @returns the store the UI reads from.
|
|
201
|
+
*/
|
|
202
|
+
export declare function createActivityStore(ctx: Context, enabled: boolean): ActivityStore;
|
|
203
|
+
/**
|
|
204
|
+
* Read one session's activity value in a component.
|
|
205
|
+
* @param store - Store to read.
|
|
206
|
+
* @param sessionId - Session the UI is showing.
|
|
207
|
+
* @returns the current value, or `undefined` when there is none.
|
|
208
|
+
*/
|
|
209
|
+
export declare function useActivity(store: ActivityStore, sessionId: string | undefined): ActivityView | undefined;
|
|
210
|
+
/**
|
|
211
|
+
* Seed one session's value from the registry's current snapshot.
|
|
212
|
+
*
|
|
213
|
+
* A value only *arrives* when it changes, so a session opened after its last
|
|
214
|
+
* change — a resume, or a window reattached to a running agent — would show
|
|
215
|
+
* nothing until the next event without this read.
|
|
216
|
+
* @param registry - Host projection registry.
|
|
217
|
+
* @param store - Store to fill.
|
|
218
|
+
* @param session - Session to read.
|
|
219
|
+
*/
|
|
220
|
+
export declare function seedActivity(registry: ProjectionRegistryLike | undefined, store: ActivityStore, session: unknown): void;
|
|
221
|
+
//# sourceMappingURL=activity-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-store.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/activity-store.ts"],"names":[],"mappings":"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"}
|