diff --git a/packages/a2a-server/src/task.ts b/packages/a2a-server/src/task.ts index 5a04a795..17c10466 100644 --- a/packages/a2a-server/src/task.ts +++ b/packages/a2a-server/src/task.ts @@ -416,6 +416,7 @@ export class Task { private createScheduler(): CoreToolScheduler { const scheduler = new CoreToolScheduler({ + /* @ts-expect-error */ outputUpdateHandler: this._schedulerOutputUpdate.bind(this), onAllToolCallsComplete: this._schedulerAllToolCallsComplete.bind(this), onToolCallsUpdate: this._schedulerToolCallsUpdate.bind(this), diff --git a/packages/cli/src/ui/commands/agentsCommand.ts b/packages/cli/src/ui/commands/agentsCommand.ts index b3cebe80..ccb5997a 100644 --- a/packages/cli/src/ui/commands/agentsCommand.ts +++ b/packages/cli/src/ui/commands/agentsCommand.ts @@ -4,7 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { CommandKind, SlashCommand, OpenDialogActionReturn } from './types.js'; +import { + CommandKind, + type SlashCommand, + type OpenDialogActionReturn, +} from './types.js'; export const agentsCommand: SlashCommand = { name: 'agents', diff --git a/packages/cli/src/ui/commands/summaryCommand.ts b/packages/cli/src/ui/commands/summaryCommand.ts index bf7375ec..98a8d466 100644 --- a/packages/cli/src/ui/commands/summaryCommand.ts +++ b/packages/cli/src/ui/commands/summaryCommand.ts @@ -7,12 +7,12 @@ import * as fsPromises from 'fs/promises'; import path from 'path'; import { - SlashCommand, + type SlashCommand, CommandKind, - SlashCommandActionReturn, + type SlashCommandActionReturn, } from './types.js'; import { getProjectSummaryPrompt } from '@qwen-code/qwen-code-core'; -import { HistoryItemSummary } from '../types.js'; +import type { HistoryItemSummary } from '../types.js'; export const summaryCommand: SlashCommand = { name: 'summary', diff --git a/packages/cli/src/ui/components/QuitConfirmationDialog.tsx b/packages/cli/src/ui/components/QuitConfirmationDialog.tsx index 72389401..c3487860 100644 --- a/packages/cli/src/ui/components/QuitConfirmationDialog.tsx +++ b/packages/cli/src/ui/components/QuitConfirmationDialog.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { Colors } from '../colors.js'; import { RadioButtonSelect, - RadioSelectItem, + type RadioSelectItem, } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; diff --git a/packages/cli/src/ui/components/WelcomeBackDialog.tsx b/packages/cli/src/ui/components/WelcomeBackDialog.tsx index 8a6161b3..5bb69f87 100644 --- a/packages/cli/src/ui/components/WelcomeBackDialog.tsx +++ b/packages/cli/src/ui/components/WelcomeBackDialog.tsx @@ -6,10 +6,10 @@ import { Box, Text } from 'ink'; import { Colors } from '../colors.js'; -import { ProjectSummaryInfo } from '@qwen-code/qwen-code-core'; +import { type ProjectSummaryInfo } from '@qwen-code/qwen-code-core'; import { RadioButtonSelect, - RadioSelectItem, + type RadioSelectItem, } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; diff --git a/packages/cli/src/ui/components/messages/SummaryMessage.tsx b/packages/cli/src/ui/components/messages/SummaryMessage.tsx index 03dc0d7a..602e9a6a 100644 --- a/packages/cli/src/ui/components/messages/SummaryMessage.tsx +++ b/packages/cli/src/ui/components/messages/SummaryMessage.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { Box, Text } from 'ink'; -import { SummaryProps } from '../../types.js'; +import type { SummaryProps } from '../../types.js'; import Spinner from 'ink-spinner'; import { Colors } from '../../colors.js'; diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx index 2c2867e8..bc5cd41d 100644 --- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx @@ -38,260 +38,260 @@ export const ToolConfirmationMessage: React.FC< availableTerminalHeight, terminalWidth, }) => { - const { onConfirm } = confirmationDetails; - const childWidth = terminalWidth - 2; // 2 for padding + const { onConfirm } = confirmationDetails; + const childWidth = terminalWidth - 2; // 2 for padding + + const handleConfirm = async (outcome: ToolConfirmationOutcome) => { + if (confirmationDetails.type === 'edit') { + const ideClient = config.getIdeClient(); + if (config.getIdeMode()) { + const cliOutcome = + outcome === ToolConfirmationOutcome.Cancel ? 'rejected' : 'accepted'; + await ideClient?.resolveDiffFromCli( + confirmationDetails.filePath, + cliOutcome, + ); + } + } + onConfirm(outcome); + }; + + const isTrustedFolder = config.isTrustedFolder() !== false; + + useKeypress( + (key) => { + if (!isFocused) return; + if (key.name === 'escape' || (key.ctrl && key.name === 'c')) { + handleConfirm(ToolConfirmationOutcome.Cancel); + } + }, + { isActive: isFocused }, + ); + + const handleSelect = (item: ToolConfirmationOutcome) => handleConfirm(item); + + let bodyContent: React.ReactNode | null = null; // Removed contextDisplay here + let question: string; + + const options: Array> = new Array< + RadioSelectItem + >(); + + // Body content is now the DiffRenderer, passing filename to it + // The bordered box is removed from here and handled within DiffRenderer + + function availableBodyContentHeight() { + if (options.length === 0) { + // This should not happen in practice as options are always added before this is called. + throw new Error('Options not provided for confirmation message'); + } + + if (availableTerminalHeight === undefined) { + return undefined; + } + + // Calculate the vertical space (in lines) consumed by UI elements + // surrounding the main body content. + const PADDING_OUTER_Y = 2; // Main container has `padding={1}` (top & bottom). + const MARGIN_BODY_BOTTOM = 1; // margin on the body container. + const HEIGHT_QUESTION = 1; // The question text is one line. + const MARGIN_QUESTION_BOTTOM = 1; // Margin on the question container. + const HEIGHT_OPTIONS = options.length; // Each option in the radio select takes one line. + + const surroundingElementsHeight = + PADDING_OUTER_Y + + MARGIN_BODY_BOTTOM + + HEIGHT_QUESTION + + MARGIN_QUESTION_BOTTOM + + HEIGHT_OPTIONS; + return Math.max(availableTerminalHeight - surroundingElementsHeight, 1); + } - const handleConfirm = async (outcome: ToolConfirmationOutcome) => { if (confirmationDetails.type === 'edit') { - const ideClient = config.getIdeClient(); - if (config.getIdeMode()) { - const cliOutcome = - outcome === ToolConfirmationOutcome.Cancel ? 'rejected' : 'accepted'; - await ideClient?.resolveDiffFromCli( - confirmationDetails.filePath, - cliOutcome, + if (confirmationDetails.isModifying) { + return ( + + Modify in progress: + + Save and close external editor to continue + + ); } - } - onConfirm(outcome); - }; - const isTrustedFolder = config.isTrustedFolder() !== false; - - useKeypress( - (key) => { - if (!isFocused) return; - if (key.name === 'escape' || (key.ctrl && key.name === 'c')) { - handleConfirm(ToolConfirmationOutcome.Cancel); - } - }, - { isActive: isFocused }, - ); - - const handleSelect = (item: ToolConfirmationOutcome) => handleConfirm(item); - - let bodyContent: React.ReactNode | null = null; // Removed contextDisplay here - let question: string; - - const options: Array> = new Array< - RadioSelectItem - >(); - - // Body content is now the DiffRenderer, passing filename to it - // The bordered box is removed from here and handled within DiffRenderer - - function availableBodyContentHeight() { - if (options.length === 0) { - // This should not happen in practice as options are always added before this is called. - throw new Error('Options not provided for confirmation message'); - } - - if (availableTerminalHeight === undefined) { - return undefined; - } - - // Calculate the vertical space (in lines) consumed by UI elements - // surrounding the main body content. - const PADDING_OUTER_Y = 2; // Main container has `padding={1}` (top & bottom). - const MARGIN_BODY_BOTTOM = 1; // margin on the body container. - const HEIGHT_QUESTION = 1; // The question text is one line. - const MARGIN_QUESTION_BOTTOM = 1; // Margin on the question container. - const HEIGHT_OPTIONS = options.length; // Each option in the radio select takes one line. - - const surroundingElementsHeight = - PADDING_OUTER_Y + - MARGIN_BODY_BOTTOM + - HEIGHT_QUESTION + - MARGIN_QUESTION_BOTTOM + - HEIGHT_OPTIONS; - return Math.max(availableTerminalHeight - surroundingElementsHeight, 1); - } - - if (confirmationDetails.type === 'edit') { - if (confirmationDetails.isModifying) { - return ( - - Modify in progress: - - Save and close external editor to continue - - - ); - } - - question = `Apply this change?`; - options.push({ - label: 'Yes, allow once', - value: ToolConfirmationOutcome.ProceedOnce, - }); - if (isTrustedFolder) { + question = `Apply this change?`; options.push({ - label: 'Yes, allow always', - value: ToolConfirmationOutcome.ProceedAlways, + label: 'Yes, allow once', + value: ToolConfirmationOutcome.ProceedOnce, }); - } - if (config.getIdeMode()) { + if (isTrustedFolder) { + options.push({ + label: 'Yes, allow always', + value: ToolConfirmationOutcome.ProceedAlways, + }); + } + if (config.getIdeMode()) { + options.push({ + label: 'No (esc)', + value: ToolConfirmationOutcome.Cancel, + }); + } else { + options.push({ + label: 'Modify with external editor', + value: ToolConfirmationOutcome.ModifyWithEditor, + }); + options.push({ + label: 'No, suggest changes (esc)', + value: ToolConfirmationOutcome.Cancel, + }); + } + + bodyContent = ( + + ); + } else if (confirmationDetails.type === 'exec') { + const executionProps = + confirmationDetails as ToolExecuteConfirmationDetails; + + question = `Allow execution of: '${executionProps.rootCommand}'?`; options.push({ - label: 'No (esc)', + label: 'Yes, allow once', + value: ToolConfirmationOutcome.ProceedOnce, + }); + if (isTrustedFolder) { + options.push({ + label: `Yes, allow always ...`, + value: ToolConfirmationOutcome.ProceedAlways, + }); + } + options.push({ + label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); - } else { + + let bodyContentHeight = availableBodyContentHeight(); + if (bodyContentHeight !== undefined) { + bodyContentHeight -= 2; // Account for padding; + } + bodyContent = ( + + + + + {executionProps.command} + + + + + ); + } else if (confirmationDetails.type === 'info') { + const infoProps = confirmationDetails; + const displayUrls = + infoProps.urls && + !(infoProps.urls.length === 1 && infoProps.urls[0] === infoProps.prompt); + + question = `Do you want to proceed?`; options.push({ - label: 'Modify with external editor', - value: ToolConfirmationOutcome.ModifyWithEditor, + label: 'Yes, allow once', + value: ToolConfirmationOutcome.ProceedOnce, }); + if (isTrustedFolder) { + options.push({ + label: 'Yes, allow always', + value: ToolConfirmationOutcome.ProceedAlways, + }); + } + options.push({ + label: 'No, suggest changes (esc)', + value: ToolConfirmationOutcome.Cancel, + }); + + bodyContent = ( + + + + + {displayUrls && infoProps.urls && infoProps.urls.length > 0 && ( + + URLs to fetch: + {infoProps.urls.map((url) => ( + + {' '} + - + + ))} + + )} + + ); + } else { + // mcp tool confirmation + const mcpProps = confirmationDetails as ToolMcpConfirmationDetails; + + bodyContent = ( + + MCP Server: {mcpProps.serverName} + Tool: {mcpProps.toolName} + + ); + + question = `Allow execution of MCP tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"?`; + options.push({ + label: 'Yes, allow once', + value: ToolConfirmationOutcome.ProceedOnce, + }); + if (isTrustedFolder) { + options.push({ + label: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`, + value: ToolConfirmationOutcome.ProceedAlwaysTool, // Cast until types are updated + }); + options.push({ + label: `Yes, always allow all tools from server "${mcpProps.serverName}"`, + value: ToolConfirmationOutcome.ProceedAlwaysServer, + }); + } options.push({ label: 'No, suggest changes (esc)', value: ToolConfirmationOutcome.Cancel, }); } - bodyContent = ( - - ); - } else if (confirmationDetails.type === 'exec') { - const executionProps = - confirmationDetails as ToolExecuteConfirmationDetails; + return ( + + {/* Body Content (Diff Renderer or Command Info) */} + {/* No separate context display here anymore for edits */} + + {bodyContent} + - question = `Allow execution of: '${executionProps.rootCommand}'?`; - options.push({ - label: 'Yes, allow once', - value: ToolConfirmationOutcome.ProceedOnce, - }); - if (isTrustedFolder) { - options.push({ - label: `Yes, allow always ...`, - value: ToolConfirmationOutcome.ProceedAlways, - }); - } - options.push({ - label: 'No, suggest changes (esc)', - value: ToolConfirmationOutcome.Cancel, - }); + {/* Confirmation Question */} + + {question} + - let bodyContentHeight = availableBodyContentHeight(); - if (bodyContentHeight !== undefined) { - bodyContentHeight -= 2; // Account for padding; - } - bodyContent = ( - - - - - {executionProps.command} - - + {/* Select Input for Options */} + + ); - } else if (confirmationDetails.type === 'info') { - const infoProps = confirmationDetails; - const displayUrls = - infoProps.urls && - !(infoProps.urls.length === 1 && infoProps.urls[0] === infoProps.prompt); - - question = `Do you want to proceed?`; - options.push({ - label: 'Yes, allow once', - value: ToolConfirmationOutcome.ProceedOnce, - }); - if (isTrustedFolder) { - options.push({ - label: 'Yes, allow always', - value: ToolConfirmationOutcome.ProceedAlways, - }); - } - options.push({ - label: 'No, suggest changes (esc)', - value: ToolConfirmationOutcome.Cancel, - }); - - bodyContent = ( - - - - - {displayUrls && infoProps.urls && infoProps.urls.length > 0 && ( - - URLs to fetch: - {infoProps.urls.map((url) => ( - - {' '} - - - - ))} - - )} - - ); - } else { - // mcp tool confirmation - const mcpProps = confirmationDetails as ToolMcpConfirmationDetails; - - bodyContent = ( - - MCP Server: {mcpProps.serverName} - Tool: {mcpProps.toolName} - - ); - - question = `Allow execution of MCP tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"?`; - options.push({ - label: 'Yes, allow once', - value: ToolConfirmationOutcome.ProceedOnce, - }); - if (isTrustedFolder) { - options.push({ - label: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`, - value: ToolConfirmationOutcome.ProceedAlwaysTool, // Cast until types are updated - }); - options.push({ - label: `Yes, always allow all tools from server "${mcpProps.serverName}"`, - value: ToolConfirmationOutcome.ProceedAlwaysServer, - }); - } - options.push({ - label: 'No, suggest changes (esc)', - value: ToolConfirmationOutcome.Cancel, - }); - } - - return ( - - {/* Body Content (Diff Renderer or Command Info) */} - {/* No separate context display here anymore for edits */} - - {bodyContent} - - - {/* Confirmation Question */} - - {question} - - - {/* Select Input for Options */} - - - - - ); -}; + }; diff --git a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx index af73813e..059815ad 100644 --- a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx @@ -60,12 +60,12 @@ export const ToolGroupMessage: React.FC = ({ const countOneLineToolCalls = toolCalls.length - countToolCallsWithResults; const availableTerminalHeightPerToolMessage = availableTerminalHeight ? Math.max( - Math.floor( - (availableTerminalHeight - staticHeight - countOneLineToolCalls) / - Math.max(1, countToolCallsWithResults), - ), - 1, - ) + Math.floor( + (availableTerminalHeight - staticHeight - countOneLineToolCalls) / + Math.max(1, countToolCallsWithResults), + ), + 1, + ) : undefined; return ( diff --git a/packages/cli/src/ui/components/messages/ToolMessage.tsx b/packages/cli/src/ui/components/messages/ToolMessage.tsx index ce96fb99..daedbef4 100644 --- a/packages/cli/src/ui/components/messages/ToolMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolMessage.tsx @@ -189,9 +189,9 @@ export const ToolMessage: React.FC = ({ }) => { const availableHeight = availableTerminalHeight ? Math.max( - availableTerminalHeight - STATIC_HEIGHT - RESERVED_LINE_COUNT, - MIN_LINES_SHOWN + 1, // enforce minimum lines shown - ) + availableTerminalHeight - STATIC_HEIGHT - RESERVED_LINE_COUNT, + MIN_LINES_SHOWN + 1, // enforce minimum lines shown + ) : undefined; // Long tool call response in MarkdownDisplay doesn't respect availableTerminalHeight properly, diff --git a/packages/cli/src/ui/components/subagents/create/AgentCreationWizard.tsx b/packages/cli/src/ui/components/subagents/create/AgentCreationWizard.tsx index 6756856b..b2c7009a 100644 --- a/packages/cli/src/ui/components/subagents/create/AgentCreationWizard.tsx +++ b/packages/cli/src/ui/components/subagents/create/AgentCreationWizard.tsx @@ -13,7 +13,7 @@ import { DescriptionInput } from './DescriptionInput.js'; import { ToolSelector } from './ToolSelector.js'; import { ColorSelector } from './ColorSelector.js'; import { CreationSummary } from './CreationSummary.js'; -import { WizardStepProps } from '../types.js'; +import { type WizardStepProps } from '../types.js'; import { WIZARD_STEPS } from '../constants.js'; import { getStepKind } from '../utils.js'; import { Config } from '@qwen-code/qwen-code-core'; diff --git a/packages/cli/src/ui/components/subagents/create/ColorSelector.tsx b/packages/cli/src/ui/components/subagents/create/ColorSelector.tsx index bac5b768..63d7b228 100644 --- a/packages/cli/src/ui/components/subagents/create/ColorSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/ColorSelector.tsx @@ -7,7 +7,7 @@ import { useState, useEffect } from 'react'; import { Box, Text } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; -import { ColorOption } from '../types.js'; +import { type ColorOption } from '../types.js'; import { Colors } from '../../../colors.js'; import { COLOR_OPTIONS } from '../constants.js'; diff --git a/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx b/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx index 97024b64..ba26f878 100644 --- a/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx +++ b/packages/cli/src/ui/components/subagents/create/CreationSummary.tsx @@ -6,8 +6,8 @@ import { useCallback, useState, useEffect } from 'react'; import { Box, Text, useInput } from 'ink'; -import { WizardStepProps } from '../types.js'; -import { SubagentManager, SubagentConfig } from '@qwen-code/qwen-code-core'; +import { type WizardStepProps } from '../types.js'; +import { SubagentManager, type SubagentConfig } from '@qwen-code/qwen-code-core'; import { theme } from '../../../semantic-colors.js'; import { shouldShowColor, getColorForDisplay } from '../utils.js'; import { useLaunchEditor } from '../../../hooks/useLaunchEditor.js'; diff --git a/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx b/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx index 24342cf8..24b9f7c2 100644 --- a/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx +++ b/packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx @@ -7,10 +7,10 @@ import { useCallback, useRef } from 'react'; import { Box, Text } from 'ink'; import Spinner from 'ink-spinner'; -import { WizardStepProps, WizardAction } from '../types.js'; +import type { WizardStepProps, WizardAction } from '../types.js'; import { sanitizeInput } from '../utils.js'; import { Config, subagentGenerator } from '@qwen-code/qwen-code-core'; -import { useKeypress, Key } from '../../../hooks/useKeypress.js'; +import { useKeypress, type Key } from '../../../hooks/useKeypress.js'; import { keyMatchers, Command } from '../../../keyMatchers.js'; import { theme } from '../../../semantic-colors.js'; import { Colors } from '../../../colors.js'; diff --git a/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx b/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx index 3b2748a2..e9e01a7f 100644 --- a/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/GenerationMethodSelector.tsx @@ -6,7 +6,7 @@ import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; -import { WizardStepProps } from '../types.js'; +import type { WizardStepProps } from '../types.js'; interface GenerationOption { label: string; diff --git a/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx b/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx index 297a3102..647c8ce6 100644 --- a/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/LocationSelector.tsx @@ -6,7 +6,7 @@ import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; -import { WizardStepProps } from '../types.js'; +import type { WizardStepProps } from '../types.js'; interface LocationOption { label: string; diff --git a/packages/cli/src/ui/components/subagents/create/TextEntryStep.tsx b/packages/cli/src/ui/components/subagents/create/TextEntryStep.tsx index 35f3aca7..a9bb4d5e 100644 --- a/packages/cli/src/ui/components/subagents/create/TextEntryStep.tsx +++ b/packages/cli/src/ui/components/subagents/create/TextEntryStep.tsx @@ -6,7 +6,7 @@ import { useCallback } from 'react'; import { Box, Text } from 'ink'; -import { WizardStepProps } from '../types.js'; +import type { WizardStepProps } from '../types.js'; import { Colors } from '../../../colors.js'; import { TextInput } from '../../shared/TextInput.js'; diff --git a/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx b/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx index 00ca1e83..fe4215d6 100644 --- a/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx +++ b/packages/cli/src/ui/components/subagents/create/ToolSelector.tsx @@ -7,7 +7,7 @@ import { useState, useMemo, useEffect } from 'react'; import { Box, Text } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; -import { ToolCategory } from '../types.js'; +import type { ToolCategory } from '../types.js'; import { Kind, Config } from '@qwen-code/qwen-code-core'; import { Colors } from '../../../colors.js'; diff --git a/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx b/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx index 87c37599..4fc112fb 100644 --- a/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/ActionSelectionStep.tsx @@ -8,7 +8,7 @@ import { useState } from 'react'; import { Box } from 'ink'; import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import { MANAGEMENT_STEPS } from '../types.js'; -import { SubagentConfig } from '@qwen-code/qwen-code-core'; +import { type SubagentConfig } from '@qwen-code/qwen-code-core'; interface ActionSelectionStepProps { selectedAgent: SubagentConfig | null; @@ -35,8 +35,8 @@ export const ActionSelectionStep = ({ const actions = selectedAgent?.isBuiltin ? allActions.filter( - (action) => action.value === 'view' || action.value === 'back', - ) + (action) => action.value === 'view' || action.value === 'back', + ) : allActions; const handleActionSelect = (value: 'view' | 'edit' | 'delete' | 'back') => { diff --git a/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx index 697d9719..245d348e 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentDeleteStep.tsx @@ -5,8 +5,8 @@ */ import { Box, Text } from 'ink'; -import { SubagentConfig } from '@qwen-code/qwen-code-core'; -import { StepNavigationProps } from '../types.js'; +import { type SubagentConfig } from '@qwen-code/qwen-code-core'; +import type { StepNavigationProps } from '../types.js'; import { theme } from '../../../semantic-colors.js'; import { useKeypress } from '../../../hooks/useKeypress.js'; diff --git a/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx index 244a0b2b..2e344b55 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentEditStep.tsx @@ -10,7 +10,7 @@ import { RadioButtonSelect } from '../../shared/RadioButtonSelect.js'; import { MANAGEMENT_STEPS } from '../types.js'; import { theme } from '../../../semantic-colors.js'; import { useLaunchEditor } from '../../../hooks/useLaunchEditor.js'; -import { SubagentConfig } from '@qwen-code/qwen-code-core'; +import { type SubagentConfig } from '@qwen-code/qwen-code-core'; interface EditOption { id: string; diff --git a/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx index d1161e10..c64cb946 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentSelectionStep.tsx @@ -9,7 +9,7 @@ import { Box, Text } from 'ink'; import { theme } from '../../../semantic-colors.js'; import { Colors } from '../../../colors.js'; import { useKeypress } from '../../../hooks/useKeypress.js'; -import { SubagentConfig } from '@qwen-code/qwen-code-core'; +import { type SubagentConfig } from '@qwen-code/qwen-code-core'; interface NavigationState { currentBlock: 'project' | 'user' | 'builtin'; @@ -318,12 +318,12 @@ export const AgentSelectionStep = ({ {(projectAgents.length > 0 || userAgents.length > 0 || builtinAgents.length > 0) && ( - - - Using: {enabledAgentsCount} agents - - - )} + + + Using: {enabledAgentsCount} agents + + + )} ); }; diff --git a/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx b/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx index 66532586..8f5fd2dd 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentViewerStep.tsx @@ -7,7 +7,7 @@ import { Box, Text } from 'ink'; import { theme } from '../../../semantic-colors.js'; import { shouldShowColor, getColorForDisplay } from '../utils.js'; -import { SubagentConfig } from '@qwen-code/qwen-code-core'; +import { type SubagentConfig } from '@qwen-code/qwen-code-core'; interface AgentViewerStepProps { selectedAgent: SubagentConfig | null; diff --git a/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx b/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx index e68167d4..73cb3c0b 100644 --- a/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx +++ b/packages/cli/src/ui/components/subagents/manage/AgentsManagerDialog.tsx @@ -17,7 +17,7 @@ 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'; +import { Config, type SubagentConfig } from '@qwen-code/qwen-code-core'; interface AgentsManagerDialogProps { onClose: () => void; @@ -170,8 +170,8 @@ export function AgentsManagerDialog({ // Use agent color for the Agent Viewer header const headerColor = currentStep === MANAGEMENT_STEPS.AGENT_VIEWER && - selectedAgent && - shouldShowColor(selectedAgent.color) + selectedAgent && + shouldShowColor(selectedAgent.color) ? getColorForDisplay(selectedAgent.color) : undefined; diff --git a/packages/cli/src/ui/components/subagents/reducers.tsx b/packages/cli/src/ui/components/subagents/reducers.tsx index 2882b354..12799145 100644 --- a/packages/cli/src/ui/components/subagents/reducers.tsx +++ b/packages/cli/src/ui/components/subagents/reducers.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { CreationWizardState, WizardAction } from './types.js'; +import { type CreationWizardState, type WizardAction } from './types.js'; import { WIZARD_STEPS } from './constants.js'; import { getStepKind, getTotalSteps } from './utils.js'; diff --git a/packages/cli/src/ui/components/subagents/runtime/AgentExecutionDisplay.tsx b/packages/cli/src/ui/components/subagents/runtime/AgentExecutionDisplay.tsx index 355e7eae..03acdaf9 100644 --- a/packages/cli/src/ui/components/subagents/runtime/AgentExecutionDisplay.tsx +++ b/packages/cli/src/ui/components/subagents/runtime/AgentExecutionDisplay.tsx @@ -7,7 +7,7 @@ import React, { useMemo } from 'react'; import { Box, Text } from 'ink'; import { Colors } from '../../../colors.js'; -import { +import type { TaskResultDisplay, SubagentStatsSummary, } from '@qwen-code/qwen-code-core'; @@ -163,8 +163,8 @@ export const AgentExecutionDisplay: React.FC = ({ {(data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') && ( - - )} + + )} {/* Footer with keyboard shortcuts */} {footerText && ( diff --git a/packages/cli/src/ui/components/subagents/types.ts b/packages/cli/src/ui/components/subagents/types.ts index 7aaa101f..1b9d8a48 100644 --- a/packages/cli/src/ui/components/subagents/types.ts +++ b/packages/cli/src/ui/components/subagents/types.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { SubagentLevel, Config } from '@qwen-code/qwen-code-core'; +import { type SubagentLevel, Config } from '@qwen-code/qwen-code-core'; /** * State management for the subagent creation wizard. diff --git a/packages/cli/src/ui/hooks/useLaunchEditor.ts b/packages/cli/src/ui/hooks/useLaunchEditor.ts index bce242c8..85ee5ccf 100644 --- a/packages/cli/src/ui/hooks/useLaunchEditor.ts +++ b/packages/cli/src/ui/hooks/useLaunchEditor.ts @@ -6,7 +6,7 @@ import { useCallback } from 'react'; import { useStdin } from 'ink'; -import { EditorType } from '@qwen-code/qwen-code-core'; +import type { EditorType } from '@qwen-code/qwen-code-core'; import { spawnSync } from 'child_process'; import { useSettings } from '../contexts/SettingsContext.js'; @@ -39,7 +39,7 @@ export function useLaunchEditor() { const launchEditor = useCallback( async (filePath: string): Promise => { - const preferredEditor = settings.merged.preferredEditor as + const preferredEditor = settings.merged.general?.preferredEditor as | EditorType | undefined; const editor = getEditorCommand(preferredEditor); @@ -75,7 +75,7 @@ export function useLaunchEditor() { if (wasRaw) setRawMode?.(true); } }, - [settings.merged.preferredEditor, setRawMode, stdin], + [settings.merged.general?.preferredEditor, setRawMode, stdin], ); return launchEditor; diff --git a/packages/core/src/core/coreToolScheduler.test.ts b/packages/core/src/core/coreToolScheduler.test.ts index eab7da71..10d4f181 100644 --- a/packages/core/src/core/coreToolScheduler.test.ts +++ b/packages/core/src/core/coreToolScheduler.test.ts @@ -794,11 +794,11 @@ describe('CoreToolScheduler cancellation during executing with live output', () model: 'test-model', authType: 'oauth-personal', }), + getToolRegistry: () => mockToolRegistry, } as unknown as Config; const scheduler = new CoreToolScheduler({ config: mockConfig, - toolRegistry: mockToolRegistry, onAllToolCallsComplete, onToolCallsUpdate, getPreferredEditor: () => 'vscode', diff --git a/packages/core/src/core/prompts.ts b/packages/core/src/core/prompts.ts index cb7d8289..fb44d16c 100644 --- a/packages/core/src/core/prompts.ts +++ b/packages/core/src/core/prompts.ts @@ -19,7 +19,7 @@ import { isGitRepository } from '../utils/gitUtils.js'; import { MemoryTool, GEMINI_CONFIG_DIR } from '../tools/memoryTool.js'; import { TodoWriteTool } from '../tools/todoWrite.js'; import { TaskTool } from '../tools/task.js'; -import { GenerateContentConfig } from '@google/genai'; +import type { GenerateContentConfig } from '@google/genai'; export interface ModelTemplateMapping { baseUrls?: string[]; diff --git a/packages/core/src/subagents/builtin-agents.ts b/packages/core/src/subagents/builtin-agents.ts index 437029cf..40576197 100644 --- a/packages/core/src/subagents/builtin-agents.ts +++ b/packages/core/src/subagents/builtin-agents.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { SubagentConfig } from './types.js'; +import type { SubagentConfig } from './types.js'; /** * Registry of built-in subagents that are always available to all users. diff --git a/packages/core/src/subagents/subagent-events.ts b/packages/core/src/subagents/subagent-events.ts index 665b33b3..de677b5b 100644 --- a/packages/core/src/subagents/subagent-events.ts +++ b/packages/core/src/subagents/subagent-events.ts @@ -6,7 +6,7 @@ import { EventEmitter } from 'events'; import { - ToolCallConfirmationDetails, + type ToolCallConfirmationDetails, ToolConfirmationOutcome, } from '../tools/tools.js'; diff --git a/packages/core/src/subagents/subagent-manager.test.ts b/packages/core/src/subagents/subagent-manager.test.ts index 2b199907..7f7f74d9 100644 --- a/packages/core/src/subagents/subagent-manager.test.ts +++ b/packages/core/src/subagents/subagent-manager.test.ts @@ -9,7 +9,7 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; import { SubagentManager } from './subagent-manager.js'; -import { SubagentConfig, SubagentError } from './types.js'; +import { type SubagentConfig, SubagentError } from './types.js'; import { ToolRegistry } from '../tools/tool-registry.js'; import { Config } from '../config/config.js'; import { makeFakeConfig } from '../test-utils/config.js'; diff --git a/packages/core/src/subagents/subagent-manager.ts b/packages/core/src/subagents/subagent-manager.ts index c06081ae..3b2629fc 100644 --- a/packages/core/src/subagents/subagent-manager.ts +++ b/packages/core/src/subagents/subagent-manager.ts @@ -13,19 +13,18 @@ import { parse as parseYaml, stringify as stringifyYaml, } from '../utils/yaml-parser.js'; -import { +import type { SubagentConfig, SubagentRuntimeConfig, SubagentLevel, ListSubagentsOptions, CreateSubagentOptions, - SubagentError, - SubagentErrorCode, PromptConfig, ModelConfig, RunConfig, ToolConfig, } from './types.js'; +import { SubagentError, SubagentErrorCode } from './types.js'; import { SubagentValidator } from './validation.js'; import { SubAgentScope } from './subagent.js'; import { Config } from '../config/config.js'; diff --git a/packages/core/src/subagents/subagent.test.ts b/packages/core/src/subagents/subagent.test.ts index 932d975f..cc7ab0f1 100644 --- a/packages/core/src/subagents/subagent.test.ts +++ b/packages/core/src/subagents/subagent.test.ts @@ -165,7 +165,7 @@ describe('subagent.ts', () => { // Default mock for executeToolCall vi.mocked(executeToolCall).mockResolvedValue({ callId: 'default-call', - responseParts: 'default response', + responseParts: [{ text: 'default response' }], resultDisplay: 'Default tool result', error: undefined, errorType: undefined, diff --git a/packages/core/src/subagents/subagent.ts b/packages/core/src/subagents/subagent.ts index 92cea603..0f787888 100644 --- a/packages/core/src/subagents/subagent.ts +++ b/packages/core/src/subagents/subagent.ts @@ -6,11 +6,11 @@ import { reportError } from '../utils/errorReporting.js'; import { Config } from '../config/config.js'; -import { ToolCallRequestInfo } from '../core/turn.js'; +import { type ToolCallRequestInfo } from '../core/turn.js'; import { CoreToolScheduler, - ToolCall, - WaitingToolCall, + type ToolCall, + type WaitingToolCall, } from '../core/coreToolScheduler.js'; import type { ToolConfirmationOutcome, @@ -18,7 +18,7 @@ import type { } from '../tools/tools.js'; import { createContentGenerator } from '../core/contentGenerator.js'; import { getEnvironmentContext } from '../utils/environmentContext.js'; -import { +import type { Content, Part, FunctionCall, @@ -27,16 +27,14 @@ import { GenerateContentResponseUsageMetadata, } from '@google/genai'; import { GeminiChat } from '../core/geminiChat.js'; -import { - SubagentTerminateMode, +import type { PromptConfig, ModelConfig, RunConfig, ToolConfig, } from './types.js'; -import { - SubAgentEventEmitter, - SubAgentEventType, +import { SubagentTerminateMode } from './types.js'; +import type { SubAgentFinishEvent, SubAgentRoundEvent, SubAgentStartEvent, @@ -45,11 +43,12 @@ import { SubAgentStreamTextEvent, SubAgentErrorEvent, } from './subagent-events.js'; +import { SubAgentEventEmitter, SubAgentEventType } from './subagent-events.js'; import { SubagentStatistics, - SubagentStatsSummary, + type SubagentStatsSummary, } from './subagent-statistics.js'; -import { SubagentHooks } from './subagent-hooks.js'; +import type { SubagentHooks } from './subagent-hooks.js'; import { logSubagentExecution } from '../telemetry/loggers.js'; import { SubagentExecutionEvent } from '../telemetry/types.js'; import { TaskTool } from '../tools/task.js'; @@ -379,26 +378,36 @@ export class SubAgentScope { let roundText = ''; let lastUsage: GenerateContentResponseUsageMetadata | undefined = undefined; - for await (const resp of responseStream) { + for await (const streamEvent of responseStream) { if (abortController.signal.aborted) { this.terminateMode = SubagentTerminateMode.CANCELLED; return; } - if (resp.functionCalls) functionCalls.push(...resp.functionCalls); - const content = resp.candidates?.[0]?.content; - const parts = content?.parts || []; - for (const p of parts) { - const txt = (p as Part & { text?: string }).text; - if (txt) roundText += txt; - if (txt) - this.eventEmitter?.emit(SubAgentEventType.STREAM_TEXT, { - subagentId: this.subagentId, - round: turnCounter, - text: txt, - timestamp: Date.now(), - } as SubAgentStreamTextEvent); + + // Handle retry events + if (streamEvent.type === 'retry') { + continue; + } + + // Handle chunk events + if (streamEvent.type === 'chunk') { + const resp = streamEvent.value; + if (resp.functionCalls) functionCalls.push(...resp.functionCalls); + const content = resp.candidates?.[0]?.content; + const parts = content?.parts || []; + for (const p of parts) { + const txt = (p as Part & { text?: string }).text; + if (txt) roundText += txt; + if (txt) + this.eventEmitter?.emit(SubAgentEventType.STREAM_TEXT, { + subagentId: this.subagentId, + round: turnCounter, + text: txt, + timestamp: Date.now(), + } as SubAgentStreamTextEvent); + } + if (resp.usageMetadata) lastUsage = resp.usageMetadata; } - if (resp.usageMetadata) lastUsage = resp.usageMetadata; } this.executionStats.rounds = turnCounter; this.stats.setRounds(turnCounter); @@ -546,7 +555,6 @@ export class SubAgentScope { const responded = new Set(); let resolveBatch: (() => void) | null = null; const scheduler = new CoreToolScheduler({ - toolRegistry: this.runtimeContext.getToolRegistry(), outputUpdateHandler: undefined, onAllToolCallsComplete: async (completedCalls) => { for (const call of completedCalls) { diff --git a/packages/core/src/subagents/types.ts b/packages/core/src/subagents/types.ts index b8146125..be30883e 100644 --- a/packages/core/src/subagents/types.ts +++ b/packages/core/src/subagents/types.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Content, FunctionDeclaration } from '@google/genai'; +import type { Content, FunctionDeclaration } from '@google/genai'; /** * Represents the storage level for a subagent configuration. diff --git a/packages/core/src/subagents/validation.test.ts b/packages/core/src/subagents/validation.test.ts index c41c2452..26819845 100644 --- a/packages/core/src/subagents/validation.test.ts +++ b/packages/core/src/subagents/validation.test.ts @@ -6,7 +6,7 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { SubagentValidator } from './validation.js'; -import { SubagentConfig, SubagentError } from './types.js'; +import { type SubagentConfig, SubagentError } from './types.js'; describe('SubagentValidator', () => { let validator: SubagentValidator; diff --git a/packages/core/src/subagents/validation.ts b/packages/core/src/subagents/validation.ts index 4bca0b5a..5df8cc31 100644 --- a/packages/core/src/subagents/validation.ts +++ b/packages/core/src/subagents/validation.ts @@ -4,13 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - SubagentConfig, - ValidationResult, - SubagentError, - SubagentErrorCode, +import { SubagentError, SubagentErrorCode } from './types.js'; +import type { ModelConfig, RunConfig, + SubagentConfig, + ValidationResult, } from './types.js'; /** diff --git a/packages/core/src/tools/task.test.ts b/packages/core/src/tools/task.test.ts index e7523df3..9de30ab9 100644 --- a/packages/core/src/tools/task.test.ts +++ b/packages/core/src/tools/task.test.ts @@ -5,12 +5,15 @@ */ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { TaskTool, TaskParams } from './task.js'; +import { TaskTool, type TaskParams } from './task.js'; import type { PartListUnion } from '@google/genai'; import type { ToolResultDisplay, TaskResultDisplay } from './tools.js'; import { Config } from '../config/config.js'; import { SubagentManager } from '../subagents/subagent-manager.js'; -import { SubagentConfig, SubagentTerminateMode } from '../subagents/types.js'; +import { + type SubagentConfig, + SubagentTerminateMode, +} from '../subagents/types.js'; import { SubAgentScope, ContextState } from '../subagents/subagent.js'; import { partToString } from '../utils/partUtils.js'; diff --git a/packages/core/src/tools/task.ts b/packages/core/src/tools/task.ts index 6c4eec00..ef0d411b 100644 --- a/packages/core/src/tools/task.ts +++ b/packages/core/src/tools/task.ts @@ -4,10 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - BaseDeclarativeTool, - BaseToolInvocation, - Kind, +import { BaseDeclarativeTool, BaseToolInvocation, Kind } from './tools.js'; +import type { ToolResult, ToolResultDisplay, TaskResultDisplay, @@ -19,14 +17,19 @@ import type { } from './tools.js'; import { Config } from '../config/config.js'; import { SubagentManager } from '../subagents/subagent-manager.js'; -import { SubagentConfig, SubagentTerminateMode } from '../subagents/types.js'; +import { + type SubagentConfig, + SubagentTerminateMode, +} from '../subagents/types.js'; import { ContextState } from '../subagents/subagent.js'; import { SubAgentEventEmitter, + SubAgentEventType, +} from '../subagents/subagent-events.js'; +import type { SubAgentToolCallEvent, SubAgentToolResultEvent, SubAgentFinishEvent, - SubAgentEventType, SubAgentErrorEvent, SubAgentApprovalRequestEvent, } from '../subagents/subagent-events.js'; diff --git a/packages/core/src/tools/tools.ts b/packages/core/src/tools/tools.ts index 2d65e65c..5a5608a8 100644 --- a/packages/core/src/tools/tools.ts +++ b/packages/core/src/tools/tools.ts @@ -8,7 +8,7 @@ import type { FunctionDeclaration, PartListUnion } from '@google/genai'; import { ToolErrorType } from './tool-error.js'; import type { DiffUpdateResult } from '../ide/ideContext.js'; import { SchemaValidator } from '../utils/schemaValidator.js'; -import { SubagentStatsSummary } from '../subagents/subagent-statistics.js'; +import { type SubagentStatsSummary } from '../subagents/subagent-statistics.js'; /** * Represents a validated and ready-to-execute tool call. diff --git a/packages/core/src/utils/subagentGenerator.test.ts b/packages/core/src/utils/subagentGenerator.test.ts index e338c03f..2f687678 100644 --- a/packages/core/src/utils/subagentGenerator.test.ts +++ b/packages/core/src/utils/subagentGenerator.test.ts @@ -4,14 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { describe, it, expect, vi, beforeEach, Mock, afterEach } from 'vitest'; -import { Content, GoogleGenAI, Models } from '@google/genai'; +import { + describe, + it, + expect, + vi, + beforeEach, + type Mock, + afterEach, +} from 'vitest'; +import { type Content, GoogleGenAI, Models } from '@google/genai'; import { DEFAULT_QWEN_MODEL } from '../config/models.js'; import { GeminiClient } from '../core/client.js'; import { Config } from '../config/config.js'; import { subagentGenerator, - SubagentGeneratedContent, + type SubagentGeneratedContent, } from './subagentGenerator.js'; // Mock GeminiClient and Config constructor diff --git a/packages/core/src/utils/subagentGenerator.ts b/packages/core/src/utils/subagentGenerator.ts index b15b71d1..58e8a121 100644 --- a/packages/core/src/utils/subagentGenerator.ts +++ b/packages/core/src/utils/subagentGenerator.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Content } from '@google/genai'; +import { type Content } from '@google/genai'; import { DEFAULT_QWEN_MODEL } from '../config/models.js'; import { GeminiClient } from '../core/client.js';