Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

130 lines
4.2 KiB
TypeScript

import { useMemo } from "react";
import { cn } from "../../../app/renderer/lib/utils";
import styles from "../AgentGUINode.styles";
import type { AgentGUIAgentTarget } from "../../../types";
interface Input {
layoutMode: "dock" | "embedded" | "hero";
provider: string;
agentTargets: readonly AgentGUIAgentTarget[];
handoffAgentTargets?: readonly AgentGUIAgentTarget[];
selectedAgentTarget: AgentGUIAgentTarget | null;
providerSelectReadonly: boolean;
composerControlsHardDisabled: boolean;
isSelectedProjectMissing: boolean;
disabled: boolean;
onHandoffConversation?: (target: AgentGUIAgentTarget) => void;
handoffLabel?: string;
handoffMenuLabel?: string;
defaultHandoffLabel: string;
defaultHandoffMenuLabel: string;
}
export function useComposerProviderTargets(input: Input) {
const {
layoutMode,
provider,
agentTargets,
handoffAgentTargets,
selectedAgentTarget,
providerSelectReadonly,
composerControlsHardDisabled,
isSelectedProjectMissing,
disabled,
onHandoffConversation,
handoffLabel,
handoffMenuLabel
} = input;
const labels = {
handoffConversation: input.defaultHandoffLabel,
handoffConversationMenu: input.defaultHandoffMenuLabel
};
const isHeroLayout = layoutMode === "hero";
const composerClassName = isHeroLayout
? styles.composerHero
: styles.composer;
const providerSwitchTargets = useMemo(
() => agentTargets.filter(Boolean),
[agentTargets]
);
const selectedAgentTargetId =
selectedAgentTarget?.targetId ?? `local:${provider}`;
const selectedProviderSwitchTarget =
providerSwitchTargets.find(
(target) => target.targetId === selectedAgentTargetId
) ??
providerSwitchTargets.find((target) => target.provider === provider) ??
selectedAgentTarget;
const providerMenuTargets =
selectedProviderSwitchTarget &&
!providerSwitchTargets.some(
(target) => target.targetId === selectedProviderSwitchTarget.targetId
)
? [selectedProviderSwitchTarget, ...providerSwitchTargets]
: providerSwitchTargets;
const enabledHandoffProviderTargets = useMemo(
() =>
(handoffAgentTargets ?? providerMenuTargets).filter(
(target) => target.disabled !== true
),
[handoffAgentTargets, providerMenuTargets]
);
const handoffMenuTargets = selectedProviderSwitchTarget
? enabledHandoffProviderTargets.filter((target) => {
if (target.targetId === selectedProviderSwitchTarget.targetId) {
return false;
}
const selectedAgentTargetId =
selectedProviderSwitchTarget.agentTargetId ??
selectedProviderSwitchTarget.targetId;
const targetAgentTargetId = target.agentTargetId ?? target.targetId;
return targetAgentTargetId !== selectedAgentTargetId;
})
: enabledHandoffProviderTargets;
const selectedProviderLabel =
selectedProviderSwitchTarget?.label ??
selectedAgentTarget?.label ??
provider;
const effectiveHandoffLabel = handoffLabel || labels.handoffConversation;
const effectiveHandoffMenuLabel =
handoffMenuLabel || labels.handoffConversationMenu;
const inputShellClassName = cn(
styles.composerInputShell,
isHeroLayout && styles.composerInputShellHero
);
const inputDisabled = isSelectedProjectMissing || disabled;
const providerSelectDisabled =
providerSelectReadonly || composerControlsHardDisabled || inputDisabled;
const handoffDisabled = resolveComposerHandoffDisabled({
hasHandoffConversation: onHandoffConversation !== undefined
});
const showProviderSelect =
!isHeroLayout &&
selectedProviderSwitchTarget !== null &&
providerMenuTargets.length > 0;
const showHandoffSelect = showProviderSelect && providerSelectReadonly;
return {
composerClassName,
effectiveHandoffLabel,
effectiveHandoffMenuLabel,
handoffDisabled,
handoffMenuTargets,
inputDisabled,
inputShellClassName,
isHeroLayout,
providerMenuTargets,
providerSelectDisabled,
selectedProviderLabel,
selectedProviderSwitchTarget,
showHandoffSelect,
showProviderSelect
};
}
export function resolveComposerHandoffDisabled(input: {
hasHandoffConversation: boolean;
}): boolean {
return !input.hasHandoffConversation;
}