| import * as React from 'react' |
| import { useAppState, useAppStateStore } from '../../state/AppState.js' |
| import { |
| getActiveAgentForInput, |
| getViewedTeammateTask, |
| } from '../../state/selectors.js' |
| import { |
| AGENT_COLOR_TO_THEME_COLOR, |
| AGENT_COLORS, |
| type AgentColorName, |
| getAgentColor, |
| } from '../../tools/AgentTool/agentColorManager.js' |
| import { getStandaloneAgentName } from '../../utils/standaloneAgent.js' |
| import { isInsideTmux } from '../../utils/swarm/backends/detection.js' |
| import { |
| getCachedDetectionResult, |
| isInProcessEnabled, |
| } from '../../utils/swarm/backends/registry.js' |
| import { getSwarmSocketName } from '../../utils/swarm/constants.js' |
| import { |
| getAgentName, |
| getTeammateColor, |
| getTeamName, |
| isTeammate, |
| } from '../../utils/teammate.js' |
| import { isInProcessTeammate } from '../../utils/teammateContext.js' |
| import type { Theme } from '../../utils/theme.js' |
|
|
| type SwarmBannerInfo = { |
| text: string |
| bgColor: keyof Theme |
| } | null |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export function useSwarmBanner(): SwarmBannerInfo { |
| const teamContext = useAppState(s => s.teamContext) |
| const standaloneAgentContext = useAppState(s => s.standaloneAgentContext) |
| const agent = useAppState(s => s.agent) |
| |
| |
| useAppState(s => s.viewingAgentTaskId) |
| const store = useAppStateStore() |
| const [insideTmux, setInsideTmux] = React.useState<boolean | null>(null) |
|
|
| React.useEffect(() => { |
| void isInsideTmux().then(setInsideTmux) |
| }, []) |
|
|
| const state = store.getState() |
|
|
| |
| |
| if (isTeammate() && !isInProcessTeammate()) { |
| const agentName = getAgentName() |
| if (agentName && getTeamName()) { |
| return { |
| text: `@${agentName}`, |
| bgColor: toThemeColor( |
| teamContext?.selfAgentColor ?? getTeammateColor(), |
| ), |
| } |
| } |
| } |
|
|
| |
| |
| const hasTeammates = |
| teamContext?.teamName && |
| teamContext.teammates && |
| Object.keys(teamContext.teammates).length > 0 |
| if (hasTeammates) { |
| const viewedTeammate = getViewedTeammateTask(state) |
| const viewedColor = toThemeColor(viewedTeammate?.identity.color) |
| const inProcessMode = isInProcessEnabled() |
| const nativePanes = getCachedDetectionResult()?.isNative ?? false |
|
|
| if (insideTmux === false && !inProcessMode && !nativePanes) { |
| return { |
| text: `View teammates: \`tmux -L ${getSwarmSocketName()} a\``, |
| bgColor: viewedColor, |
| } |
| } |
| if ( |
| (insideTmux === true || inProcessMode || nativePanes) && |
| viewedTeammate |
| ) { |
| return { |
| text: `@${viewedTeammate.identity.agentName}`, |
| bgColor: viewedColor, |
| } |
| } |
| |
| |
| } |
|
|
| |
| |
| |
| const active = getActiveAgentForInput(state) |
| if (active.type === 'named_agent') { |
| const task = active.task |
| let name: string | undefined |
| for (const [n, id] of state.agentNameRegistry) { |
| if (id === task.id) { |
| name = n |
| break |
| } |
| } |
| return { |
| text: name ? `@${name}` : task.description, |
| bgColor: getAgentColor(task.agentType) ?? 'cyan_FOR_SUBAGENTS_ONLY', |
| } |
| } |
|
|
| |
| const standaloneName = getStandaloneAgentName(state) |
| const standaloneColor = standaloneAgentContext?.color |
| if (standaloneName || standaloneColor) { |
| return { |
| text: standaloneName ?? '', |
| bgColor: toThemeColor(standaloneColor), |
| } |
| } |
|
|
| |
| if (agent) { |
| const agentDef = state.agentDefinitions.activeAgents.find( |
| a => a.agentType === agent, |
| ) |
| return { |
| text: agent, |
| bgColor: toThemeColor(agentDef?.color, 'promptBorder'), |
| } |
| } |
|
|
| return null |
| } |
|
|
| function toThemeColor( |
| colorName: string | undefined, |
| fallback: keyof Theme = 'cyan_FOR_SUBAGENTS_ONLY', |
| ): keyof Theme { |
| return colorName && AGENT_COLORS.includes(colorName as AgentColorName) |
| ? AGENT_COLOR_TO_THEME_COLOR[colorName as AgentColorName] |
| : fallback |
| } |
|
|