@deepseek-harness-tui/dsh-tui 0.15.0 → 0.16.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 +98 -8
- package/guide/dsh-tui-guide/claude-backend.en.md +8 -0
- package/guide/dsh-tui-guide/claude-backend.md +5 -0
- package/guide/dsh-tui-guide/codex-backend.en.md +13 -3
- package/guide/dsh-tui-guide/codex-backend.md +9 -2
- package/guide/dsh-tui-guide/configuration.en.md +39 -2
- package/guide/dsh-tui-guide/configuration.md +34 -2
- package/guide/dsh-tui-guide/getting-started.en.md +32 -9
- package/guide/dsh-tui-guide/getting-started.md +27 -8
- package/guide/dsh-tui-guide/interaction.en.md +8 -1
- package/guide/dsh-tui-guide/interaction.md +8 -1
- package/guide/dsh-tui-guide/plugins.en.md +66 -5
- package/guide/dsh-tui-guide/plugins.md +37 -3
- package/guide/dsh-tui-guide/user-guide.en.md +3 -2
- package/guide/dsh-tui-guide/user-guide.md +3 -2
- package/lib/settings.json +1 -1
- package/lib/types/adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/adapter/channel/projection.js +1 -0
- package/lib/types/adapter/channel/ui-policy.d.ts +1 -1
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +1 -0
- package/lib/types/adapter/ports/channel-catalog.d.ts +5 -1
- package/lib/types/adapter/ports/channel-catalog.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-settings.d.ts +5 -3
- package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +7 -1
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +47 -0
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel.d.ts +2 -0
- package/lib/types/adapter/ports/channel.d.ts.map +1 -1
- package/lib/types/agent/events.d.ts +3 -2
- package/lib/types/agent/events.d.ts.map +1 -1
- package/lib/types/backends/codex/contract.d.ts +3 -0
- package/lib/types/backends/codex/contract.d.ts.map +1 -1
- package/lib/types/backends/codex/contract.js +3 -0
- package/lib/types/backends/codex/session/async-questions.d.ts +17 -0
- package/lib/types/backends/codex/session/async-questions.d.ts.map +1 -0
- package/lib/types/backends/codex/session/async-questions.js +89 -0
- package/lib/types/backends/codex/session/session.d.ts.map +1 -1
- package/lib/types/backends/codex/session/session.js +35 -9
- package/lib/types/backends/codex/text.d.ts +3 -3
- package/lib/types/backends/codex/text.js +1 -1
- package/lib/types/backends/codex/translate/items.d.ts.map +1 -1
- package/lib/types/backends/codex/translate/items.js +3 -1
- package/lib/types/backends/codex/translate/question-reply.d.ts +11 -0
- package/lib/types/backends/codex/translate/question-reply.d.ts.map +1 -0
- package/lib/types/backends/codex/translate/question-reply.js +53 -0
- package/lib/types/channel/projection.d.ts.map +1 -1
- package/lib/types/channel/projection.js +10 -0
- package/lib/types/commands.d.ts +10 -0
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +11 -2
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/CommandSuggestions.js +4 -1
- package/lib/types/components/LogoV2.d.ts +4 -1
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +5 -3
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +95 -14
- package/lib/types/components/PermissionsPicker.d.ts +10 -1
- package/lib/types/components/PermissionsPicker.d.ts.map +1 -1
- package/lib/types/components/PermissionsPicker.js +24 -16
- package/lib/types/components/PluginInstallPane.d.ts +21 -0
- package/lib/types/components/PluginInstallPane.d.ts.map +1 -0
- package/lib/types/components/PluginInstallPane.js +84 -0
- package/lib/types/components/PluginManagePane.d.ts +21 -0
- package/lib/types/components/PluginManagePane.d.ts.map +1 -0
- package/lib/types/components/PluginManagePane.js +69 -0
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +7 -3
- package/lib/types/components/SubagentCard.d.ts +13 -1
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +27 -12
- package/lib/types/components/SubagentDashboard.d.ts +8 -1
- package/lib/types/components/SubagentDashboard.d.ts.map +1 -1
- package/lib/types/components/SubagentDashboard.js +58 -16
- package/lib/types/components/launchpadLayout.d.ts +14 -1
- package/lib/types/components/launchpadLayout.d.ts.map +1 -1
- package/lib/types/components/launchpadLayout.js +36 -17
- package/lib/types/components/messages/TeamMessageBubble.d.ts +20 -0
- package/lib/types/components/messages/TeamMessageBubble.d.ts.map +1 -0
- package/lib/types/components/messages/TeamMessageBubble.js +15 -0
- package/lib/types/components/sidePanel/PanelHost.d.ts.map +1 -1
- package/lib/types/components/sidePanel/PanelHost.js +5 -1
- package/lib/types/components/sidePanel/PanelStore.d.ts +8 -0
- package/lib/types/components/sidePanel/PanelStore.d.ts.map +1 -1
- package/lib/types/components/sidePanel/PanelStore.js +11 -0
- package/lib/types/components/sidePanel/SidePanelColumn.d.ts.map +1 -1
- package/lib/types/components/sidePanel/SidePanelColumn.js +13 -1
- package/lib/types/components/sidePanel/SidePanelRuntimeContext.d.ts +7 -0
- package/lib/types/components/sidePanel/SidePanelRuntimeContext.d.ts.map +1 -1
- package/lib/types/components/sidePanel/SidePanelRuntimeContext.js +4 -0
- package/lib/types/components/sidePanel/btw/BtwComposer.d.ts +3 -0
- package/lib/types/components/sidePanel/btw/BtwComposer.d.ts.map +1 -1
- package/lib/types/components/sidePanel/btw/BtwComposer.js +20 -8
- package/lib/types/components/sidePanel/btw/BtwPanelAdapter.d.ts +2 -1
- package/lib/types/components/sidePanel/btw/BtwPanelAdapter.d.ts.map +1 -1
- package/lib/types/components/sidePanel/btw/BtwPanelAdapter.js +104 -13
- package/lib/types/components/sidePanel/btw/BtwThreadScene.d.ts +6 -2
- package/lib/types/components/sidePanel/btw/BtwThreadScene.d.ts.map +1 -1
- package/lib/types/components/sidePanel/btw/BtwThreadScene.js +61 -15
- package/lib/types/components/sidePanel/btw/BtwThreadView.d.ts +14 -4
- package/lib/types/components/sidePanel/btw/BtwThreadView.d.ts.map +1 -1
- package/lib/types/components/sidePanel/btw/BtwThreadView.js +90 -5
- package/lib/types/components/sidePanel/btw/threads.d.ts +18 -0
- package/lib/types/components/sidePanel/btw/threads.d.ts.map +1 -1
- package/lib/types/components/sidePanel/btw/threads.js +51 -0
- package/lib/types/components/sidePanel/builtinPanels.d.ts.map +1 -1
- package/lib/types/components/sidePanel/builtinPanels.js +5 -1
- package/lib/types/components/sidePanel/companion/SplashMascot.d.ts +5 -1
- package/lib/types/components/sidePanel/companion/SplashMascot.d.ts.map +1 -1
- package/lib/types/components/sidePanel/companion/SplashMascot.js +19 -4
- package/lib/types/components/sidePanel/companion/skins.d.ts +8 -0
- package/lib/types/components/sidePanel/companion/skins.d.ts.map +1 -1
- package/lib/types/components/sidePanel/companion/skins.js +57 -12
- package/lib/types/components/sidePanel/types.d.ts +6 -0
- package/lib/types/components/sidePanel/types.d.ts.map +1 -1
- package/lib/types/components/splashArtRows.d.ts +29 -0
- package/lib/types/components/splashArtRows.d.ts.map +1 -0
- package/lib/types/components/splashArtRows.js +31 -0
- package/lib/types/components/teamRoster.d.ts +70 -0
- package/lib/types/components/teamRoster.d.ts.map +1 -0
- package/lib/types/components/teamRoster.js +78 -0
- package/lib/types/dsh-adapter/admission-loader.d.ts +82 -0
- package/lib/types/dsh-adapter/admission-loader.d.ts.map +1 -1
- package/lib/types/dsh-adapter/admission-loader.js +73 -28
- package/lib/types/dsh-adapter/agent-view.d.ts.map +1 -1
- package/lib/types/dsh-adapter/agent-view.js +3 -1
- package/lib/types/dsh-adapter/approvals.d.ts +7 -0
- package/lib/types/dsh-adapter/approvals.d.ts.map +1 -1
- package/lib/types/dsh-adapter/approvals.js +45 -1
- package/lib/types/dsh-adapter/backend/translate.d.ts.map +1 -1
- package/lib/types/dsh-adapter/backend/translate.js +68 -8
- package/lib/types/dsh-adapter/backend-assembly.d.ts +31 -0
- package/lib/types/dsh-adapter/backend-assembly.d.ts.map +1 -0
- package/lib/types/dsh-adapter/backend-assembly.js +225 -0
- package/lib/types/dsh-adapter/backend-contribution.d.ts +36 -0
- package/lib/types/dsh-adapter/backend-contribution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/backend-contribution.js +41 -0
- package/lib/types/dsh-adapter/backend-registry.d.ts.map +1 -1
- package/lib/types/dsh-adapter/backend-registry.js +22 -3
- package/lib/types/dsh-adapter/backends.d.ts.map +1 -1
- package/lib/types/dsh-adapter/backends.js +4 -5
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/bundled-presets.js +60 -3
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +1 -0
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +1 -0
- package/lib/types/dsh-adapter/channel/command-completions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/command-completions.js +64 -7
- package/lib/types/dsh-adapter/channel/compaction.d.ts +7 -2
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +100 -26
- package/lib/types/dsh-adapter/channel/core/binding-feed.d.ts +3 -0
- package/lib/types/dsh-adapter/channel/core/binding-feed.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/core/binding-feed.js +2 -1
- package/lib/types/dsh-adapter/channel/core/compose.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/core/compose.js +12 -0
- package/lib/types/dsh-adapter/channel/extensions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/extensions.js +68 -8
- package/lib/types/dsh-adapter/channel/mode-permission-actions.d.ts +6 -0
- package/lib/types/dsh-adapter/channel/mode-permission-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/mode-permission-actions.js +104 -12
- package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-actions.js +8 -1
- package/lib/types/dsh-adapter/channel/permissions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/permissions.js +4 -1
- package/lib/types/dsh-adapter/channel/projection-helpers.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection-helpers.js +2 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +4 -3
- package/lib/types/dsh-adapter/channel/session-reset.js +2 -2
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +7 -0
- package/lib/types/dsh-adapter/channel/settings-host.d.ts +3 -0
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +135 -5
- package/lib/types/dsh-adapter/channel/state.d.ts +6 -0
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +18 -6
- package/lib/types/dsh-adapter/channel/transcript.d.ts +7 -0
- package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/transcript.js +19 -2
- package/lib/types/dsh-adapter/compat/agent-team-0.2.0.d.ts +55 -0
- package/lib/types/dsh-adapter/compat/agent-team-0.2.0.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/agent-team-0.2.0.js +96 -0
- package/lib/types/dsh-adapter/contract.d.ts +4 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +5 -5
- package/lib/types/dsh-adapter/effect-ledger.d.ts +7 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -1
- package/lib/types/dsh-adapter/effect-ledger.js +8 -1
- package/lib/types/dsh-adapter/entry-slot.d.ts +3 -1
- package/lib/types/dsh-adapter/entry-slot.d.ts.map +1 -1
- package/lib/types/dsh-adapter/entry-slot.js +2 -2
- package/lib/types/dsh-adapter/fresh-agent.d.ts.map +1 -1
- package/lib/types/dsh-adapter/fresh-agent.js +6 -1
- package/lib/types/dsh-adapter/host-access.d.ts.map +1 -1
- package/lib/types/dsh-adapter/host-access.js +99 -0
- package/lib/types/dsh-adapter/host-contract.d.ts +1 -1
- package/lib/types/dsh-adapter/host-contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/host-contract.js +4 -3
- package/lib/types/dsh-adapter/host-dsh.d.ts +8 -2
- package/lib/types/dsh-adapter/host-dsh.d.ts.map +1 -1
- package/lib/types/dsh-adapter/host-dsh.js +45 -30
- package/lib/types/dsh-adapter/host-entry.js +40 -13
- package/lib/types/dsh-adapter/index.d.ts +9 -10
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +8 -6
- package/lib/types/dsh-adapter/install/pnpm-profile-add.d.ts.map +1 -1
- package/lib/types/dsh-adapter/install/pnpm-profile-add.js +9 -3
- package/lib/types/dsh-adapter/invariant.d.ts +7 -2
- package/lib/types/dsh-adapter/invariant.d.ts.map +1 -1
- package/lib/types/dsh-adapter/invariant.js +6 -3
- package/lib/types/dsh-adapter/migrate/index.js +2 -2
- package/lib/types/dsh-adapter/panels.d.ts.map +1 -1
- package/lib/types/dsh-adapter/panels.js +6 -0
- package/lib/types/dsh-adapter/plugin-declaration.d.ts +99 -1
- package/lib/types/dsh-adapter/plugin-declaration.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-declaration.js +132 -2
- package/lib/types/dsh-adapter/plugin-feed.d.ts +94 -0
- package/lib/types/dsh-adapter/plugin-feed.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-feed.js +135 -0
- package/lib/types/dsh-adapter/plugin-guard.d.ts +115 -0
- package/lib/types/dsh-adapter/plugin-guard.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-guard.js +108 -0
- package/lib/types/dsh-adapter/plugin-install.d.ts +160 -0
- package/lib/types/dsh-adapter/plugin-install.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-install.js +545 -0
- package/lib/types/dsh-adapter/plugin-manage.d.ts +178 -0
- package/lib/types/dsh-adapter/plugin-manage.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-manage.js +468 -0
- package/lib/types/dsh-adapter/plugin-manager.d.ts +78 -2
- package/lib/types/dsh-adapter/plugin-manager.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-manager.js +32 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +49 -2
- package/lib/types/dsh-adapter/plugins-info.d.ts +87 -1
- package/lib/types/dsh-adapter/plugins-info.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugins-info.js +131 -26
- package/lib/types/dsh-adapter/process-exit.d.ts +1 -1
- package/lib/types/dsh-adapter/process-exit.d.ts.map +1 -1
- package/lib/types/dsh-adapter/process-exit.js +1 -1
- package/lib/types/dsh-adapter/session-projection-store.d.ts +66 -0
- package/lib/types/dsh-adapter/session-projection-store.d.ts.map +1 -0
- package/lib/types/dsh-adapter/session-projection-store.js +149 -0
- package/lib/types/dsh-adapter/settingsEditor.js +2 -2
- package/lib/types/dsh-adapter/sideQuestion.d.ts +21 -0
- package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sideQuestion.js +53 -0
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +2 -1
- package/lib/types/dsh-adapter/team-mode.d.ts +74 -0
- package/lib/types/dsh-adapter/team-mode.d.ts.map +1 -0
- package/lib/types/dsh-adapter/team-mode.js +188 -0
- package/lib/types/dsh-adapter/team-roster.d.ts +67 -0
- package/lib/types/dsh-adapter/team-roster.d.ts.map +1 -0
- package/lib/types/dsh-adapter/team-roster.js +136 -0
- package/lib/types/dsh-adapter/team-tools.d.ts +58 -0
- package/lib/types/dsh-adapter/team-tools.d.ts.map +1 -0
- package/lib/types/dsh-adapter/team-tools.js +208 -0
- package/lib/types/dsh-adapter/types.d.ts +1 -1
- package/lib/types/dsh-adapter/types.d.ts.map +1 -1
- package/lib/types/i18n.d.ts +607 -16
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +295 -9
- package/lib/types/ink/components/ScrollBox.d.ts +9 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +23 -0
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/kernelPrefs.d.ts +1 -1
- package/lib/types/kernelPrefs.d.ts.map +1 -1
- package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
- package/lib/types/native-ts/yoga-layout/index.js +8 -1
- package/lib/types/permissionPresetLabels.d.ts +25 -0
- package/lib/types/permissionPresetLabels.d.ts.map +1 -0
- package/lib/types/permissionPresetLabels.js +33 -0
- package/lib/types/preset-patch.d.ts +22 -0
- package/lib/types/preset-patch.d.ts.map +1 -0
- package/lib/types/preset-patch.js +14 -0
- package/lib/types/screens/Chat.d.ts +33 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +301 -9
- package/lib/types/screens/Launchpad.d.ts +7 -1
- package/lib/types/screens/Launchpad.d.ts.map +1 -1
- package/lib/types/screens/Launchpad.js +19 -4
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +1 -0
- package/lib/types/screens/chat/usePluginWriteFlow.d.ts +68 -0
- package/lib/types/screens/chat/usePluginWriteFlow.d.ts.map +1 -0
- package/lib/types/screens/chat/usePluginWriteFlow.js +92 -0
- package/lib/types/screens/chatOverlay.d.ts +19 -1
- package/lib/types/screens/chatOverlay.d.ts.map +1 -1
- package/lib/types/sessionModes.d.ts +5 -3
- package/lib/types/sessionModes.d.ts.map +1 -1
- package/lib/types/sessionModes.js +9 -3
- package/lib/types/tips.js +2 -2
- package/lib/types/update.d.ts +31 -22
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +85 -42
- package/lib/types/utils/paths.d.ts +11 -0
- package/lib/types/utils/paths.d.ts.map +1 -1
- package/lib/types/utils/paths.js +13 -0
- package/package.json +126 -120
- package/tui-profile/feed/README.md +63 -0
- package/tui-profile/feed/first-party.json +10 -0
|
@@ -24,6 +24,16 @@ export const BTW_CONTEXT_CHAR_BUDGET = 24_000;
|
|
|
24
24
|
export const BTW_ANSWER_CHAR_BUDGET = 8_000;
|
|
25
25
|
/** 跨线程并发上限:超过显示忙,不隐式取消。 */
|
|
26
26
|
export const BTW_MAX_CONCURRENT_ASKS = 2;
|
|
27
|
+
/**
|
|
28
|
+
* 有效选中轮:钉住的 id 还在就继续用它,否则跟最后一条(新轮到达自动跟尾、
|
|
29
|
+
* 轮被清掉/换话题自动落回)。面板与全屏场景共用这一条解析,保证两个形态
|
|
30
|
+
* 的选中语义逐字一致。
|
|
31
|
+
*/
|
|
32
|
+
export function effectiveSelectedTurnId(turns, pinned) {
|
|
33
|
+
if (pinned !== null && turns.some(turn => turn.turnId === pinned))
|
|
34
|
+
return pinned;
|
|
35
|
+
return turns.length === 0 ? null : turns[turns.length - 1].turnId;
|
|
36
|
+
}
|
|
27
37
|
/** 钳到 1–8;非有限值取默认 4。 */
|
|
28
38
|
export function normalizeRecentTurnsLimit(value) {
|
|
29
39
|
if (value === undefined || !Number.isFinite(value))
|
|
@@ -92,6 +102,7 @@ function buildSnapshot(record) {
|
|
|
92
102
|
turns: Object.freeze([...record.turns]),
|
|
93
103
|
activeTurnId: active === null ? null : active.turnId,
|
|
94
104
|
draft: record.draft,
|
|
105
|
+
selectedTurnId: effectiveSelectedTurnId(record.turns, record.selectedTurnId),
|
|
95
106
|
unread: Object.freeze({ count: unreadCount, error: unreadError }),
|
|
96
107
|
version: record.version,
|
|
97
108
|
});
|
|
@@ -147,6 +158,8 @@ class BtwThreadStore {
|
|
|
147
158
|
omittedOlderCount: selection.omittedOlderCount,
|
|
148
159
|
};
|
|
149
160
|
record.turns.push(turn);
|
|
161
|
+
// 新轮到达回到跟尾:选中态跟的是「最后一条」,上一轮的钉位不再有意义。
|
|
162
|
+
record.selectedTurnId = null;
|
|
150
163
|
this.bump(record);
|
|
151
164
|
const controller = new AbortController();
|
|
152
165
|
this.controllers.set(turn.turnId, controller);
|
|
@@ -230,6 +243,7 @@ class BtwThreadStore {
|
|
|
230
243
|
record.generation += 1;
|
|
231
244
|
record.turns = [];
|
|
232
245
|
record.draft = '';
|
|
246
|
+
record.selectedTurnId = null;
|
|
233
247
|
record.seenThroughSeq = this.turnSeq;
|
|
234
248
|
this.bump(record);
|
|
235
249
|
return true;
|
|
@@ -241,6 +255,41 @@ class BtwThreadStore {
|
|
|
241
255
|
record.draft = text;
|
|
242
256
|
this.bump(record);
|
|
243
257
|
}
|
|
258
|
+
/** 指定选中某一轮(点标题行;null = 回到跟最后一条)。 */
|
|
259
|
+
select(sessionId, turnId) {
|
|
260
|
+
const record = this.recordOf(sessionId);
|
|
261
|
+
if (record.selectedTurnId === turnId)
|
|
262
|
+
return;
|
|
263
|
+
record.selectedTurnId = turnId;
|
|
264
|
+
this.bump(record);
|
|
265
|
+
}
|
|
266
|
+
/** 当前选中轮(实时解析,不依赖渲染期快照)。 */
|
|
267
|
+
selectedTurn(sessionId) {
|
|
268
|
+
const record = this.threads.get(sessionId);
|
|
269
|
+
if (record === undefined)
|
|
270
|
+
return undefined;
|
|
271
|
+
const id = effectiveSelectedTurnId(record.turns, record.selectedTurnId);
|
|
272
|
+
return id === null ? undefined : record.turns.find(turn => turn.turnId === id);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* ↑/↓ 移动选中:从当前有效选中出发、夹在两端(delta = ±1)。落点即钉住,
|
|
276
|
+
* 所以移动之后不再跟尾;返回新选中轮(线程为空 = undefined)。
|
|
277
|
+
*/
|
|
278
|
+
moveSelection(sessionId, delta) {
|
|
279
|
+
const record = this.recordOf(sessionId);
|
|
280
|
+
if (record.turns.length === 0)
|
|
281
|
+
return undefined;
|
|
282
|
+
const current = effectiveSelectedTurnId(record.turns, record.selectedTurnId);
|
|
283
|
+
const at = record.turns.findIndex(turn => turn.turnId === current);
|
|
284
|
+
const from = at === -1 ? record.turns.length - 1 : at;
|
|
285
|
+
const next = Math.min(record.turns.length - 1, Math.max(0, from + delta));
|
|
286
|
+
const turnId = record.turns[next].turnId;
|
|
287
|
+
if (record.selectedTurnId !== turnId) {
|
|
288
|
+
record.selectedTurnId = turnId;
|
|
289
|
+
this.bump(record);
|
|
290
|
+
}
|
|
291
|
+
return record.turns[next];
|
|
292
|
+
}
|
|
244
293
|
/** 看到最新线程:把已落定轮全部记为已读(running 轮落定时再见分晓)。 */
|
|
245
294
|
markSeen(sessionId) {
|
|
246
295
|
const record = this.threads.get(sessionId);
|
|
@@ -269,6 +318,7 @@ class BtwThreadStore {
|
|
|
269
318
|
generation: 0,
|
|
270
319
|
turns: [],
|
|
271
320
|
draft: '',
|
|
321
|
+
selectedTurnId: null,
|
|
272
322
|
seenThroughSeq: this.turnSeq,
|
|
273
323
|
version: 0,
|
|
274
324
|
snapshot: Object.freeze({
|
|
@@ -279,6 +329,7 @@ class BtwThreadStore {
|
|
|
279
329
|
turns: Object.freeze([]),
|
|
280
330
|
activeTurnId: null,
|
|
281
331
|
draft: '',
|
|
332
|
+
selectedTurnId: null,
|
|
282
333
|
unread: Object.freeze({ count: 0, error: false }),
|
|
283
334
|
version: 0,
|
|
284
335
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtinPanels.d.ts","sourceRoot":"","sources":["../../../../src/components/sidePanel/builtinPanels.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"builtinPanels.d.ts","sourceRoot":"","sources":["../../../../src/components/sidePanel/builtinPanels.tsx"],"names":[],"mappings":"AAiOA,2BAA2B;AAC3B,wBAAgB,qBAAqB,IAAI,IAAI,CAmG5C"}
|
|
@@ -141,6 +141,10 @@ function AgentsPanelAdapter({ focused, visible }) {
|
|
|
141
141
|
React.useEffect(() => {
|
|
142
142
|
const running = subagents.filter(s => s.status === 'running' || s.status === 'starting').length;
|
|
143
143
|
const failedIds = new Set(subagents.filter(s => s.status === 'failed').map(s => s.agentId));
|
|
144
|
+
// A failed team member is durable; it counts once even beside a failed run.
|
|
145
|
+
for (const member of channel.team?.members ?? [])
|
|
146
|
+
if (member.phase === 'failed')
|
|
147
|
+
failedIds.add(member.id);
|
|
144
148
|
if (visible) {
|
|
145
149
|
seenFailedRef.current = failedIds;
|
|
146
150
|
panelStore.setBadge('agents', running > 0 ? { level: 'info', unread: 0 } : null);
|
|
@@ -162,7 +166,7 @@ function AgentsPanelAdapter({ focused, visible }) {
|
|
|
162
166
|
if (typeof route === 'object' && detail !== undefined) {
|
|
163
167
|
return (_jsx(SubagentDetailScene, { subagent: detail, variant: "panel", focused: focused, visible: visible, onBack: () => setRoute('dashboard'), onInterrupt: (id) => channel.subagentControl?.interrupt(id), ...(channel.subagentControl?.history === undefined ? {} : { loadTranscript: channel.subagentControl.history }), onOpenView: () => agentViewStore.request(detail.agentId, 'agent-detail', true), messages: detailMessages, ...(detailCompose === undefined ? {} : { compose: detailCompose }) }));
|
|
164
168
|
}
|
|
165
|
-
return (_jsx(SubagentDashboard, { subagents: subagents, variant: "panel", focused: focused, visible: visible, onSelect: (id) => setRoute({ detail: id }), onOpenView: (id) => agentViewStore.request(id, 'agents-dashboard', true), messages: messageControl?.messages() }));
|
|
169
|
+
return (_jsx(SubagentDashboard, { subagents: subagents, team: channel.team, sessionId: channel.sessionId, variant: "panel", focused: focused, visible: visible, onSelect: (id) => setRoute({ detail: id }), onOpenView: (id) => agentViewStore.request(id, 'agents-dashboard', true), messages: messageControl?.messages() }));
|
|
166
170
|
}
|
|
167
171
|
let registered = false;
|
|
168
172
|
/** 幂等:重复调用(夹具多次挂载)不再注册。 */
|
|
@@ -19,13 +19,17 @@
|
|
|
19
19
|
* 渲染路径(LogoV2 底部块,welcomePad 缩进)。
|
|
20
20
|
*/
|
|
21
21
|
import React from 'react';
|
|
22
|
+
import { type SplashImageBox } from '../../splashArtRows.js';
|
|
22
23
|
export type SplashMascotSkin = 'deepy' | 'whaleGirl';
|
|
23
24
|
/** 读 companion.skin(LogoV2 的测试缝 prop 优先);非吉祥物皮肤返回
|
|
24
25
|
* undefined(LogoV2 走原鲸鱼/女仆娘路径,零改动)。 */
|
|
25
26
|
export declare function useSplashMascotSkin(pinned?: string): SplashMascotSkin | undefined;
|
|
27
|
+
/** 图片原生尺寸的紧凑槽;仅启动页使用,协议/像元/素材未就绪时保持原回退。 */
|
|
28
|
+
export declare function useSplashMascotBox(skin: SplashMascotSkin | undefined, compact: boolean): SplashImageBox | undefined;
|
|
26
29
|
/** 启动页吉祥物本体:按 skin 渲染动画,点击交互(poke/连点)在内层盒。 */
|
|
27
|
-
export declare function SplashMascot({ skin, active }: {
|
|
30
|
+
export declare function SplashMascot({ skin, active, imageBox }: {
|
|
28
31
|
readonly skin: SplashMascotSkin;
|
|
32
|
+
readonly imageBox?: SplashImageBox;
|
|
29
33
|
/** 动画许可:false(冻结/落地页 whaleIdle=false)时定格 idle 帧 0、零时钟。 */
|
|
30
34
|
readonly active: boolean;
|
|
31
35
|
}): React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplashMascot.d.ts","sourceRoot":"","sources":["../../../../../src/components/sidePanel/companion/SplashMascot.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"SplashMascot.d.ts","sourceRoot":"","sources":["../../../../../src/components/sidePanel/companion/SplashMascot.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAiB/E,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,WAAW,CAAA;AAEpD;wCACwC;AACxC,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAIjF;AAGD,2CAA2C;AAC3C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAUnH;AAED,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IACvD,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB,GAAG,KAAK,CAAC,SAAS,CAsElB"}
|
|
@@ -20,10 +20,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
20
20
|
* 渲染路径(LogoV2 底部块,welcomePad 缩进)。
|
|
21
21
|
*/
|
|
22
22
|
import React from 'react';
|
|
23
|
-
import { Box } from '../../../ui.js';
|
|
23
|
+
import { Box, useTerminalImages, useTerminalImageCellSize, useTerminalImageProtocol } from '../../../ui.js';
|
|
24
|
+
import { fitSplashImageBox } from '../../splashArtRows.js';
|
|
25
|
+
import { loadWhaleGirlKit } from './deepy.js';
|
|
24
26
|
import { getCompanionSkin, subscribeCompanionSkin } from '../../../tuiDisplayPrefs.js';
|
|
25
27
|
import { TICKLE_MIN_CLICKS, TICKLE_WINDOW_MS } from './mood.js';
|
|
26
|
-
import { DeepySkin, WhaleGirlSkin } from './skins.js';
|
|
28
|
+
import { DeepySkin, WhaleGirlSkin, loadWhaleGirlImageKit } from './skins.js';
|
|
27
29
|
import { initialCompanionPoseState, nextCompanionPoseStep } from './pose.js';
|
|
28
30
|
/** 点击反应档时长:poke 帧表一轮 2100ms,取头段(同 CompanionPanel 的口径)。 */
|
|
29
31
|
const SPLASH_POKE_MS = 1400;
|
|
@@ -40,8 +42,20 @@ export function useSplashMascotSkin(pinned) {
|
|
|
40
42
|
const id = pinned ?? setting;
|
|
41
43
|
return id === 'deepy' || id === 'whaleGirl' ? id : undefined;
|
|
42
44
|
}
|
|
45
|
+
/** 图片原生尺寸的紧凑槽;仅启动页使用,协议/像元/素材未就绪时保持原回退。 */
|
|
46
|
+
export function useSplashMascotBox(skin, compact) {
|
|
47
|
+
// 高度降级可能暂时撤掉吉祥物,因此能力探测不能只依赖吉祥物挂载。
|
|
48
|
+
const available = useTerminalImages(compact && skin === 'whaleGirl');
|
|
49
|
+
const protocol = useTerminalImageProtocol();
|
|
50
|
+
const cell = useTerminalImageCellSize();
|
|
51
|
+
const canvas = available && compact && skin === 'whaleGirl' && cell !== undefined
|
|
52
|
+
&& (protocol === 'kitty' || protocol === 'sixel') && loadWhaleGirlKit() !== undefined
|
|
53
|
+
? loadWhaleGirlImageKit()?.canvas : undefined;
|
|
54
|
+
return React.useMemo(() => canvas !== undefined && cell !== undefined
|
|
55
|
+
? fitSplashImageBox(canvas, cell, WhaleGirlSkin.cells) : undefined, [canvas, cell]);
|
|
56
|
+
}
|
|
43
57
|
/** 启动页吉祥物本体:按 skin 渲染动画,点击交互(poke/连点)在内层盒。 */
|
|
44
|
-
export function SplashMascot({ skin, active }) {
|
|
58
|
+
export function SplashMascot({ skin, active, imageBox }) {
|
|
45
59
|
const [, setBump] = React.useState(0);
|
|
46
60
|
// 稳态 idle 从挂载起循环;冻结时 now 钉在挂载值 → elapsed 恒 0 → 帧 0。
|
|
47
61
|
const mountedAtRef = React.useRef(Date.now());
|
|
@@ -78,6 +92,7 @@ export function SplashMascot({ skin, active }) {
|
|
|
78
92
|
now,
|
|
79
93
|
width: SPLASH_MASCOT_COLUMNS,
|
|
80
94
|
animationSemantic,
|
|
95
|
+
...(imageBox === undefined ? {} : { imageBox }),
|
|
81
96
|
};
|
|
82
97
|
return (_jsx(Box, { flexDirection: "column", alignItems: "center", flexShrink: 0, children: _jsx(Box, { onClick: (event) => {
|
|
83
98
|
event.stopImmediatePropagation();
|
|
@@ -93,7 +108,7 @@ export function SplashMascot({ skin, active }) {
|
|
|
93
108
|
overrideRef.current = rapid
|
|
94
109
|
? { semantic: 'tickle', since: at, until: at + TICKLE_WINDOW_MS }
|
|
95
110
|
: {
|
|
96
|
-
semantic: event.localCol < SPLASH_MASCOT_COLUMNS / 2 ? 'poke-left' : 'poke-right',
|
|
111
|
+
semantic: event.localCol < (imageBox?.columns ?? (skin === 'whaleGirl' ? WhaleGirlSkin.cells.columns : SPLASH_MASCOT_COLUMNS)) / 2 ? 'poke-left' : 'poke-right',
|
|
97
112
|
since: at,
|
|
98
113
|
until: at + SPLASH_POKE_MS,
|
|
99
114
|
};
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* 皮肤 = id + cells + render(pose, ctx),自定义皮肤走同一接口进入。
|
|
12
12
|
*/
|
|
13
13
|
import React from 'react';
|
|
14
|
+
import type { SplashImageBox } from '../../splashArtRows.js';
|
|
14
15
|
import type { I18nKey } from '../../../i18n.js';
|
|
15
16
|
import type { TerminalImageSource } from '../../../ink/terminal-image.js';
|
|
16
17
|
import type { CompanionMood } from './mood.js';
|
|
@@ -29,6 +30,8 @@ export interface CompanionSkinRenderInput {
|
|
|
29
30
|
* 旧调用方(缺省)皮肤退回 pose.mood 分层,属皮肤接口「未支持即
|
|
30
31
|
* 退化」契约。 */
|
|
31
32
|
readonly animationSemantic?: string;
|
|
33
|
+
/** 启动页专属紧凑图片槽;侧栏不传,保持原来的固定几何。 */
|
|
34
|
+
readonly imageBox?: SplashImageBox;
|
|
32
35
|
}
|
|
33
36
|
export interface CompanionSkin {
|
|
34
37
|
readonly id: string;
|
|
@@ -86,6 +89,11 @@ interface WhaleGirlImageAnimation {
|
|
|
86
89
|
interface WhaleGirlImageKit {
|
|
87
90
|
/** img/ 目录的绝对路径(帧 PNG 解码用)。 */
|
|
88
91
|
readonly dir: string;
|
|
92
|
+
/** idle 首帧 PNG 头部声明的稳定画布,不等待像素解码。 */
|
|
93
|
+
readonly canvas?: {
|
|
94
|
+
readonly width: number;
|
|
95
|
+
readonly height: number;
|
|
96
|
+
};
|
|
89
97
|
readonly byKey: Readonly<Record<string, WhaleGirlImageAnimation>>;
|
|
90
98
|
}
|
|
91
99
|
/** 惰性加载 + 缓存图像 timings;缺失/校验失败返回 undefined(退字母格)。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skins.d.ts","sourceRoot":"","sources":["../../../../../src/components/sidePanel/companion/skins.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AAYzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;IAC5B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;;iBAKa;IACb,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"skins.d.ts","sourceRoot":"","sources":["../../../../../src/components/sidePanel/companion/skins.tsx"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
import { Box, Text, Image, useTerminalImages, useTerminalImageProtocol, useTerminalImageCellSize } from '../../../ui.js';
|
|
19
|
-
import { WhaleArt, renderSpriteRows } from '../../Whale.js';
|
|
19
|
+
import { WhaleArt, renderSpriteRows, renderCellRows } from '../../Whale.js';
|
|
20
20
|
import { loadSharp } from '../../../dsh-adapter/sharp.js';
|
|
21
21
|
import { DEEPY_CELLS, DEEPY_MOOD_ANIMATION, DEEPY_SEMANTIC_ANIMATION, frameAt, loadDeepyKit, loadWhaleGirlKit, renderedDeepyAnimation, } from './deepy.js';
|
|
22
22
|
/** deepy 小鲸鱼(默认):语义/心情 → 动画,elapsed → frameAt 确定性选帧。 */
|
|
@@ -122,14 +122,31 @@ export function resolveWhaleGirlAnimationKey(pose, animationSemantic, hasKey) {
|
|
|
122
122
|
* 回归锁「全部帧内容 ⊆ [5, 5+31)」防素材更新后悄悄越窗被截。 */
|
|
123
123
|
const WHALE_GIRL_LETTER_WINDOW_START = 5;
|
|
124
124
|
const whaleGirlWindowCache = new Map();
|
|
125
|
-
function renderedWhaleGirlWindowRows(kit, key) {
|
|
125
|
+
function renderedWhaleGirlWindowRows(kit, key, imageBox) {
|
|
126
126
|
const animation = kit.byKey[key];
|
|
127
127
|
if (animation === undefined)
|
|
128
128
|
return undefined;
|
|
129
|
-
const cacheKey = kit.id + ':window:' + key;
|
|
129
|
+
const cacheKey = kit.id + ':window:' + key + (imageBox === undefined ? '' : `:${imageBox.columns}x${imageBox.rows}`);
|
|
130
130
|
let rendered = whaleGirlWindowCache.get(cacheKey);
|
|
131
131
|
if (rendered === undefined) {
|
|
132
|
-
rendered = Object.freeze(animation.frames.map(frame =>
|
|
132
|
+
rendered = Object.freeze(animation.frames.map(frame => {
|
|
133
|
+
if (imageBox === undefined)
|
|
134
|
+
return renderSpriteRows(frame.rows.map(row => row.slice(WHALE_GIRL_LETTER_WINDOW_START, WHALE_GIRL_LETTER_WINDOW_START + WHALE_GIRL_CELLS.columns)), kit.palette);
|
|
135
|
+
// 解码前/失败时整幅字母格 contain 进同一个槽,不裁掉头脚,也不换画跳高。
|
|
136
|
+
const pixelRows = imageBox.rows * 2;
|
|
137
|
+
const scale = Math.min(imageBox.columns / WHALE_GIRL_CELLS.columns, pixelRows / kit.rows);
|
|
138
|
+
const width = Math.max(1, Math.floor(WHALE_GIRL_CELLS.columns * scale));
|
|
139
|
+
const height = Math.max(1, Math.floor(kit.rows * scale));
|
|
140
|
+
const left = Math.floor((imageBox.columns - width) / 2);
|
|
141
|
+
const top = Math.floor((pixelRows - height) / 2);
|
|
142
|
+
return renderCellRows(imageBox.columns, pixelRows, (x, y) => {
|
|
143
|
+
if (x < left || x >= left + width || y < top || y >= top + height)
|
|
144
|
+
return undefined;
|
|
145
|
+
const sx = Math.min(WHALE_GIRL_CELLS.columns - 1, Math.floor((x - left) * WHALE_GIRL_CELLS.columns / width));
|
|
146
|
+
const sy = Math.min(kit.rows - 1, Math.floor((y - top) * kit.rows / height));
|
|
147
|
+
return kit.palette[frame.rows[sy]?.[sx + WHALE_GIRL_LETTER_WINDOW_START] ?? '.'];
|
|
148
|
+
});
|
|
149
|
+
}));
|
|
133
150
|
whaleGirlWindowCache.set(cacheKey, rendered);
|
|
134
151
|
}
|
|
135
152
|
return rendered;
|
|
@@ -146,14 +163,14 @@ function renderWhaleGirlLetterGrid(input) {
|
|
|
146
163
|
const animationKey = resolveWhaleGirlAnimationKey(pose, animationSemantic, key => kit.byKey[key] !== undefined);
|
|
147
164
|
if (animationKey === undefined)
|
|
148
165
|
return DeepySkin.render({ ...input, width: WHALE_GIRL_CELLS.columns });
|
|
149
|
-
const rendered = renderedWhaleGirlWindowRows(kit, animationKey);
|
|
166
|
+
const rendered = renderedWhaleGirlWindowRows(kit, animationKey, input.imageBox);
|
|
150
167
|
const animation = kit.byKey[animationKey];
|
|
151
168
|
if (rendered === undefined || animation === undefined) {
|
|
152
169
|
return DeepySkin.render({ ...input, width: WHALE_GIRL_CELLS.columns });
|
|
153
170
|
}
|
|
154
171
|
const frameIndex = frameAt(animation, now - moodSince);
|
|
155
172
|
const rows = rendered[frameIndex] ?? rendered[0] ?? [];
|
|
156
|
-
return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: WHALE_GIRL_CELLS.columns, children: rows.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, index))) }));
|
|
173
|
+
return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: input.imageBox?.columns ?? WHALE_GIRL_CELLS.columns, children: rows.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, index))) }));
|
|
157
174
|
}
|
|
158
175
|
export const WhaleGirlSkin = {
|
|
159
176
|
id: 'whaleGirl',
|
|
@@ -210,8 +227,25 @@ export function loadWhaleGirlImageKit() {
|
|
|
210
227
|
continue;
|
|
211
228
|
const kit = parseWhaleGirlImageKit(JSON.parse(readFileSync(join(dir, 'timings.json'), 'utf8')), dir);
|
|
212
229
|
if (kit !== undefined) {
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
const first = kit.byKey.idle?.frames[0];
|
|
231
|
+
let canvas;
|
|
232
|
+
if (first !== undefined) {
|
|
233
|
+
try {
|
|
234
|
+
const png = readFileSync(join(dir, 'idle', first.file));
|
|
235
|
+
if (png.length >= 24 && png.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))
|
|
236
|
+
&& png.toString('ascii', 12, 16) === 'IHDR') {
|
|
237
|
+
const width = png.readUInt32BE(16);
|
|
238
|
+
const height = png.readUInt32BE(20);
|
|
239
|
+
if (width > 0 && height > 0 && width <= 4096 && height <= 4096)
|
|
240
|
+
canvas = { width, height };
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// 缺失/坏帧仍走原来的异步解码失败与字母格回退。
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
whaleGirlImageKitCache = { ...kit, ...(canvas === undefined ? {} : { canvas }) };
|
|
248
|
+
return whaleGirlImageKitCache;
|
|
215
249
|
}
|
|
216
250
|
}
|
|
217
251
|
catch {
|
|
@@ -537,17 +571,28 @@ function WhaleGirlRasterSkin(input) {
|
|
|
537
571
|
const frameRatio = source.width / source.height;
|
|
538
572
|
// 盒宽=图宽(钳在 cells.columns 内;超宽像元比下 contain 收行不裁剪)。
|
|
539
573
|
const rawColumns = Math.max(1, Math.round(cellRatio * WHALE_GIRL_CELLS.rows * frameRatio));
|
|
540
|
-
const columns = whaleGirlImageBoxColumns(cellSize, frameRatio);
|
|
541
|
-
const rows = rawColumns > columns
|
|
574
|
+
const columns = input.imageBox?.columns ?? whaleGirlImageBoxColumns(cellSize, frameRatio);
|
|
575
|
+
const rows = input.imageBox?.rows ?? (rawColumns > columns
|
|
542
576
|
? Math.max(1, Math.round(columns / (cellRatio * frameRatio)))
|
|
543
|
-
: WHALE_GIRL_CELLS.rows;
|
|
577
|
+
: WHALE_GIRL_CELLS.rows);
|
|
544
578
|
image = (_jsx(Image, { transparent: true, source: source, width: columns, height: rows, alt: "", presentation: "transcript", children: _jsx(Text, { children: Array.from({ length: rows }, () => ' '.repeat(columns)).join('\n') }) }));
|
|
545
579
|
}
|
|
546
580
|
}
|
|
547
581
|
// 本次候选或上一帧;都没有(冷启动)时画字母格。切到还没解码的键时
|
|
548
582
|
// 保持上一帧,不闪回字母格。
|
|
549
583
|
const [visibleImage] = useHeldCommittedImage(image);
|
|
550
|
-
|
|
584
|
+
let raster = visibleImage;
|
|
585
|
+
// 换键等待解码时保留旧像素,但 resize 后不能把旧的大 Image 盒塞进新小槽。
|
|
586
|
+
if (input.imageBox !== undefined && React.isValidElement(raster)
|
|
587
|
+
&& (raster.props.width !== input.imageBox.columns || raster.props.height !== input.imageBox.rows)) {
|
|
588
|
+
const { columns, rows } = input.imageBox;
|
|
589
|
+
raster = React.cloneElement(raster, {
|
|
590
|
+
width: columns,
|
|
591
|
+
height: rows,
|
|
592
|
+
children: _jsx(Text, { children: Array.from({ length: rows }, () => ' '.repeat(columns)).join('\n') }),
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
return (_jsx(Box, { ref: boxRef, flexDirection: "column", flexShrink: 0, alignItems: "center", justifyContent: "center", width: input.imageBox?.columns ?? WHALE_GIRL_CELLS.columns, height: input.imageBox?.rows ?? WHALE_GIRL_CELLS.rows, children: raster !== undefined ? raster : renderWhaleGirlLetterGrid(input) }));
|
|
551
596
|
}
|
|
552
597
|
const WHALE_CELLS = Object.freeze({ columns: 40, rows: 13 });
|
|
553
598
|
/** 现有像素鲸鱼:直接消费 nativeWhalePose(与开屏 splash 同一规划器、
|
|
@@ -74,6 +74,12 @@ export interface PanelEntry {
|
|
|
74
74
|
/** 同 id 重注册时递增,用于重挂 error boundary。 */
|
|
75
75
|
readonly registrationId: number;
|
|
76
76
|
readonly badge: PanelBadge | null;
|
|
77
|
+
/**
|
|
78
|
+
* 面板自己广告的键位片段(底栏用)。`''` = 面板明确「此刻没有要广告的键」
|
|
79
|
+
* (底栏连能力位那一段也不画);没设置过则由底栏按 capabilities 兜底。
|
|
80
|
+
* 层内状态(编辑层 vs 列表层)只有面板自己知道,所以由面板发、宿主只拼。
|
|
81
|
+
*/
|
|
82
|
+
readonly hint?: string;
|
|
77
83
|
readonly lastError: {
|
|
78
84
|
readonly message: string;
|
|
79
85
|
readonly at: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/sidePanel/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/sidePanel/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Brand } from '../branding.js';
|
|
2
|
+
/** 启动页立绘槽的占行:鲸鱼自然高度、portrait 的 minimal 等高盒、吉祥物的侧栏默认盒。 */
|
|
3
|
+
export declare const WHALE_ART_ROWS = 13;
|
|
4
|
+
export declare const PORTRAIT_ART_ROWS = 11;
|
|
5
|
+
export declare const MASCOT_ART_ROWS = 15;
|
|
6
|
+
export type SplashArtForm = 'whale' | 'portrait' | 'mascot';
|
|
7
|
+
export interface SplashImageBox {
|
|
8
|
+
readonly columns: number;
|
|
9
|
+
readonly rows: number;
|
|
10
|
+
}
|
|
11
|
+
/** 与 LogoV2 的默认品牌及 mascot → portrait → whale 分支一致。 */
|
|
12
|
+
export declare function resolveSplashArtForm(input: {
|
|
13
|
+
readonly brand: Brand | undefined;
|
|
14
|
+
readonly whaleGirl: boolean;
|
|
15
|
+
readonly mascotSkin: string | undefined;
|
|
16
|
+
}): SplashArtForm;
|
|
17
|
+
export declare function splashArtRows(form: SplashArtForm, imageBox?: SplashImageBox): number;
|
|
18
|
+
/**
|
|
19
|
+
* 启动页图片按原生画布占位:只缩小、不预留放大后用不上的空间。
|
|
20
|
+
* 同一个稳定画布用于全部动画帧;不按 alpha 包围盒逐帧裁剪。
|
|
21
|
+
*/
|
|
22
|
+
export declare function fitSplashImageBox(source: {
|
|
23
|
+
readonly width: number;
|
|
24
|
+
readonly height: number;
|
|
25
|
+
}, cell: {
|
|
26
|
+
readonly width: number;
|
|
27
|
+
readonly height: number;
|
|
28
|
+
}, limit: SplashImageBox): SplashImageBox;
|
|
29
|
+
//# sourceMappingURL=splashArtRows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"splashArtRows.d.ts","sourceRoot":"","sources":["../../../src/components/splashArtRows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,yDAAyD;AACzD,eAAO,MAAM,cAAc,KAAK,CAAA;AAChC,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,eAAe,KAAK,CAAA;AAEjC,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAA;AAC3D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC,GAAG,aAAa,CAKhB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAIpF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC3D,IAAI,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACzD,KAAK,EAAE,cAAc,GACpB,cAAc,CAMhB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** 启动页立绘槽的占行:鲸鱼自然高度、portrait 的 minimal 等高盒、吉祥物的侧栏默认盒。 */
|
|
2
|
+
export const WHALE_ART_ROWS = 13;
|
|
3
|
+
export const PORTRAIT_ART_ROWS = 11;
|
|
4
|
+
export const MASCOT_ART_ROWS = 15;
|
|
5
|
+
/** 与 LogoV2 的默认品牌及 mascot → portrait → whale 分支一致。 */
|
|
6
|
+
export function resolveSplashArtForm(input) {
|
|
7
|
+
const brand = input.brand ?? 'deepseek';
|
|
8
|
+
if (brand === 'deepseek' && (input.mascotSkin === 'deepy' || input.mascotSkin === 'whaleGirl'))
|
|
9
|
+
return 'mascot';
|
|
10
|
+
if (input.whaleGirl || brand !== 'deepseek')
|
|
11
|
+
return 'portrait';
|
|
12
|
+
return 'whale';
|
|
13
|
+
}
|
|
14
|
+
export function splashArtRows(form, imageBox) {
|
|
15
|
+
if (form === 'whale')
|
|
16
|
+
return WHALE_ART_ROWS;
|
|
17
|
+
if (form === 'portrait')
|
|
18
|
+
return PORTRAIT_ART_ROWS;
|
|
19
|
+
return imageBox?.rows ?? MASCOT_ART_ROWS;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 启动页图片按原生画布占位:只缩小、不预留放大后用不上的空间。
|
|
23
|
+
* 同一个稳定画布用于全部动画帧;不按 alpha 包围盒逐帧裁剪。
|
|
24
|
+
*/
|
|
25
|
+
export function fitSplashImageBox(source, cell, limit) {
|
|
26
|
+
const scale = Math.min(1, limit.columns * cell.width / source.width, limit.rows * cell.height / source.height);
|
|
27
|
+
return {
|
|
28
|
+
columns: Math.max(1, Math.min(limit.columns, Math.ceil(source.width * scale / cell.width))),
|
|
29
|
+
rows: Math.max(1, Math.min(limit.rows, Math.ceil(source.height * scale / cell.height))),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Teams in the agents surfaces (issue #1241, phase 2): fold the
|
|
3
|
+
* session's `TeamView` and its subagent rows into what the dashboard
|
|
4
|
+
* renders. A teammate is a continuable subagent of the Lead whose row id is
|
|
5
|
+
* the member id, so the two join by id; neither side overwrites the other's
|
|
6
|
+
* state (see `teamMemberStatus`). Pure: no I/O, no backend import.
|
|
7
|
+
*/
|
|
8
|
+
import type { TeamMember, TeamTask, TeamView } from '../adapter/ports/channel-view.js';
|
|
9
|
+
import type { SubagentState } from '../dsh-adapter/subagents.js';
|
|
10
|
+
/** A member's state as shown: durable `phase` first, then the run. `active`
|
|
11
|
+
* is an active member whose run this session cannot see (a teammate's own
|
|
12
|
+
* subagent rows never hold its siblings). */
|
|
13
|
+
export type TeamMemberStatus = 'provisioning' | 'running' | 'idle' | 'active' | 'failed';
|
|
14
|
+
/** One teammate, with its subagent row once the host has announced it. */
|
|
15
|
+
export interface TeamMemberRow {
|
|
16
|
+
readonly member: TeamMember;
|
|
17
|
+
readonly subagent?: SubagentState;
|
|
18
|
+
readonly status: TeamMemberStatus;
|
|
19
|
+
}
|
|
20
|
+
export interface TeamDashboardModel {
|
|
21
|
+
readonly lead?: TeamMember;
|
|
22
|
+
/** Whether the session on screen is the Lead (its subagent rows are the teammates). */
|
|
23
|
+
readonly viewedFromLead: boolean;
|
|
24
|
+
readonly teammates: readonly TeamMemberRow[];
|
|
25
|
+
/** Subagent rows that are not team members (workflow / ralph spawns). */
|
|
26
|
+
readonly others: readonly SubagentState[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A member's shown state. A failed `phase` is durable and wins; provisioning
|
|
30
|
+
* has no run yet. An active member is running only while its row runs: a
|
|
31
|
+
* finished turn leaves the member alive and waiting (a message wakes it),
|
|
32
|
+
* so a completed — or failed, or absent — run reads as idle, never done.
|
|
33
|
+
* @param member - Roster row.
|
|
34
|
+
* @param subagent - The member's subagent row, if any.
|
|
35
|
+
* @param runKnown - Whether the subagent rows are the Lead's (default).
|
|
36
|
+
* @returns the state to render.
|
|
37
|
+
*/
|
|
38
|
+
export declare function teamMemberStatus(member: TeamMember, subagent: SubagentState | undefined, runKnown?: boolean): TeamMemberStatus;
|
|
39
|
+
/**
|
|
40
|
+
* Join the roster with the subagent rows.
|
|
41
|
+
* @param team - The session's team.
|
|
42
|
+
* @param subagents - The session's subagent rows.
|
|
43
|
+
* @param sessionId - The session on screen; inside a teammate its rows are
|
|
44
|
+
* its own children, never joined with the roster.
|
|
45
|
+
* @returns the Lead, teammates in roster order, and the remaining rows.
|
|
46
|
+
*/
|
|
47
|
+
export declare function teamDashboardModel(team: TeamView, subagents: readonly SubagentState[], sessionId?: string): TeamDashboardModel;
|
|
48
|
+
/**
|
|
49
|
+
* Teammates on the roster: those known to be running or provisioning, and
|
|
50
|
+
* those that may be running. Inside a teammate a sibling's run is not
|
|
51
|
+
* visible, so an active sibling is `unseen`; the teammate on screen itself
|
|
52
|
+
* counts in neither.
|
|
53
|
+
* @param team - The session's team.
|
|
54
|
+
* @param subagents - The session's subagent rows.
|
|
55
|
+
* @param sessionId - The session on screen.
|
|
56
|
+
* @returns the three counts.
|
|
57
|
+
*/
|
|
58
|
+
export declare function teamMemberCounts(team: TeamView, subagents: readonly SubagentState[], sessionId?: string): {
|
|
59
|
+
readonly total: number;
|
|
60
|
+
readonly active: number;
|
|
61
|
+
readonly unseen: number;
|
|
62
|
+
};
|
|
63
|
+
/** Completed / total of the task board. */
|
|
64
|
+
export declare function teamTaskProgress(tasks: readonly TeamTask[]): {
|
|
65
|
+
readonly completed: number;
|
|
66
|
+
readonly total: number;
|
|
67
|
+
};
|
|
68
|
+
/** A pending task some blocker still holds back. */
|
|
69
|
+
export declare function isTeamTaskBlocked(task: TeamTask): boolean;
|
|
70
|
+
//# sourceMappingURL=teamRoster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teamRoster.d.ts","sourceRoot":"","sources":["../../../src/components/teamRoster.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAA;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAEhE;;8CAE8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAExF,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAA;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAA;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAC1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE,QAAQ,UAAO,GAAG,gBAAgB,CAK3H;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,aAAa,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAmB9H;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,aAAa,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQtL;AAED,2CAA2C;AAC3C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAEnH;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEzD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A member's shown state. A failed `phase` is durable and wins; provisioning
|
|
3
|
+
* has no run yet. An active member is running only while its row runs: a
|
|
4
|
+
* finished turn leaves the member alive and waiting (a message wakes it),
|
|
5
|
+
* so a completed — or failed, or absent — run reads as idle, never done.
|
|
6
|
+
* @param member - Roster row.
|
|
7
|
+
* @param subagent - The member's subagent row, if any.
|
|
8
|
+
* @param runKnown - Whether the subagent rows are the Lead's (default).
|
|
9
|
+
* @returns the state to render.
|
|
10
|
+
*/
|
|
11
|
+
export function teamMemberStatus(member, subagent, runKnown = true) {
|
|
12
|
+
if (member.phase === 'failed')
|
|
13
|
+
return 'failed';
|
|
14
|
+
if (member.phase === 'provisioning')
|
|
15
|
+
return 'provisioning';
|
|
16
|
+
if (!runKnown)
|
|
17
|
+
return 'active';
|
|
18
|
+
return subagent?.status === 'running' || subagent?.status === 'starting' ? 'running' : 'idle';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Join the roster with the subagent rows.
|
|
22
|
+
* @param team - The session's team.
|
|
23
|
+
* @param subagents - The session's subagent rows.
|
|
24
|
+
* @param sessionId - The session on screen; inside a teammate its rows are
|
|
25
|
+
* its own children, never joined with the roster.
|
|
26
|
+
* @returns the Lead, teammates in roster order, and the remaining rows.
|
|
27
|
+
*/
|
|
28
|
+
export function teamDashboardModel(team, subagents, sessionId) {
|
|
29
|
+
const viewedFromLead = sessionId === undefined || sessionId === team.leadSessionId;
|
|
30
|
+
const byId = new Map();
|
|
31
|
+
if (viewedFromLead)
|
|
32
|
+
for (const row of subagents)
|
|
33
|
+
byId.set(row.agentId, row);
|
|
34
|
+
const teammates = [];
|
|
35
|
+
const memberIds = new Set();
|
|
36
|
+
for (const member of team.members) {
|
|
37
|
+
if (member.role !== 'teammate')
|
|
38
|
+
continue;
|
|
39
|
+
const subagent = byId.get(member.id);
|
|
40
|
+
if (subagent !== undefined)
|
|
41
|
+
memberIds.add(member.id);
|
|
42
|
+
teammates.push({ member, status: teamMemberStatus(member, subagent, viewedFromLead), ...subagent === undefined ? {} : { subagent } });
|
|
43
|
+
}
|
|
44
|
+
const lead = team.members.find(member => member.role === 'lead');
|
|
45
|
+
return {
|
|
46
|
+
...lead === undefined ? {} : { lead },
|
|
47
|
+
viewedFromLead,
|
|
48
|
+
teammates,
|
|
49
|
+
others: subagents.filter(row => !memberIds.has(row.agentId)),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Teammates on the roster: those known to be running or provisioning, and
|
|
54
|
+
* those that may be running. Inside a teammate a sibling's run is not
|
|
55
|
+
* visible, so an active sibling is `unseen`; the teammate on screen itself
|
|
56
|
+
* counts in neither.
|
|
57
|
+
* @param team - The session's team.
|
|
58
|
+
* @param subagents - The session's subagent rows.
|
|
59
|
+
* @param sessionId - The session on screen.
|
|
60
|
+
* @returns the three counts.
|
|
61
|
+
*/
|
|
62
|
+
export function teamMemberCounts(team, subagents, sessionId) {
|
|
63
|
+
const { teammates } = teamDashboardModel(team, subagents, sessionId);
|
|
64
|
+
const counted = teammates.filter(row => row.member.id !== sessionId);
|
|
65
|
+
return {
|
|
66
|
+
total: teammates.length,
|
|
67
|
+
active: counted.filter(row => row.status === 'running' || row.status === 'provisioning').length,
|
|
68
|
+
unseen: counted.filter(row => row.status === 'active').length,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Completed / total of the task board. */
|
|
72
|
+
export function teamTaskProgress(tasks) {
|
|
73
|
+
return { completed: tasks.filter(task => task.status === 'completed').length, total: tasks.length };
|
|
74
|
+
}
|
|
75
|
+
/** A pending task some blocker still holds back. */
|
|
76
|
+
export function isTeamTaskBlocked(task) {
|
|
77
|
+
return task.status === 'pending' && !task.ready;
|
|
78
|
+
}
|