feat: claude subagents transform

This commit is contained in:
LaZzyMan 2026-01-15 20:00:09 +08:00
parent 4c7605d900
commit f00f76456c
14 changed files with 891 additions and 455 deletions

View file

@ -58,7 +58,11 @@ export const ActionSelectionStep = ({
},
];
const actions = selectedAgent?.isBuiltin
// Extension-level agents are also read-only (like builtin)
const isReadOnly =
selectedAgent?.isBuiltin || selectedAgent?.level === 'extension';
const actions = isReadOnly
? allActions.filter(
(action) => action.value === 'view' || action.value === 'back',
)

View file

@ -12,10 +12,11 @@ import { type SubagentConfig } from '@qwen-code/qwen-code-core';
import { t } from '../../../../i18n/index.js';
interface NavigationState {
currentBlock: 'project' | 'user' | 'builtin';
currentBlock: 'project' | 'user' | 'builtin' | 'extension';
projectIndex: number;
userIndex: number;
builtinIndex: number;
extensionIndex: number;
}
interface AgentSelectionStepProps {
@ -32,6 +33,7 @@ export const AgentSelectionStep = ({
projectIndex: 0,
userIndex: 0,
builtinIndex: 0,
extensionIndex: 0,
});
// Group agents by level
@ -47,6 +49,10 @@ export const AgentSelectionStep = ({
() => availableAgents.filter((agent) => agent.level === 'builtin'),
[availableAgents],
);
const extensionAgents = useMemo(
() => availableAgents.filter((agent) => agent.level === 'extension'),
[availableAgents],
);
const projectNames = useMemo(
() => new Set(projectAgents.map((agent) => agent.name)),
[projectAgents],
@ -60,8 +66,10 @@ export const AgentSelectionStep = ({
setNavigation((prev) => ({ ...prev, currentBlock: 'user' }));
} else if (builtinAgents.length > 0) {
setNavigation((prev) => ({ ...prev, currentBlock: 'builtin' }));
} else if (extensionAgents.length > 0) {
setNavigation((prev) => ({ ...prev, currentBlock: 'extension' }));
}
}, [projectAgents, userAgents, builtinAgents]);
}, [projectAgents, userAgents, builtinAgents, extensionAgents]);
// Custom keyboard navigation
useKeypress(
@ -87,6 +95,13 @@ export const AgentSelectionStep = ({
currentBlock: 'user',
userIndex: userAgents.length - 1,
};
} else if (extensionAgents.length > 0) {
// Move to last item in extension block
return {
...prev,
currentBlock: 'extension',
extensionIndex: extensionAgents.length - 1,
};
} else {
// Wrap to last item in project block
return { ...prev, projectIndex: projectAgents.length - 1 };
@ -108,11 +123,18 @@ export const AgentSelectionStep = ({
currentBlock: 'builtin',
builtinIndex: builtinAgents.length - 1,
};
} else if (extensionAgents.length > 0) {
// Move to last item in extension block
return {
...prev,
currentBlock: 'extension',
extensionIndex: extensionAgents.length - 1,
};
} else {
// Wrap to last item in user block
return { ...prev, userIndex: userAgents.length - 1 };
}
} else {
} else if (prev.currentBlock === 'builtin') {
// builtin block
if (prev.builtinIndex > 0) {
return { ...prev, builtinIndex: prev.builtinIndex - 1 };
@ -130,10 +152,46 @@ export const AgentSelectionStep = ({
currentBlock: 'project',
projectIndex: projectAgents.length - 1,
};
} else if (extensionAgents.length > 0) {
// Move to last item in extension block
return {
...prev,
currentBlock: 'extension',
extensionIndex: extensionAgents.length - 1,
};
} else {
// Wrap to last item in builtin block
return { ...prev, builtinIndex: builtinAgents.length - 1 };
}
} else {
// extension block
if (prev.extensionIndex > 0) {
return { ...prev, extensionIndex: prev.extensionIndex - 1 };
} else if (userAgents.length > 0) {
// Move to last item in user block
return {
...prev,
currentBlock: 'user',
userIndex: userAgents.length - 1,
};
} else if (projectAgents.length > 0) {
// Move to last item in project block
return {
...prev,
currentBlock: 'project',
projectIndex: projectAgents.length - 1,
};
} else if (builtinAgents.length > 0) {
// Move to last item in builtin block
return {
...prev,
currentBlock: 'builtin',
builtinIndex: builtinAgents.length - 1,
};
} else {
// Wrap to last item in extension block
return { ...prev, extensionIndex: extensionAgents.length - 1 };
}
}
});
} else if (name === 'down' || name === 'j') {
@ -147,6 +205,9 @@ export const AgentSelectionStep = ({
} else if (builtinAgents.length > 0) {
// Move to first item in builtin block
return { ...prev, currentBlock: 'builtin', builtinIndex: 0 };
} else if (extensionAgents.length > 0) {
// Move to first item in extension block
return { ...prev, currentBlock: 'extension', extensionIndex: 0 };
} else {
// Wrap to first item in project block
return { ...prev, projectIndex: 0 };
@ -157,6 +218,9 @@ export const AgentSelectionStep = ({
} else if (builtinAgents.length > 0) {
// Move to first item in builtin block
return { ...prev, currentBlock: 'builtin', builtinIndex: 0 };
} else if (extensionAgents.length > 0) {
// Move to first item in extension block
return { ...prev, currentBlock: 'extension', extensionIndex: 0 };
} else if (projectAgents.length > 0) {
// Move to first item in project block
return { ...prev, currentBlock: 'project', projectIndex: 0 };
@ -164,10 +228,13 @@ export const AgentSelectionStep = ({
// Wrap to first item in user block
return { ...prev, userIndex: 0 };
}
} else {
} else if (prev.currentBlock === 'builtin') {
// builtin block
if (prev.builtinIndex < builtinAgents.length - 1) {
return { ...prev, builtinIndex: prev.builtinIndex + 1 };
} else if (extensionAgents.length > 0) {
// Move to first item in extension block
return { ...prev, currentBlock: 'extension', extensionIndex: 0 };
} else if (projectAgents.length > 0) {
// Move to first item in project block
return { ...prev, currentBlock: 'project', projectIndex: 0 };
@ -178,6 +245,23 @@ export const AgentSelectionStep = ({
// Wrap to first item in builtin block
return { ...prev, builtinIndex: 0 };
}
} else {
// extension block
if (prev.extensionIndex < extensionAgents.length - 1) {
return { ...prev, extensionIndex: prev.extensionIndex + 1 };
} else if (projectAgents.length > 0) {
// Move to first item in project block
return { ...prev, currentBlock: 'project', projectIndex: 0 };
} else if (userAgents.length > 0) {
// Move to first item in user block
return { ...prev, currentBlock: 'user', userIndex: 0 };
} else if (builtinAgents.length > 0) {
// Move to first item in builtin block
return { ...prev, currentBlock: 'builtin', builtinIndex: 0 };
} else {
// Wrap to first item in extension block
return { ...prev, extensionIndex: 0 };
}
}
});
} else if (name === 'return' || name === 'space') {
@ -188,11 +272,17 @@ export const AgentSelectionStep = ({
} else if (navigation.currentBlock === 'user') {
// User agents come after project agents in the availableAgents array
globalIndex = projectAgents.length + navigation.userIndex;
} else {
// builtin block
} else if (navigation.currentBlock === 'builtin') {
// Builtin agents come after project and user agents in the availableAgents array
globalIndex =
projectAgents.length + userAgents.length + navigation.builtinIndex;
} else {
// Extension agents come after project, user, and builtin agents
globalIndex =
projectAgents.length +
userAgents.length +
builtinAgents.length +
navigation.extensionIndex;
}
if (globalIndex >= 0 && globalIndex < availableAgents.length) {
@ -258,7 +348,8 @@ export const AgentSelectionStep = ({
const enabledAgentsCount =
projectAgents.length +
userAgents.filter((agent) => !projectNames.has(agent.name)).length +
builtinAgents.length;
builtinAgents.length +
extensionAgents.length;
return (
<Box flexDirection="column">
@ -305,7 +396,10 @@ export const AgentSelectionStep = ({
{/* Built-in Agents */}
{builtinAgents.length > 0 && (
<Box flexDirection="column">
<Box
flexDirection="column"
marginBottom={extensionAgents.length > 0 ? 1 : 0}
>
<Text color={theme.text.primary} bold>
{t('Built-in Agents')}
</Text>
@ -320,10 +414,28 @@ export const AgentSelectionStep = ({
</Box>
)}
{/* Extension Agents */}
{extensionAgents.length > 0 && (
<Box flexDirection="column">
<Text color={theme.text.primary} bold>
{t('Extension Agents')}
</Text>
<Box marginTop={1} flexDirection="column">
{extensionAgents.map((agent, index) => {
const isSelected =
navigation.currentBlock === 'extension' &&
navigation.extensionIndex === index;
return renderAgentItem(agent, index, isSelected);
})}
</Box>
</Box>
)}
{/* Agent count summary */}
{(projectAgents.length > 0 ||
userAgents.length > 0 ||
builtinAgents.length > 0) && (
builtinAgents.length > 0 ||
extensionAgents.length > 0) && (
<Box marginTop={1}>
<Text color={theme.text.secondary}>
{t('Using: {{count}} agents', {

View file

@ -95,7 +95,11 @@ export function AgentsManagerDialog({
try {
const subagentManager = config.getSubagentManager();
await subagentManager.deleteSubagent(agent.name, agent.level);
await subagentManager.deleteSubagent(
agent.name,
agent.level,
agent.extensionName,
);
// Reload agents to get updated state
await loadAgents();