@deepseek-harness-tui/dsh-tui 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -5
- 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 +15 -0
- package/guide/dsh-tui-guide/getting-started.md +15 -0
- 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 +95 -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 +3 -2
- 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 +35 -10
- 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/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/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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { t } from '../i18n.js';
|
|
3
|
+
import { Box, Text } from '../ui.js';
|
|
4
|
+
import { cleanRenderText, NOTICE_CELLS } from '../channel/sanitize.js';
|
|
5
|
+
import { HintLine } from './design-system/HintLine.js';
|
|
6
|
+
import { LoadingState } from './design-system/LoadingState.js';
|
|
7
|
+
import { Pane } from './design-system/Pane.js';
|
|
8
|
+
/** Foreign text on its way to the screen: control sequences stripped, bounded. */
|
|
9
|
+
const clean = (value) => cleanRenderText(value, NOTICE_CELLS);
|
|
10
|
+
/**
|
|
11
|
+
* The target's identity is the subject of the question, and it is foreign text
|
|
12
|
+
* like everything else here: a package name and a module specifier come from
|
|
13
|
+
* somebody else's manifest, so either can carry newlines or thousands of cells.
|
|
14
|
+
* Bounded to what a line can show — at 50 columns an unbounded name buries the
|
|
15
|
+
* title and the key hints, which are exactly what the person needs to answer.
|
|
16
|
+
*/
|
|
17
|
+
const TARGET_CELLS = 80;
|
|
18
|
+
/**
|
|
19
|
+
* `/plugin remove | enable | disable`: the pane that asks what the flow cannot
|
|
20
|
+
* answer on its own (Stage C-5).
|
|
21
|
+
*
|
|
22
|
+
* The flow (`dsh-adapter/plugin-manage.ts`) writes every line of the action into
|
|
23
|
+
* the transcript — what it resolved, why it refused, what the service answered —
|
|
24
|
+
* so this pane only carries the one thing a person must decide before the write.
|
|
25
|
+
* Unlike the install pane there is no progress, no cancellation and no retry:
|
|
26
|
+
* each action is a single call that settles once.
|
|
27
|
+
*
|
|
28
|
+
* Presentational only, and the same three parts as its install sibling
|
|
29
|
+
* (`PluginInstallPane`): the pane, the facts that make the question answerable,
|
|
30
|
+
* and the key hints. Keys are handled in Chat (Enter answers, Esc closes).
|
|
31
|
+
*/
|
|
32
|
+
export function PluginManagePane({ step, busy }) {
|
|
33
|
+
if (busy) {
|
|
34
|
+
// A write is in flight. Esc closes the pane and the write finishes anyway —
|
|
35
|
+
// the service has no cancellation for these three, and saying "cancelling"
|
|
36
|
+
// here would be a promise nobody can keep.
|
|
37
|
+
return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "remember", bold: true, children: t('plugins-manage-pane-title') }), _jsx(Box, { marginTop: 1, children: _jsx(LoadingState, { message: t('plugins-manage-working') }) })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('plugins-manage-key-busy') }) })] }));
|
|
38
|
+
}
|
|
39
|
+
if (step.kind === 'confirm') {
|
|
40
|
+
return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "remember", bold: true, children: t('plugins-manage-pane-title') }) }), _jsx(Text, { children: t('plugins-manage-configure', {
|
|
41
|
+
action: t(actionKeyOf(step.target)),
|
|
42
|
+
target: describe(step.target),
|
|
43
|
+
}) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [step.question.kind === 'remove' && (_jsx(Text, { children: t('plugins-manage-remove-facts', {
|
|
44
|
+
rows: String(step.target.kind === 'bundle' ? step.target.rows : 0),
|
|
45
|
+
overrides: String(step.target.kind === 'bundle' ? step.target.overrides : 0),
|
|
46
|
+
}) })), step.question.kind === 'trust' && _jsx(Text, { children: t('plugins-manage-trust-facts') }), step.question.kind === 'host-row' && _jsx(Text, { children: t('plugins-manage-host-row-facts') }), step.question.kind === 'team-active' && (_jsxs(_Fragment, { children: [step.question.members > 0 && _jsx(Text, { children: t('plugins-manage-team-active-facts', { members: String(step.question.members) }) }), step.question.unseen > 0 && _jsx(Text, { children: t('plugins-manage-team-unseen-facts', { members: String(step.question.unseen) }) }), _jsx(Text, { children: t('plugins-manage-team-active-stop') })] }))] })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('plugins-manage-key-confirm') }) })] }));
|
|
47
|
+
}
|
|
48
|
+
// `done` never renders: its lines are already in the transcript, so Chat
|
|
49
|
+
// closes the pane instead of leaving an empty box behind.
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/** Which verb the title asks about. */
|
|
53
|
+
function actionKeyOf(target) {
|
|
54
|
+
return target.action === 'remove'
|
|
55
|
+
? 'plugins-manage-action-remove'
|
|
56
|
+
: target.action === 'enable' ? 'plugins-manage-action-enable' : 'plugins-manage-action-disable';
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The target as one bounded cell. A bundle is named by its package name; a row
|
|
60
|
+
* by the module it loads, which is what the report listed it as and what a
|
|
61
|
+
* person typed to get here.
|
|
62
|
+
*/
|
|
63
|
+
function describe(target) {
|
|
64
|
+
if (target.kind === 'bundle') {
|
|
65
|
+
const version = target.version === undefined ? '' : `@${target.version}`;
|
|
66
|
+
return cleanRenderText(`${target.name}${version}`, TARGET_CELLS);
|
|
67
|
+
}
|
|
68
|
+
return cleanRenderText(target.moduleName, TARGET_CELLS);
|
|
69
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -954,6 +954,7 @@ export function PromptInput({ channel, toastSuppressed, suspended = false, curso
|
|
|
954
954
|
// index space: `suggestions` stays the only list selection, Enter dispatch and
|
|
955
955
|
// clicks read, and the default selection stays the first normal-region row.
|
|
956
956
|
// The region is marked by colour only — it costs no display row.
|
|
957
|
+
const completionInput = value;
|
|
957
958
|
const completions = value.startsWith('/') ? channel.commandCompletions(value) : [];
|
|
958
959
|
const holdOf = (commandLine) => workingHoldOf(commandLine, channel.commandList.find(command => command.name === commandLine.replace(/^\//, '').split(/[\t ]/u)[0])?.skill === true) !== undefined;
|
|
959
960
|
const normalCompletions = channel.working
|
|
@@ -1709,7 +1710,10 @@ export function PromptInput({ channel, toastSuppressed, suspended = false, curso
|
|
|
1709
1710
|
editDocked(dockSelectedRef.current);
|
|
1710
1711
|
return;
|
|
1711
1712
|
}
|
|
1712
|
-
|
|
1713
|
+
// A preceding edit in this stdin batch has already updated valueRef, but
|
|
1714
|
+
// the completion rows still belong to the last render. Submit the current
|
|
1715
|
+
// draft through the ordinary path instead of accepting a stale row.
|
|
1716
|
+
if (overlayOpen && value === completionInput) {
|
|
1713
1717
|
const command = suggestions[selectedCommand];
|
|
1714
1718
|
if (command) {
|
|
1715
1719
|
tryRunCommand(command.commandLine);
|
|
@@ -2427,7 +2431,7 @@ export function PromptInput({ channel, toastSuppressed, suspended = false, curso
|
|
|
2427
2431
|
}
|
|
2428
2432
|
if (key.tab && overlayOpen) {
|
|
2429
2433
|
const command = suggestions[selectedCommand];
|
|
2430
|
-
if (command) {
|
|
2434
|
+
if (command && value === completionInput) {
|
|
2431
2435
|
updateFoldBlock(null);
|
|
2432
2436
|
setInput(command.replacement, command.replacement.length, 'step');
|
|
2433
2437
|
}
|
|
@@ -3809,7 +3813,7 @@ export function PromptInput({ channel, toastSuppressed, suspended = false, curso
|
|
|
3809
3813
|
onPick: (index) => {
|
|
3810
3814
|
const command = suggestions[index];
|
|
3811
3815
|
if (command)
|
|
3812
|
-
tryRunCommand(command.commandLine);
|
|
3816
|
+
tryRunCommand(valueRef.current === completionInput ? command.commandLine : valueRef.current);
|
|
3813
3817
|
},
|
|
3814
3818
|
// 滚轮 = 移动选中行(与 ↑/↓ 同路径,窗口跟随)
|
|
3815
3819
|
onWheelStep: (step) => {
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { SubagentState } from '../dsh-adapter/subagents.js';
|
|
3
3
|
import type { ClickEvent } from '../ink/events/click-event.js';
|
|
4
|
+
import type { TeamMemberStatus } from './teamRoster.js';
|
|
4
5
|
export interface SubagentCardProps {
|
|
5
6
|
subagent: SubagentState;
|
|
6
7
|
focused?: boolean;
|
|
7
8
|
onClick?(event: ClickEvent): void;
|
|
8
9
|
variant?: 'default' | 'panel';
|
|
10
|
+
/** Agent Teams: the row is this teammate — its name replaces the
|
|
11
|
+
* description and its member state replaces the run status. */
|
|
12
|
+
teamMember?: {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly status: TeamMemberStatus;
|
|
15
|
+
};
|
|
9
16
|
}
|
|
10
|
-
|
|
17
|
+
/** Status glyph and color of a team member (`·`-style in minimal UI). */
|
|
18
|
+
export declare function teamStatusGlyph(status: TeamMemberStatus, minimalUi: boolean): {
|
|
19
|
+
readonly glyph: string;
|
|
20
|
+
readonly color?: 'warning' | 'subtle' | 'error' | 'accent';
|
|
21
|
+
};
|
|
22
|
+
export declare function SubagentCard({ subagent, focused, onClick, variant, teamMember }: SubagentCardProps): React.ReactNode;
|
|
11
23
|
//# sourceMappingURL=SubagentCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubagentCard.d.ts","sourceRoot":"","sources":["../../../src/components/SubagentCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAIhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"SubagentCard.d.ts","sourceRoot":"","sources":["../../../src/components/SubagentCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAIhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAOvD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,aAAa,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACjC,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B;oEACgE;IAChE,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAA;CAC1E;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;CAAE,CAQpK;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAmB,EAAE,UAAU,EAAE,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CA2FhI"}
|
|
@@ -8,9 +8,21 @@ function formatDuration(ms) {
|
|
|
8
8
|
const seconds = Math.floor(ms / 1000);
|
|
9
9
|
return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m${seconds % 60}s`;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/** Status glyph and color of a team member (`·`-style in minimal UI). */
|
|
12
|
+
export function teamStatusGlyph(status, minimalUi) {
|
|
13
|
+
switch (status) {
|
|
14
|
+
case 'running': return minimalUi ? { glyph: '·' } : { glyph: '🟡', color: 'warning' };
|
|
15
|
+
case 'idle': return minimalUi ? { glyph: '○' } : { glyph: '🔵', color: 'accent' };
|
|
16
|
+
case 'active': return minimalUi ? { glyph: '◇' } : { glyph: '🟣', color: 'accent' };
|
|
17
|
+
case 'provisioning': return minimalUi ? { glyph: '…' } : { glyph: '⚪', color: 'subtle' };
|
|
18
|
+
case 'failed': return minimalUi ? { glyph: '×' } : { glyph: '🔴', color: 'error' };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function SubagentCard({ subagent, focused, onClick, variant = 'default', teamMember }) {
|
|
12
22
|
const panelMode = variant === 'panel';
|
|
13
|
-
const running =
|
|
23
|
+
const running = teamMember !== undefined
|
|
24
|
+
? teamMember.status === 'running'
|
|
25
|
+
: subagent.status === 'running' || subagent.status === 'starting';
|
|
14
26
|
const [clockRef] = useAnimationFrame(running ? 1000 : null);
|
|
15
27
|
// Unknown rows have no completion time, so they do not get a fabricated duration.
|
|
16
28
|
const elapsed = running
|
|
@@ -25,15 +37,18 @@ export function SubagentCard({ subagent, focused, onClick, variant = 'default' }
|
|
|
25
37
|
const [hovered, setHovered] = useState(false);
|
|
26
38
|
const liveLine = running ? subagent.output[subagent.output.length - 1] : undefined;
|
|
27
39
|
const minimalUi = isMinimalUiMode();
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
const teamGlyph = teamMember === undefined ? undefined : teamStatusGlyph(teamMember.status, minimalUi);
|
|
41
|
+
const glyph = teamGlyph !== undefined ? teamGlyph.glyph
|
|
42
|
+
: running ? (minimalUi ? '·' : '🟡')
|
|
43
|
+
: subagent.status === 'unknown' ? (minimalUi ? '·' : '⚪')
|
|
44
|
+
: subagent.status === 'failed' || subagent.status === 'cancelled' ? (minimalUi ? '×' : '🔴')
|
|
45
|
+
: (minimalUi ? '✓' : '🟢');
|
|
46
|
+
const glyphColor = teamGlyph !== undefined ? teamGlyph.color
|
|
47
|
+
: minimalUi ? undefined
|
|
48
|
+
: running ? 'warning'
|
|
49
|
+
: subagent.status === 'unknown' ? 'subtle'
|
|
50
|
+
: subagent.status === 'failed' || subagent.status === 'cancelled' ? 'error'
|
|
51
|
+
: 'success';
|
|
37
52
|
const hoverTint = onClick !== undefined && hovered && !focused;
|
|
38
53
|
// Keep the description on one row; narrower panels progressively drop metadata.
|
|
39
54
|
const { columns } = useTerminalSize();
|
|
@@ -55,7 +70,7 @@ export function SubagentCard({ subagent, focused, onClick, variant = 'default' }
|
|
|
55
70
|
subagent.effort,
|
|
56
71
|
shownDuration === undefined ? undefined : formatDuration(shownDuration),
|
|
57
72
|
].filter(part => part !== undefined && part !== '').join(' · ');
|
|
58
|
-
return _jsxs(Box, { ref: clockRef, flexDirection: "column", paddingLeft: 1, marginBottom: panelMode ? 0 : 1, onClick: onClick, onMouseEnter: onClick !== undefined ? () => setHovered(true) : undefined, onMouseLeave: onClick !== undefined ? () => setHovered(false) : undefined, backgroundColor: hoverTint ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { flexShrink: 0, marginRight: 1, children: _jsx(Text, { color: glyphColor, children: glyph }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { bold: true, color: focused ? 'accent' : undefined, wrap: "truncate-end", children: panelMode ? subagent.description : `${t('subagent-card-prefix')}${subagent.description}` }) }), subagent.mode === 'continuable' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: focused ? 'accent' : 'warning', children: t('subagent-mode-continuable') }) })), subagent.mode === 'one-shot' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { dimColor: true, children: t('subagent-mode-one-shot') }) })), !panelMode && meta !== '' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { dimColor: true, wrap: "truncate-end", children: meta }) }))] }), panelMode && panelMeta !== '' && _jsx(Box, { paddingLeft: 3, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: panelMeta }) }), panelMode
|
|
73
|
+
return _jsxs(Box, { ref: clockRef, flexDirection: "column", paddingLeft: 1, marginBottom: panelMode ? 0 : 1, onClick: onClick, onMouseEnter: onClick !== undefined ? () => setHovered(true) : undefined, onMouseLeave: onClick !== undefined ? () => setHovered(false) : undefined, backgroundColor: hoverTint ? 'userMessageBackgroundHover' : undefined, children: [_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { flexShrink: 0, marginRight: 1, children: _jsx(Text, { color: glyphColor, children: glyph }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { bold: true, color: focused ? 'accent' : undefined, wrap: "truncate-end", children: teamMember !== undefined ? teamMember.name : panelMode ? subagent.description : `${t('subagent-card-prefix')}${subagent.description}` }) }), teamMember !== undefined && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: focused ? 'accent' : teamGlyph?.color, dimColor: teamMember.status === 'provisioning', children: t(`team-status-${teamMember.status}`) }) })), teamMember === undefined && subagent.mode === 'continuable' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: focused ? 'accent' : 'warning', children: t('subagent-mode-continuable') }) })), teamMember === undefined && subagent.mode === 'one-shot' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { dimColor: true, children: t('subagent-mode-one-shot') }) })), !panelMode && meta !== '' && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { dimColor: true, wrap: "truncate-end", children: meta }) }))] }), panelMode && panelMeta !== '' && _jsx(Box, { paddingLeft: 3, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: panelMeta }) }), panelMode
|
|
59
74
|
? previewRows.map(row => _jsx(Text, { dimColor: true, wrap: "truncate", children: ` ${row.text}` }, row.key))
|
|
60
75
|
: liveLine !== undefined && _jsx(Text, { dimColor: true, wrap: "truncate", children: ` │ ${liveLine}` })] });
|
|
61
76
|
}
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { SubagentState } from '../dsh-adapter/subagents.js';
|
|
3
3
|
import type { SidePanelKeyFlags } from './sidePanel/types.js';
|
|
4
4
|
import type { AgentMessageView, AgentIdentity } from './messages/agentTeam.js';
|
|
5
|
+
import type { TeamView } from '../adapter/ports/channel-view.js';
|
|
5
6
|
export interface SubagentDashboardProps {
|
|
6
7
|
subagents: readonly SubagentState[];
|
|
7
8
|
/** Optional cross-session agents, kept separate from this session children. */
|
|
@@ -15,6 +16,12 @@ export interface SubagentDashboardProps {
|
|
|
15
16
|
onOpenView?: (agentId: string) => void;
|
|
16
17
|
/** 代理↔代理消息流:每张卡下显示最后一条 from → to 摘要。 */
|
|
17
18
|
messages?: readonly AgentMessageView[];
|
|
19
|
+
/** Agent Teams: present → team mode (members joined with their subagent
|
|
20
|
+
* rows, a read-only task board, the failure banner). */
|
|
21
|
+
team?: TeamView;
|
|
22
|
+
/** The session on screen: inside a teammate the subagent rows are its own
|
|
23
|
+
* children, so the roster is not joined with them. */
|
|
24
|
+
sessionId?: string;
|
|
18
25
|
/** `panel` 挂在侧栏宿主里(去外层 padding、键盘走 usePanelInput 分发器);
|
|
19
26
|
* default(缺省)与整屏形态逐字节一致。 */
|
|
20
27
|
variant?: 'default' | 'panel';
|
|
@@ -32,5 +39,5 @@ export declare function ExitButton({ onClick }: {
|
|
|
32
39
|
* SubagentDashboard — overlay panel showing all active/recent subagents.
|
|
33
40
|
* Keyboard: up/down to navigate, Enter to view detail, Esc to close.
|
|
34
41
|
*/
|
|
35
|
-
export declare function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenView, messages, variant, focused, visible, }: SubagentDashboardProps): React.ReactNode;
|
|
42
|
+
export declare function SubagentDashboard({ subagents, team, sessionId, peers, onClose, onSelect, onOpenView, messages, variant, focused, visible, }: SubagentDashboardProps): React.ReactNode;
|
|
36
43
|
//# sourceMappingURL=SubagentDashboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubagentDashboard.d.ts","sourceRoot":"","sources":["../../../src/components/SubagentDashboard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAMhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"SubagentDashboard.d.ts","sourceRoot":"","sources":["../../../src/components/SubagentDashboard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAMhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAC9E,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,kCAAkC,CAAA;AAI1E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAA;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IACzC;mDAC+C;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC;0BACsB;IACtB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACtC;6DACyD;IACzD,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf;2DACuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;iCAC6B;IAC7B,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAOjF;AAED,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAWhF;AAgED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,IAAI,EACJ,SAAS,EACT,KAAK,EACL,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,OAAmB,EACnB,OAAc,EACd,OAAc,GACf,EAAE,sBAAsB,GAAG,KAAK,CAAC,SAAS,CAkS1C"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Box, Text, useInput, ScrollBox, useTerminalSize } from '../ui.js';
|
|
4
|
-
import { SubagentCard } from './SubagentCard.js';
|
|
4
|
+
import { SubagentCard, teamStatusGlyph } from './SubagentCard.js';
|
|
5
5
|
import { t } from '../i18n.js';
|
|
6
6
|
import { Divider } from './design-system/Divider.js';
|
|
7
7
|
import { isPlainReturnInput } from '../utils/modifiers.js';
|
|
8
8
|
import { usePanelInput } from './sidePanel/usePanelInput.js';
|
|
9
9
|
import { AgentMessagesSummary } from './messages/AgentMessageFlow.js';
|
|
10
|
+
import { isTeamTaskBlocked, teamDashboardModel, teamTaskProgress } from './teamRoster.js';
|
|
11
|
+
import { isMinimalUiMode } from '../minimalUiMode.js';
|
|
10
12
|
/** Accept Ink's Enter flag and the panel dispatcher's normalized alias. */
|
|
11
13
|
export function isPanelPlainReturn(input, key) {
|
|
12
14
|
return isPlainReturnInput(input, {
|
|
@@ -21,13 +23,29 @@ export function ExitButton({ onClick }) {
|
|
|
21
23
|
const [hovered, setHovered] = React.useState(false);
|
|
22
24
|
return (_jsx(Box, { onClick: onClick, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), children: _jsx(Text, { color: hovered ? 'text' : 'subtle', children: ' ✕' }) }));
|
|
23
25
|
}
|
|
26
|
+
/** A teammate the host has not announced as a subagent yet. */
|
|
27
|
+
function TeamRosterOnlyRow({ row, focused, panelMode, self }) {
|
|
28
|
+
const { glyph, color } = teamStatusGlyph(row.status, isMinimalUiMode());
|
|
29
|
+
return (_jsxs(Box, { flexDirection: "row", paddingLeft: 1, marginBottom: panelMode ? 0 : 1, children: [_jsx(Box, { flexShrink: 0, marginRight: 1, children: _jsx(Text, { color: color, children: glyph }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { bold: true, color: focused ? 'accent' : undefined, children: row.member.name }), self && _jsx(Text, { dimColor: true, children: ' · ' + t('team-self-mark') })] }) }), _jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: focused ? 'accent' : color, dimColor: row.status === 'provisioning', children: t(`team-status-${row.status}`) }) })] }));
|
|
30
|
+
}
|
|
31
|
+
const TASK_GLYPH = {
|
|
32
|
+
pending: { glyph: '○', color: 'subtle' },
|
|
33
|
+
in_progress: { glyph: '◐', color: 'accent' },
|
|
34
|
+
completed: { glyph: '●', color: 'success' },
|
|
35
|
+
};
|
|
36
|
+
/** The team's shared task board, read-only; narrow widths drop the owner. */
|
|
37
|
+
function TeamTaskBoard({ tasks }) {
|
|
38
|
+
const { columns } = useTerminalSize();
|
|
39
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { dimColor: true, wrap: "truncate-end", children: t('team-tasks-title', teamTaskProgress(tasks)) }), tasks.length === 0 && _jsx(Text, { dimColor: true, children: ' ' + t('team-tasks-empty') }), tasks.map(task => (_jsxs(Box, { flexDirection: "row", paddingLeft: 1, children: [_jsx(Box, { flexShrink: 0, marginRight: 1, children: _jsx(Text, { color: TASK_GLYPH[task.status].color, children: TASK_GLYPH[task.status].glyph }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", children: _jsx(Text, { dimColor: task.status === 'completed', wrap: "truncate-end", children: task.subject }) }), columns >= 40 && task.ownerName !== undefined && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { dimColor: true, children: '@' + task.ownerName }) })), isTeamTaskBlocked(task) && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: "warning", children: t('team-task-blocked') }) })), task.writeScopeWarnings.length > 0 && (_jsx(Box, { flexShrink: 0, marginLeft: 1, children: _jsx(Text, { color: "warning", children: '⚠' + task.writeScopeWarnings.length }) }))] }, task.id)))] }));
|
|
40
|
+
}
|
|
24
41
|
/**
|
|
25
42
|
* SubagentDashboard — overlay panel showing all active/recent subagents.
|
|
26
43
|
* Keyboard: up/down to navigate, Enter to view detail, Esc to close.
|
|
27
44
|
*/
|
|
28
|
-
export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenView, messages, variant = 'default', focused = true, visible = true, }) {
|
|
45
|
+
export function SubagentDashboard({ subagents, team, sessionId, peers, onClose, onSelect, onOpenView, messages, variant = 'default', focused = true, visible = true, }) {
|
|
29
46
|
const panelMode = variant === 'panel';
|
|
30
|
-
|
|
47
|
+
// Focus follows the row's key: team mode reorders the rows, and the roster can shrink.
|
|
48
|
+
const [focus, setFocus] = React.useState({ index: 0 });
|
|
31
49
|
const scrollRef = React.useRef(null);
|
|
32
50
|
const { rows, columns } = useTerminalSize();
|
|
33
51
|
// Keep top-level children first when the roster includes nested agents.
|
|
@@ -35,6 +53,29 @@ export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenV
|
|
|
35
53
|
const nestedRows = subagents.filter(isNestedSpawn);
|
|
36
54
|
const flatRows = subagents.filter(row => !isNestedSpawn(row));
|
|
37
55
|
const ordered = nestedRows.length === 0 ? subagents : [...flatRows, ...nestedRows];
|
|
56
|
+
const model = team === undefined ? undefined : teamDashboardModel(team, subagents, sessionId);
|
|
57
|
+
const others = new Set(model?.others);
|
|
58
|
+
const nested = nestedRows.length;
|
|
59
|
+
const rowEntry = (subagent) => ({ key: subagent.agentId, subagent, nested: nested > 0 && isNestedSpawn(subagent) });
|
|
60
|
+
const entries = model === undefined
|
|
61
|
+
? ordered.map(rowEntry)
|
|
62
|
+
: [
|
|
63
|
+
...model.teammates.map(row => ({ key: row.member.id, teamRow: row, nested: false, ...row.subagent === undefined ? {} : { subagent: row.subagent } })),
|
|
64
|
+
...ordered.filter(row => others.has(row)).map(rowEntry),
|
|
65
|
+
];
|
|
66
|
+
const othersStart = model === undefined ? -1 : model.teammates.length;
|
|
67
|
+
const focusOf = (state) => {
|
|
68
|
+
const found = state.key === undefined ? -1 : entries.findIndex(entry => entry.key === state.key);
|
|
69
|
+
return found >= 0 ? found : Math.min(state.index, Math.max(0, entries.length - 1));
|
|
70
|
+
};
|
|
71
|
+
const focusIndex = focusOf(focus);
|
|
72
|
+
const moveFocus = (delta) => {
|
|
73
|
+
setFocus((prev) => {
|
|
74
|
+
const index = Math.max(0, Math.min(entries.length - 1, focusOf(prev) + delta));
|
|
75
|
+
const key = entries[index]?.key;
|
|
76
|
+
return key === undefined ? { index } : { index, key };
|
|
77
|
+
});
|
|
78
|
+
};
|
|
38
79
|
useInput((input, key, event) => {
|
|
39
80
|
if (panelMode)
|
|
40
81
|
return;
|
|
@@ -45,19 +86,19 @@ export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenV
|
|
|
45
86
|
}
|
|
46
87
|
if (key.upArrow) {
|
|
47
88
|
event.stopImmediatePropagation();
|
|
48
|
-
|
|
89
|
+
moveFocus(-1);
|
|
49
90
|
scrollRef.current?.scrollBy(-3);
|
|
50
91
|
return;
|
|
51
92
|
}
|
|
52
93
|
if (key.downArrow) {
|
|
53
94
|
event.stopImmediatePropagation();
|
|
54
|
-
|
|
95
|
+
moveFocus(1);
|
|
55
96
|
scrollRef.current?.scrollBy(3);
|
|
56
97
|
return;
|
|
57
98
|
}
|
|
58
99
|
if (isPlainReturnInput(input, key) && onSelect) {
|
|
59
100
|
event.stopImmediatePropagation();
|
|
60
|
-
const selected =
|
|
101
|
+
const selected = entries[focusIndex]?.subagent;
|
|
61
102
|
if (selected)
|
|
62
103
|
onSelect(selected.agentId);
|
|
63
104
|
return;
|
|
@@ -65,7 +106,7 @@ export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenV
|
|
|
65
106
|
// v = 主屏查看(Enter 仍是详情)。
|
|
66
107
|
if (input.toLowerCase() === 'v' && onOpenView) {
|
|
67
108
|
event.stopImmediatePropagation();
|
|
68
|
-
const selected =
|
|
109
|
+
const selected = entries[focusIndex]?.subagent;
|
|
69
110
|
if (selected)
|
|
70
111
|
onOpenView(selected.agentId);
|
|
71
112
|
return;
|
|
@@ -78,23 +119,23 @@ export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenV
|
|
|
78
119
|
if (key.escape === true || (key.ctrl === true && input === 'c'))
|
|
79
120
|
return false;
|
|
80
121
|
if (key.upArrow === true) {
|
|
81
|
-
|
|
122
|
+
moveFocus(-1);
|
|
82
123
|
scrollRef.current?.scrollBy(-3);
|
|
83
124
|
return true;
|
|
84
125
|
}
|
|
85
126
|
if (key.downArrow === true) {
|
|
86
|
-
|
|
127
|
+
moveFocus(1);
|
|
87
128
|
scrollRef.current?.scrollBy(3);
|
|
88
129
|
return true;
|
|
89
130
|
}
|
|
90
131
|
if (isPanelPlainReturn(input, key)) {
|
|
91
|
-
const selected =
|
|
132
|
+
const selected = entries[focusIndex]?.subagent;
|
|
92
133
|
if (selected !== undefined)
|
|
93
134
|
onSelect?.(selected.agentId);
|
|
94
135
|
return true;
|
|
95
136
|
}
|
|
96
137
|
if (input.toLowerCase() === 'v' && onOpenView !== undefined) {
|
|
97
|
-
const selected =
|
|
138
|
+
const selected = entries[focusIndex]?.subagent;
|
|
98
139
|
if (selected !== undefined)
|
|
99
140
|
onOpenView(selected.agentId);
|
|
100
141
|
return true;
|
|
@@ -105,13 +146,14 @@ export function SubagentDashboard({ subagents, peers, onClose, onSelect, onOpenV
|
|
|
105
146
|
const running = subagents.filter(s => s.status === 'running').length;
|
|
106
147
|
const completed = subagents.filter(s => s.status === 'completed').length;
|
|
107
148
|
const failed = subagents.filter(s => s.status === 'failed').length;
|
|
108
|
-
const
|
|
149
|
+
const memberCount = (status) => model?.teammates.filter(row => row.status === status).length ?? 0;
|
|
150
|
+
const teamSep = panelMode ? ' · ' : ' ';
|
|
109
151
|
// Full-screen keeps its inset; the panel uses one cell on each side.
|
|
110
152
|
const outer = panelMode
|
|
111
153
|
? { paddingLeft: 1, paddingRight: 1, paddingTop: 0 }
|
|
112
154
|
: { paddingX: 2, paddingY: 1 };
|
|
113
|
-
return (_jsxs(Box, { flexDirection: "column", ...outer, children: [!panelMode && _jsx(Divider, { color: "accent", title: t('subagent-dashboard-title') }), _jsxs(Box, { flexDirection: "row", gap: 3, marginTop: panelMode ? 0 : 1, marginBottom: panelMode ? 0 : 1, children: [_jsxs(Text, { children: [_jsx(Text, { color: "accent", children: running }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-running')] })] }), _jsxs(Text, { children: [_jsx(Text, { color: "success", children: completed }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-completed')] })] }), failed > 0 && (_jsxs(Text, { children: [_jsx(Text, { color: "error", children: failed }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-failed')] })] })), nested > 0 && (_jsxs(Text, { children: [_jsx(Text, { color: "accent", children: nested }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-nested')] })] })), _jsx(Box, { flexGrow: 1 }), !panelMode && onClose !== undefined && _jsx(ExitButton, { onClick: onClose })] }), _jsx(Box, { flexDirection: "column", maxHeight: panelMode ? Math.max(6, rows - 4) : Math.max(10, rows - 10), marginTop: panelMode ? 0 : 1, children:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
155
|
+
return (_jsxs(Box, { flexDirection: "column", ...outer, children: [!panelMode && _jsx(Divider, { color: "accent", title: t(team === undefined ? 'subagent-dashboard-title' : 'team-dashboard-title') }), _jsxs(Box, { flexDirection: "row", gap: 3, marginTop: panelMode ? 0 : 1, marginBottom: panelMode ? 0 : 1, children: [team !== undefined ? (_jsx(Box, { flexShrink: 1, overflow: "hidden", children: _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { color: "accent", children: memberCount('running') }), _jsx(Text, { dimColor: true, children: ' ' + t('team-status-running') + teamSep }), _jsx(Text, { color: "accent", children: memberCount('idle') }), _jsx(Text, { dimColor: true, children: ' ' + t('team-status-idle') + teamSep }), memberCount('provisioning') > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: memberCount('provisioning') }), _jsx(Text, { dimColor: true, children: ' ' + t('team-status-provisioning') + teamSep })] })), memberCount('active') > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "accent", children: memberCount('active') }), _jsx(Text, { dimColor: true, children: ' ' + t('team-status-active') + teamSep })] })), memberCount('failed') > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "error", children: memberCount('failed') }), _jsx(Text, { dimColor: true, children: ' ' + t('team-status-failed') + teamSep })] })), _jsx(Text, { dimColor: true, children: t('team-tasks-count', teamTaskProgress(team.tasks)) })] }) })) : (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [_jsx(Text, { color: "accent", children: running }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-running')] })] }), _jsxs(Text, { children: [_jsx(Text, { color: "success", children: completed }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-completed')] })] }), failed > 0 && (_jsxs(Text, { children: [_jsx(Text, { color: "error", children: failed }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-failed')] })] })), nested > 0 && (_jsxs(Text, { children: [_jsx(Text, { color: "accent", children: nested }), _jsxs(Text, { dimColor: true, children: [" ", t('subagent-count-nested')] })] }))] })), _jsx(Box, { flexGrow: 1 }), !panelMode && onClose !== undefined && _jsx(ExitButton, { onClick: onClose })] }), team?.failure !== undefined && (_jsx(Text, { color: "error", wrap: "wrap", children: '⚠ ' + t('team-failure', { failure: team.failure }) })), _jsx(Box, { flexDirection: "column", maxHeight: panelMode ? Math.max(6, rows - 4) : Math.max(10, rows - 10), marginTop: panelMode ? 0 : 1, children: _jsxs(ScrollBox, { ref: scrollRef, flexDirection: "column", flexGrow: 1, children: [model !== undefined && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: t('team-members-title') }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: ' ◆ ' + t(model.viewedFromLead ? 'team-lead-row' : 'team-lead-row-peer') })] })), model === undefined && subagents.length === 0 ? (_jsxs(Box, { flexDirection: "column", alignItems: "center", marginTop: Math.max(2, Math.floor((rows - 16) / 3)), children: [_jsx(Text, { dimColor: true, children: '○' }), _jsx(Text, { dimColor: true, children: t('subagent-none') }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t('subagent-empty-hint') }) })] })) : (entries.map(({ key, subagent, teamRow, nested: nestedMark }, index) => (_jsxs(Box, { flexDirection: "column", children: [index === othersStart && _jsx(Text, { dimColor: true, children: t('team-others-title') }), nestedMark && (_jsx(Text, { dimColor: true, children: ' ↳ ' + t('subagent-nested-mark') })), subagent === undefined ? (teamRow !== undefined && _jsx(TeamRosterOnlyRow, { row: teamRow, focused: index === focusIndex, panelMode: panelMode, self: teamRow.member.id === sessionId })) : (_jsx(SubagentCard, { subagent: subagent, variant: panelMode ? 'panel' : 'default', focused: index === focusIndex, onClick: onSelect !== undefined
|
|
156
|
+
// Click = view detail, same as Enter on the focused card.
|
|
157
|
+
? () => onSelect(subagent.agentId)
|
|
158
|
+
: undefined, ...teamRow === undefined ? {} : { teamMember: { name: teamRow.member.name, status: teamRow.status } } })), teamRow?.status === 'failed' && teamRow.member.error !== undefined && (_jsx(Text, { color: "error", wrap: "truncate-end", children: ' │ ' + teamRow.member.error })), teamRow?.status === 'idle' && subagent?.status === 'failed' && (_jsx(Text, { color: "error", wrap: "truncate-end", children: ' │ ' + t('team-last-run-failed', { error: subagent.error ?? '' }).trimEnd() })), subagent !== undefined && messages !== undefined && messages.length > 0 && (_jsx(AgentMessagesSummary, { messages: messages.filter(message => message.from === subagent.agentId || message.to === subagent.agentId), selfAgentId: subagent.agentId })), subagent !== undefined && onOpenView !== undefined && (!panelMode || index === focusIndex) && (_jsx(Box, { paddingLeft: 1, onClick: () => onOpenView(subagent.agentId), children: _jsx(Text, { color: "subtle", children: `⤢ ${t('agent-view-open-action')}` }) })), !panelMode && index < entries.length - 1 && index + 1 !== othersStart && (_jsx(Text, { dimColor: true, children: '─'.repeat(Math.max(20, Math.min(72, columns - 6))) }))] }, key)))), team !== undefined && _jsx(TeamTaskBoard, { tasks: team.tasks })] }) }), peers !== undefined && (!panelMode || peers.length > 0) && (_jsx(Box, { flexDirection: "column", children: panelMode ? (_jsx(Text, { dimColor: true, wrap: "truncate-end", children: t('agents-peers-title') + ' · ' + peers.length })) : (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: t('agents-peers-title') }), peers.length === 0 ? (_jsx(Text, { dimColor: true, children: ' ' + t('agents-peers-empty') })) : (_jsxs(Box, { flexDirection: "column", children: [peers.map(peer => (_jsx(Text, { dimColor: true, wrap: "truncate-end", children: ' · ' + (peer.name ?? peer.label ?? peer.agentId.slice(0, 8)) + ' · ' + peer.agentId.slice(0, 8) }, peer.agentId))), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: ' ' + t('agents-peers-note') })] }))] })) })), !panelMode && (_jsxs(_Fragment, { children: [_jsx(Divider, { color: "subtle", title: "" }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: onSelect ? t('subagent-dashboard-hint-detail') : t('subagent-dashboard-hint-basic') }) })] }))] }));
|
|
117
159
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { SplashFont } from './splashFonts.js';
|
|
2
|
+
/**
|
|
3
|
+
* 块体大字的行数:上排 5 + 空 1 + 下排 5。
|
|
4
|
+
*
|
|
5
|
+
* 导出是给回归钉的:`portrait` 立绘槽高(`splashArtRows.ts` 的
|
|
6
|
+
* `PORTRAIT_ART_ROWS`)**等于这个数**——`LogoV2` 把娘立绘钳在与文字列等高的
|
|
7
|
+
* 槽里(`textColumnRows` = 两排大字 + 空行),落地页是 `chrome="minimal"`,
|
|
8
|
+
* 槽高就是大字块的行数。两处一漂移,预算就重新和渲染分叉。
|
|
9
|
+
*/
|
|
10
|
+
export declare const BIG_TITLE_ROWS = 11;
|
|
2
11
|
/** 输入框卡片占的行数:边框 2 + 输入 1(第三版:参数行移出框外)。 */
|
|
3
12
|
export declare const CARD_ROWS = 3;
|
|
4
13
|
/** 框下参数行的行数(模型/思考深度/模式/权限全空时整行不画)。 */
|
|
@@ -50,7 +59,9 @@ export interface LaunchpadLayout {
|
|
|
50
59
|
* @param rows - 内容区行数。
|
|
51
60
|
* @param options - whale / whaleGirl 对应设置项;font 是当天那款字体(字身宽度
|
|
52
61
|
* 不同,宽轴阈值也跟着不同);params 是框下有没有参数行(模型/思考深度/模式/
|
|
53
|
-
* 权限全拿不到时为 false
|
|
62
|
+
* 权限全拿不到时为 false,成组行矮一行);`artRows` 是**当天真正上场的立绘**
|
|
63
|
+
* 占的行数(`splashArtRows.ts` 解,缺省按像素鲸鱼 13 行);`cornerRows` 是
|
|
64
|
+
* 右下角铭牌自身的行数(第一行 + 内核数,缺省按老口径 2 行)。
|
|
54
65
|
* @returns 该尺寸下要渲染的部件。
|
|
55
66
|
*/
|
|
56
67
|
export declare function resolveLaunchpadLayout(columns: number, rows: number, options: {
|
|
@@ -58,5 +69,7 @@ export declare function resolveLaunchpadLayout(columns: number, rows: number, op
|
|
|
58
69
|
whaleGirl?: boolean;
|
|
59
70
|
font: SplashFont;
|
|
60
71
|
params?: boolean;
|
|
72
|
+
artRows?: number;
|
|
73
|
+
cornerRows?: number;
|
|
61
74
|
}): LaunchpadLayout;
|
|
62
75
|
//# sourceMappingURL=launchpadLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launchpadLayout.d.ts","sourceRoot":"","sources":["../../../src/components/launchpadLayout.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"launchpadLayout.d.ts","sourceRoot":"","sources":["../../../src/components/launchpadLayout.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAyClD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,KAAK,CAAA;AAIhC,0CAA0C;AAC1C,eAAO,MAAM,SAAS,IAAI,CAAA;AAC1B,sCAAsC;AACtC,eAAO,MAAM,UAAU,IAAI,CAAA;AA2C3B,iBAAiB;AACjB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAA;AAErF,yBAAyB;AACzB,MAAM,WAAW,eAAe;IAC9B,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,kCAAkC;IAClC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,+BAA+B;IAC/B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,gBAAgB;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,4BAA4B;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,6BAA6B;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IACP,KAAK,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GACA,eAAe,CA6FjB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { bigTextWidth } from './bigfont.js';
|
|
2
2
|
import { WHALE_BOX_WIDTH } from './splashLayout.js';
|
|
3
|
+
import { WHALE_ART_ROWS } from './splashArtRows.js';
|
|
3
4
|
/**
|
|
4
5
|
* 落地页的降级阶梯——两个轴一起解:
|
|
5
6
|
*
|
|
@@ -32,10 +33,21 @@ import { WHALE_BOX_WIDTH } from './splashLayout.js';
|
|
|
32
33
|
* 所有列数按**内容区**算(PageMargin 已经把 TerminalSizeContext 收窄);行数
|
|
33
34
|
* 同理。落地页不自己减页边距。
|
|
34
35
|
*/
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
/**
|
|
37
|
+
* 立绘槽的默认行数(像素鲸鱼 13 行)。**真实行数由调用方传 `artRows`**——
|
|
38
|
+
* 槽高随形态变(女仆娘/Claude 娘 11、吉祥物 15),写死 13 会让默认的吉祥物
|
|
39
|
+
* 路径少算 2 行(见 `splashArtRows.ts` 的表与那段修复说明)。
|
|
40
|
+
*/
|
|
41
|
+
const DEFAULT_ART_ROWS = WHALE_ART_ROWS;
|
|
42
|
+
/**
|
|
43
|
+
* 块体大字的行数:上排 5 + 空 1 + 下排 5。
|
|
44
|
+
*
|
|
45
|
+
* 导出是给回归钉的:`portrait` 立绘槽高(`splashArtRows.ts` 的
|
|
46
|
+
* `PORTRAIT_ART_ROWS`)**等于这个数**——`LogoV2` 把娘立绘钳在与文字列等高的
|
|
47
|
+
* 槽里(`textColumnRows` = 两排大字 + 空行),落地页是 `chrome="minimal"`,
|
|
48
|
+
* 槽高就是大字块的行数。两处一漂移,预算就重新和渲染分叉。
|
|
49
|
+
*/
|
|
50
|
+
export const BIG_TITLE_ROWS = 11;
|
|
39
51
|
/** 只留文字的档位:一行纯标题。 */
|
|
40
52
|
const PLAIN_TITLE_ROWS = 1;
|
|
41
53
|
/** 输入框卡片占的行数:边框 2 + 输入 1(第三版:参数行移出框外)。 */
|
|
@@ -73,18 +85,23 @@ const TIP_BLOCK_ROWS = 3;
|
|
|
73
85
|
/** 矮屏撤呼吸后的紧档(自身 1 + 留白 1)。 */
|
|
74
86
|
const TIP_BLOCK_ROWS_TIGHT = 2;
|
|
75
87
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
88
|
+
* 双角铭牌:自身行数 + 上方 1 行留白。自身 = 第一行(`工作目录:分支` 与
|
|
89
|
+
* `dsh-tui v…` 共用底边)+ **一行一个内核**——第八版给右下角扩了内核区,
|
|
90
|
+
* 行数随内核数变,所以**由调用方传 `cornerRows`**;写死 2 行时,装了多个
|
|
91
|
+
* 内核的机器(DSH + Claude + Codex)会少算两行,和立绘槽那处是同一类账
|
|
92
|
+
* 不平(矮屏阶梯以为放得下、实际溢出)。
|
|
80
93
|
*/
|
|
81
|
-
const
|
|
94
|
+
const CORNERS_TOP_GAP_ROWS = 1;
|
|
95
|
+
/** 铭牌自身行数的老口径(第一行 + 一个内核行):内核数拿不到时的上限估算。 */
|
|
96
|
+
const DEFAULT_CORNER_ROWS = 2;
|
|
82
97
|
/**
|
|
83
98
|
* @param columns - 内容区列数。
|
|
84
99
|
* @param rows - 内容区行数。
|
|
85
100
|
* @param options - whale / whaleGirl 对应设置项;font 是当天那款字体(字身宽度
|
|
86
101
|
* 不同,宽轴阈值也跟着不同);params 是框下有没有参数行(模型/思考深度/模式/
|
|
87
|
-
* 权限全拿不到时为 false
|
|
102
|
+
* 权限全拿不到时为 false,成组行矮一行);`artRows` 是**当天真正上场的立绘**
|
|
103
|
+
* 占的行数(`splashArtRows.ts` 解,缺省按像素鲸鱼 13 行);`cornerRows` 是
|
|
104
|
+
* 右下角铭牌自身的行数(第一行 + 内核数,缺省按老口径 2 行)。
|
|
88
105
|
* @returns 该尺寸下要渲染的部件。
|
|
89
106
|
*/
|
|
90
107
|
export function resolveLaunchpadLayout(columns, rows, options) {
|
|
@@ -100,21 +117,23 @@ export function resolveLaunchpadLayout(columns, rows, options) {
|
|
|
100
117
|
const showPlainTitle = !showBigTitle && !showWhale;
|
|
101
118
|
const showHero = showWhale || showBigTitle || showPlainTitle;
|
|
102
119
|
// 上下排布时头部 = 立绘 + 间隔 1 + 大字;退化档位取各自实际行数。
|
|
103
|
-
|
|
120
|
+
// 立绘行数按**当天上场的形态**算(鲸鱼 13 / 娘与吉祥物 15),不写死。
|
|
121
|
+
const artRows = showWhale ? (options.artRows ?? DEFAULT_ART_ROWS) : 0;
|
|
104
122
|
const titleRows = showBigTitle ? BIG_TITLE_ROWS : PLAIN_TITLE_ROWS;
|
|
105
123
|
const heroRows = showHero ? (artRows > 0 ? artRows + 1 + titleRows : titleRows) : 0;
|
|
106
124
|
// 头部整块(含根盒 marginTop)实际占的行数:阶梯与 totalRows 都按它算。
|
|
107
125
|
const heroBlockRows = showHero ? heroRows + HERO_TOP_MARGIN : 0;
|
|
108
126
|
// 第六版行数预算:输入框(恒 3)+ 框下成组行(参数 1 + 呼吸留白 0/1 +
|
|
109
|
-
// 键帽 1 + Tips 3)+
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
127
|
+
// 键帽 1 + Tips 3)+ 双角铭牌(自身行数 + 上方留白)。撤的顺序「从最可省
|
|
128
|
+
// 到最不可省」:新增的两处呼吸(词标↔输入框、入口行↔Tips)→ 参数行呼吸
|
|
129
|
+
// 留白 → Tips 行本身 → 键帽行 → 立绘(**所有留白永远排在 Tips/入口行之
|
|
130
|
+
// 前撤**,绝不让呼吸把输入框挤掉)。
|
|
113
131
|
const paramRows = options.params === true ? PARAM_ROWS : 0;
|
|
114
132
|
const gapRows = paramRows > 0 ? PARAM_HINTS_GAP_ROWS : 0;
|
|
115
133
|
const cardRows = CARD_ROWS;
|
|
134
|
+
const cornersBlockRows = (options.cornerRows ?? DEFAULT_CORNER_ROWS) + CORNERS_TOP_GAP_ROWS;
|
|
116
135
|
const withArt = artRows > 0 ? artRows + 1 : 0;
|
|
117
|
-
const core = heroBlockRows + cardRows + paramRows +
|
|
136
|
+
const core = heroBlockRows + cardRows + paramRows + cornersBlockRows;
|
|
118
137
|
// 每一档的总行数。顺序即从最全的往下掉:先试最全的,放不下就往下掉。
|
|
119
138
|
// full 带 4 个变体(呼吸×参数留白的紧/松组合)、no-tip 带 3 个:
|
|
120
139
|
// 呼吸在(默认 2/2)→ 撤呼吸(紧档 1/1)→ 撤参数留白,全部都矮于撤 Tips。
|
|
@@ -154,7 +173,7 @@ export function resolveLaunchpadLayout(columns, rows, options) {
|
|
|
154
173
|
const heroGapRows = keepBreath ? HERO_TO_CARD_GAP : HERO_TO_CARD_GAP_TIGHT;
|
|
155
174
|
const tipGapRows = keepBreath ? TIP_BLOCK_ROWS - 1 : TIP_BLOCK_ROWS_TIGHT - 1;
|
|
156
175
|
const total = (showTip ? 1 + tipGapRows : 0) + hintsGapRows + (showHints ? HINTS_ROWS : 0) + heroBlockFinal
|
|
157
|
-
+ heroGapRows + cardRows + paramRows +
|
|
176
|
+
+ heroGapRows + cardRows + paramRows + cornersBlockRows;
|
|
158
177
|
return {
|
|
159
178
|
stage,
|
|
160
179
|
// dropArt 只撤立绘——`heroRowsFinal`/`totalRows` 都按「撤立绘、留大字」算,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
/** The sending team member's name. */
|
|
4
|
+
sender: string;
|
|
5
|
+
text: string;
|
|
6
|
+
/** Adds the top margin between turns. */
|
|
7
|
+
marginTopOnTurn: boolean;
|
|
8
|
+
/** Message-selection mode highlight. */
|
|
9
|
+
isSelected?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* An Agent Teams peer message delivered to this session: a `✉ <sender>` line
|
|
13
|
+
* in the agent tint, then the body in plain text with a hanging indent — it
|
|
14
|
+
* reads apart from the human's bold `❯` prompt it shares a log role with.
|
|
15
|
+
* The body wraps in its own flex column, so it fits whatever column hosts it
|
|
16
|
+
* (the main list, a child scene's padded page, a split with the workbench).
|
|
17
|
+
*/
|
|
18
|
+
export declare function TeamMessageBubble({ sender, text, marginTopOnTurn, isSelected }: Props): React.ReactNode;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=TeamMessageBubble.d.ts.map
|