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`**:
- **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`
- **`list`**:
- **`manage`**:
- **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:**
- **Project-level:** `.qwen/agents/` (shared with team, takes precedence)
- **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.
2. **List existing agents**:
2. **Manage existing agents**:
```
/agents list
/agents manage
```
View and manage your configured subagents.
@@ -77,14 +77,14 @@ Creates a new subagent through a guided step wizard.
/agents create
```
#### `/agents list`
#### `/agents manage`
Opens an interactive management dialog for viewing and managing existing subagents.
**Usage:**
```
/agents list
/agents manage
```
### Storage Locations

View File

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

View File

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

View File

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

View File

@@ -30,33 +30,31 @@ export const AgentViewerStep = ({ selectedAgent }: AgentViewerStepProps) => {
<Box flexDirection="column" gap={1}>
<Box flexDirection="column">
<Box>
<Text bold>File Path: </Text>
<Text color={theme.text.primary}>File Path: </Text>
<Text>{agent.filePath}</Text>
</Box>
<Box>
<Text bold>Tools: </Text>
<Text color={theme.text.primary}>Tools: </Text>
<Text>{toolsDisplay}</Text>
</Box>
{shouldShowColor(agent.color) && (
<Box>
<Text bold>Color: </Text>
<Text
color={getColorForDisplay(agent.color)}
>{` ${agent.name} `}</Text>
<Text color={theme.text.primary}>Color: </Text>
<Text color={getColorForDisplay(agent.color)}>{agent.color}</Text>
</Box>
)}
<Box marginTop={1}>
<Text bold>Description:</Text>
<Text color={theme.text.primary}>Description:</Text>
</Box>
<Box padding={1} paddingBottom={0}>
<Text wrap="wrap">{agent.description}</Text>
</Box>
<Box marginTop={1}>
<Text bold>System Prompt:</Text>
<Text color={theme.text.primary}>System Prompt:</Text>
</Box>
<Box padding={1} paddingBottom={0}>
<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 { Colors } from '../../../colors.js';
import { theme } from '../../../semantic-colors.js';
import { getColorForDisplay, shouldShowColor } from '../utils.js';
import { Config, SubagentConfig } from '@qwen-code/qwen-code-core';
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 (
<Box>
<Text bold>{getStepHeaderText()}</Text>
<Text bold color={headerColor}>
{getStepHeaderText()}
</Text>
</Box>
);
}, [getCurrentStep, selectedAgent]);

View File

@@ -171,7 +171,10 @@ const TaskPromptSection: React.FC<{
<Box flexDirection="row">
<Text color={theme.text.primary}>Task Detail: </Text>
{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 paddingLeft={1}>

View File

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