feat: subagent feature wip

This commit is contained in:
tanzhenxin
2025-09-10 14:35:08 +08:00
parent 6b09aee32b
commit 4839cb9320
13 changed files with 48 additions and 33 deletions

View File

@@ -122,9 +122,9 @@ Slash commands provide meta-level control over the CLI itself.
- **`create`**: - **`create`**:
- **Description:** Launch an interactive wizard to create a new subagent. The wizard guides you through location selection, AI-powered prompt generation, tool selection, and visual customization. - **Description:** Launch an interactive wizard to create a new subagent. The wizard guides you through location selection, AI-powered prompt generation, tool selection, and visual customization.
- **Usage:** `/agents create` - **Usage:** `/agents create`
- **`list`**: - **`manage`**:
- **Description:** Open an interactive management dialog to view, edit, and delete existing subagents. Shows both project-level and user-level agents. - **Description:** Open an interactive management dialog to view, edit, and delete existing subagents. Shows both project-level and user-level agents.
- **Usage:** `/agents list` - **Usage:** `/agents manage`
- **Storage Locations:** - **Storage Locations:**
- **Project-level:** `.qwen/agents/` (shared with team, takes precedence) - **Project-level:** `.qwen/agents/` (shared with team, takes precedence)
- **User-level:** `~/.qwen/agents/` (personal agents, available across projects) - **User-level:** `~/.qwen/agents/` (personal agents, available across projects)

View File

@@ -39,10 +39,10 @@ Subagents are independent AI assistants that:
Follow the guided wizard to create a specialized agent. Follow the guided wizard to create a specialized agent.
2. **List existing agents**: 2. **Manage existing agents**:
``` ```
/agents list /agents manage
``` ```
View and manage your configured subagents. View and manage your configured subagents.
@@ -77,14 +77,14 @@ Creates a new subagent through a guided step wizard.
/agents create /agents create
``` ```
#### `/agents list` #### `/agents manage`
Opens an interactive management dialog for viewing and managing existing subagents. Opens an interactive management dialog for viewing and managing existing subagents.
**Usage:** **Usage:**
``` ```
/agents list /agents manage
``` ```
### Storage Locations ### Storage Locations

View File

@@ -12,7 +12,7 @@ export const agentsCommand: SlashCommand = {
kind: CommandKind.BUILT_IN, kind: CommandKind.BUILT_IN,
subCommands: [ subCommands: [
{ {
name: 'list', name: 'manage',
description: 'Manage existing subagents (view, edit, delete).', description: 'Manage existing subagents (view, edit, delete).',
kind: CommandKind.BUILT_IN, kind: CommandKind.BUILT_IN,
action: (): OpenDialogActionReturn => ({ action: (): OpenDialogActionReturn => ({

View File

@@ -100,9 +100,9 @@ export function CreationSummary({
state.location, state.location,
]); ]);
const toolsDisplay = Array.isArray(state.selectedTools) // If no tools explicitly selected, it means "all tools" for this agent
? state.selectedTools.join(', ') const toolsDisplay =
: '*'; state.selectedTools.length === 0 ? '*' : state.selectedTools.join(', ');
// Common method to save subagent configuration // Common method to save subagent configuration
const saveSubagent = useCallback(async (): Promise<SubagentManager> => { const saveSubagent = useCallback(async (): Promise<SubagentManager> => {
@@ -225,12 +225,14 @@ export function CreationSummary({
<Box flexDirection="column" gap={1}> <Box flexDirection="column" gap={1}>
<Box flexDirection="column"> <Box flexDirection="column">
<Box> <Box>
<Text bold>Name: </Text> <Text color={theme.text.primary}>Name: </Text>
<Text>{state.generatedName}</Text> <Text color={getColorForDisplay(state.color)}>
{state.generatedName}
</Text>
</Box> </Box>
<Box> <Box>
<Text bold>Location: </Text> <Text color={theme.text.primary}>Location: </Text>
<Text> <Text>
{state.location === 'project' {state.location === 'project'
? 'Project Level (.qwen/agents/)' ? 'Project Level (.qwen/agents/)'
@@ -239,21 +241,19 @@ export function CreationSummary({
</Box> </Box>
<Box> <Box>
<Text bold>Tools: </Text> <Text color={theme.text.primary}>Tools: </Text>
<Text>{toolsDisplay}</Text> <Text>{toolsDisplay}</Text>
</Box> </Box>
{shouldShowColor(state.color) && ( {shouldShowColor(state.color) && (
<Box> <Box>
<Text bold>Color: </Text> <Text color={theme.text.primary}>Color: </Text>
<Text <Text color={getColorForDisplay(state.color)}>{state.color}</Text>
color={getColorForDisplay(state.color)}
>{` ${state.generatedName} `}</Text>
</Box> </Box>
)} )}
<Box marginTop={1}> <Box marginTop={1}>
<Text bold>Description:</Text> <Text color={theme.text.primary}>Description:</Text>
</Box> </Box>
<Box padding={1} paddingBottom={0}> <Box padding={1} paddingBottom={0}>
<Text wrap="wrap"> <Text wrap="wrap">
@@ -262,7 +262,7 @@ export function CreationSummary({
</Box> </Box>
<Box marginTop={1}> <Box marginTop={1}>
<Text bold>System Prompt:</Text> <Text color={theme.text.primary}>System Prompt:</Text>
</Box> </Box>
<Box padding={1} paddingBottom={0}> <Box padding={1} paddingBottom={0}>
<Text wrap="wrap"> <Text wrap="wrap">

View File

@@ -6,6 +6,7 @@
import { useState, useCallback, useRef } from 'react'; import { useState, useCallback, useRef } from 'react';
import { Box, Text } from 'ink'; import { Box, Text } from 'ink';
import Spinner from 'ink-spinner';
import { WizardStepProps, WizardAction } from '../types.js'; import { WizardStepProps, WizardAction } from '../types.js';
import { sanitizeInput } from '../utils.js'; import { sanitizeInput } from '../utils.js';
import { Config, subagentGenerator } from '@qwen-code/qwen-code-core'; import { Config, subagentGenerator } from '@qwen-code/qwen-code-core';
@@ -239,8 +240,11 @@ export function DescriptionInput({
{state.isGenerating ? ( {state.isGenerating ? (
<Box> <Box>
<Box marginRight={1}>
<Spinner />
</Box>
<Text color={theme.text.accent}> <Text color={theme.text.accent}>
Generating subagent configuration... Generating subagent configuration...
</Text> </Text>
</Box> </Box>
) : ( ) : (

View File

@@ -30,33 +30,31 @@ export const AgentViewerStep = ({ selectedAgent }: AgentViewerStepProps) => {
<Box flexDirection="column" gap={1}> <Box flexDirection="column" gap={1}>
<Box flexDirection="column"> <Box flexDirection="column">
<Box> <Box>
<Text bold>File Path: </Text> <Text color={theme.text.primary}>File Path: </Text>
<Text>{agent.filePath}</Text> <Text>{agent.filePath}</Text>
</Box> </Box>
<Box> <Box>
<Text bold>Tools: </Text> <Text color={theme.text.primary}>Tools: </Text>
<Text>{toolsDisplay}</Text> <Text>{toolsDisplay}</Text>
</Box> </Box>
{shouldShowColor(agent.color) && ( {shouldShowColor(agent.color) && (
<Box> <Box>
<Text bold>Color: </Text> <Text color={theme.text.primary}>Color: </Text>
<Text <Text color={getColorForDisplay(agent.color)}>{agent.color}</Text>
color={getColorForDisplay(agent.color)}
>{` ${agent.name} `}</Text>
</Box> </Box>
)} )}
<Box marginTop={1}> <Box marginTop={1}>
<Text bold>Description:</Text> <Text color={theme.text.primary}>Description:</Text>
</Box> </Box>
<Box padding={1} paddingBottom={0}> <Box padding={1} paddingBottom={0}>
<Text wrap="wrap">{agent.description}</Text> <Text wrap="wrap">{agent.description}</Text>
</Box> </Box>
<Box marginTop={1}> <Box marginTop={1}>
<Text bold>System Prompt:</Text> <Text color={theme.text.primary}>System Prompt:</Text>
</Box> </Box>
<Box padding={1} paddingBottom={0}> <Box padding={1} paddingBottom={0}>
<Text wrap="wrap">{agent.systemPrompt}</Text> <Text wrap="wrap">{agent.systemPrompt}</Text>

View File

@@ -16,6 +16,7 @@ import { ColorSelector } from '../create/ColorSelector.js';
import { MANAGEMENT_STEPS } from '../types.js'; import { MANAGEMENT_STEPS } from '../types.js';
import { Colors } from '../../../colors.js'; import { Colors } from '../../../colors.js';
import { theme } from '../../../semantic-colors.js'; import { theme } from '../../../semantic-colors.js';
import { getColorForDisplay, shouldShowColor } from '../utils.js';
import { Config, SubagentConfig } from '@qwen-code/qwen-code-core'; import { Config, SubagentConfig } from '@qwen-code/qwen-code-core';
interface AgentsManagerDialogProps { interface AgentsManagerDialogProps {
@@ -166,9 +167,19 @@ export function AgentsManagerDialog({
} }
}; };
// Use agent color for the Agent Viewer header
const headerColor =
currentStep === MANAGEMENT_STEPS.AGENT_VIEWER &&
selectedAgent &&
shouldShowColor(selectedAgent.color)
? getColorForDisplay(selectedAgent.color)
: undefined;
return ( return (
<Box> <Box>
<Text bold>{getStepHeaderText()}</Text> <Text bold color={headerColor}>
{getStepHeaderText()}
</Text>
</Box> </Box>
); );
}, [getCurrentStep, selectedAgent]); }, [getCurrentStep, selectedAgent]);

View File

@@ -171,7 +171,10 @@ const TaskPromptSection: React.FC<{
<Box flexDirection="row"> <Box flexDirection="row">
<Text color={theme.text.primary}>Task Detail: </Text> <Text color={theme.text.primary}>Task Detail: </Text>
{shouldTruncate && displayMode === 'default' && ( {shouldTruncate && displayMode === 'default' && (
<Text color={Colors.Gray}> Showing the first 10 lines.</Text> <Text color={Colors.Gray}>
{' '}
Showing the first {MAX_TASK_PROMPT_LINES} lines.
</Text>
)} )}
</Box> </Box>
<Box paddingLeft={1}> <Box paddingLeft={1}>

View File

@@ -16,8 +16,7 @@
* - Runtime conversion functions integrated into the manager * - Runtime conversion functions integrated into the manager
* - Manager class for CRUD operations on subagent files * - Manager class for CRUD operations on subagent files
* *
* The implementation follows the Markdown + YAML frontmatter format specified * The implementation follows the Markdown + YAML frontmatter format , with storage at both project and user levels.
* in the Claude Code product manual, with storage at both project and user levels.
*/ */
// Core types and interfaces // Core types and interfaces