mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
feat: subagent feature wip
This commit is contained in:
@@ -258,10 +258,8 @@ describe('TaskTool', () => {
|
||||
beforeEach(() => {
|
||||
mockSubagentScope = {
|
||||
runNonInteractive: vi.fn().mockResolvedValue(undefined),
|
||||
output: {
|
||||
result: 'Task completed successfully',
|
||||
terminate_reason: SubagentTerminateMode.GOAL,
|
||||
},
|
||||
result: 'Task completed successfully',
|
||||
terminateMode: SubagentTerminateMode.GOAL,
|
||||
getFinalText: vi.fn().mockReturnValue('Task completed successfully'),
|
||||
formatCompactResult: vi
|
||||
.fn()
|
||||
@@ -305,6 +303,7 @@ describe('TaskTool', () => {
|
||||
successfulToolCalls: 3,
|
||||
failedToolCalls: 0,
|
||||
}),
|
||||
getTerminateMode: vi.fn().mockReturnValue(SubagentTerminateMode.GOAL),
|
||||
} as unknown as SubAgentScope;
|
||||
|
||||
mockContextState = {
|
||||
@@ -375,25 +374,6 @@ describe('TaskTool', () => {
|
||||
expect(display.subagentName).toBe('non-existent');
|
||||
});
|
||||
|
||||
it('should handle subagent execution failure', async () => {
|
||||
mockSubagentScope.output.terminate_reason = SubagentTerminateMode.ERROR;
|
||||
|
||||
const params: TaskParams = {
|
||||
description: 'Search files',
|
||||
prompt: 'Find all TypeScript files',
|
||||
subagent_type: 'file-search',
|
||||
};
|
||||
|
||||
const invocation = (
|
||||
taskTool as TaskToolWithProtectedMethods
|
||||
).createInvocation(params);
|
||||
const result = await invocation.execute();
|
||||
|
||||
const display = result.returnDisplay as TaskResultDisplay;
|
||||
expect(display.status).toBe('failed');
|
||||
expect(display.terminateReason).toBe('ERROR');
|
||||
});
|
||||
|
||||
it('should handle execution errors gracefully', async () => {
|
||||
vi.mocked(mockSubagentManager.createSubagentScope).mockRejectedValue(
|
||||
new Error('Creation failed'),
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from './tools.js';
|
||||
import { Config } from '../config/config.js';
|
||||
import { SubagentManager } from '../subagents/subagent-manager.js';
|
||||
import { SubagentConfig } from '../subagents/types.js';
|
||||
import { SubagentConfig, SubagentTerminateMode } from '../subagents/types.js';
|
||||
import { ContextState } from '../subagents/subagent.js';
|
||||
import {
|
||||
SubAgentEventEmitter,
|
||||
@@ -409,21 +409,6 @@ class TaskToolInvocation extends BaseToolInvocation<TaskParams, ToolResult> {
|
||||
// Set up event listeners for real-time updates
|
||||
this.setupEventListeners(updateOutput);
|
||||
|
||||
if (signal) {
|
||||
signal.addEventListener('abort', () => {
|
||||
if (this.currentDisplay) {
|
||||
this.updateDisplay(
|
||||
{
|
||||
status: 'failed',
|
||||
terminateReason: 'CANCELLED',
|
||||
result: 'Task was cancelled by user',
|
||||
},
|
||||
updateOutput,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Send initial display
|
||||
if (updateOutput) {
|
||||
updateOutput(this.currentDisplay);
|
||||
@@ -474,20 +459,31 @@ class TaskToolInvocation extends BaseToolInvocation<TaskParams, ToolResult> {
|
||||
|
||||
// Get the results
|
||||
const finalText = subagentScope.getFinalText();
|
||||
const terminateReason = subagentScope.output.terminate_reason;
|
||||
const success = terminateReason === 'GOAL';
|
||||
const terminateReason = subagentScope.getTerminateMode();
|
||||
const success = terminateReason === SubagentTerminateMode.GOAL;
|
||||
const executionSummary = subagentScope.getExecutionSummary();
|
||||
|
||||
// Update the final display state
|
||||
this.updateDisplay(
|
||||
{
|
||||
status: success ? 'completed' : 'failed',
|
||||
terminateReason,
|
||||
result: finalText,
|
||||
executionSummary,
|
||||
},
|
||||
updateOutput,
|
||||
);
|
||||
if (signal?.aborted) {
|
||||
this.updateDisplay(
|
||||
{
|
||||
status: 'cancelled',
|
||||
terminateReason: 'CANCELLED',
|
||||
result: finalText || 'Task was cancelled by user',
|
||||
executionSummary,
|
||||
},
|
||||
updateOutput,
|
||||
);
|
||||
} else {
|
||||
this.updateDisplay(
|
||||
{
|
||||
status: success ? 'completed' : 'failed',
|
||||
terminateReason,
|
||||
result: finalText,
|
||||
executionSummary,
|
||||
},
|
||||
updateOutput,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
llmContent: [{ text: finalText }],
|
||||
@@ -500,7 +496,7 @@ class TaskToolInvocation extends BaseToolInvocation<TaskParams, ToolResult> {
|
||||
|
||||
const errorDisplay: TaskResultDisplay = {
|
||||
...this.currentDisplay!,
|
||||
status: 'failed' as const,
|
||||
status: 'failed',
|
||||
terminateReason: 'ERROR',
|
||||
result: `Failed to run subagent: ${errorMessage}`,
|
||||
};
|
||||
|
||||
@@ -428,7 +428,7 @@ export interface TaskResultDisplay {
|
||||
subagentColor?: string;
|
||||
taskDescription: string;
|
||||
taskPrompt: string;
|
||||
status: 'running' | 'completed' | 'failed';
|
||||
status: 'running' | 'completed' | 'failed' | 'cancelled';
|
||||
terminateReason?: string;
|
||||
result?: string;
|
||||
executionSummary?: SubagentStatsSummary;
|
||||
|
||||
Reference in New Issue
Block a user