mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
fix: enhance 429 error handling and fix failed cases
This commit is contained in:
@@ -19,6 +19,8 @@ import type {
|
||||
CLIControlInitializeRequest,
|
||||
CLIControlSetModelRequest,
|
||||
} from '../../types.js';
|
||||
import { CommandService } from '../../../services/CommandService.js';
|
||||
import { BuiltinCommandLoader } from '../../../services/BuiltinCommandLoader.js';
|
||||
|
||||
export class SystemController extends BaseController {
|
||||
/**
|
||||
@@ -141,31 +143,10 @@ export class SystemController extends BaseController {
|
||||
can_set_permission_mode:
|
||||
typeof this.context.config.setApprovalMode === 'function',
|
||||
can_set_model: typeof this.context.config.setModel === 'function',
|
||||
/* TODO: sdkMcpServers support */
|
||||
can_handle_mcp_message: false,
|
||||
};
|
||||
|
||||
// Check if MCP message handling is available
|
||||
try {
|
||||
const mcpProvider = this.context.config as unknown as {
|
||||
getMcpServers?: () => Record<string, unknown> | undefined;
|
||||
};
|
||||
if (typeof mcpProvider.getMcpServers === 'function') {
|
||||
const servers = mcpProvider.getMcpServers();
|
||||
capabilities['can_handle_mcp_message'] = Boolean(
|
||||
servers && Object.keys(servers).length > 0,
|
||||
);
|
||||
} else {
|
||||
capabilities['can_handle_mcp_message'] = false;
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.context.debugMode) {
|
||||
console.error(
|
||||
'[SystemController] Failed to determine MCP capability:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
capabilities['can_handle_mcp_message'] = false;
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@@ -240,27 +221,45 @@ export class SystemController extends BaseController {
|
||||
/**
|
||||
* Handle supported_commands request
|
||||
*
|
||||
* Returns list of supported control commands
|
||||
*
|
||||
* Note: This list should match the ControlRequestType enum in
|
||||
* packages/sdk/typescript/src/types/controlRequests.ts
|
||||
* Returns list of supported slash commands loaded dynamically
|
||||
*/
|
||||
private async handleSupportedCommands(): Promise<Record<string, unknown>> {
|
||||
const commands = [
|
||||
'initialize',
|
||||
'interrupt',
|
||||
'set_model',
|
||||
'supported_commands',
|
||||
'can_use_tool',
|
||||
'set_permission_mode',
|
||||
'mcp_message',
|
||||
'mcp_server_status',
|
||||
'hook_callback',
|
||||
];
|
||||
const slashCommands = await this.loadSlashCommandNames();
|
||||
|
||||
return {
|
||||
subtype: 'supported_commands',
|
||||
commands,
|
||||
commands: slashCommands,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load slash command names using CommandService
|
||||
*
|
||||
* @returns Promise resolving to array of slash command names
|
||||
*/
|
||||
private async loadSlashCommandNames(): Promise<string[]> {
|
||||
const controller = new AbortController();
|
||||
try {
|
||||
const service = await CommandService.create(
|
||||
[new BuiltinCommandLoader(this.context.config)],
|
||||
controller.signal,
|
||||
);
|
||||
const names = new Set<string>();
|
||||
const commands = service.getCommands();
|
||||
for (const command of commands) {
|
||||
names.add(command.name);
|
||||
}
|
||||
return Array.from(names).sort();
|
||||
} catch (error) {
|
||||
if (this.context.debugMode) {
|
||||
console.error(
|
||||
'[SystemController] Failed to load slash commands:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
return [];
|
||||
} finally {
|
||||
controller.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@ import type {
|
||||
ServerGeminiStreamEvent,
|
||||
TaskResultDisplay,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import { GeminiEventType, ToolErrorType } from '@qwen-code/qwen-code-core';
|
||||
import {
|
||||
GeminiEventType,
|
||||
ToolErrorType,
|
||||
parseAndFormatApiError,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import type { Part, GenerateContentResponseUsageMetadata } from '@google/genai';
|
||||
import type {
|
||||
CLIAssistantMessage,
|
||||
@@ -600,6 +604,18 @@ export abstract class BaseJsonOutputAdapter {
|
||||
}
|
||||
this.finalizePendingBlocks(state, null);
|
||||
break;
|
||||
case GeminiEventType.Error: {
|
||||
// Format the error message using parseAndFormatApiError for consistency
|
||||
// with interactive mode error display
|
||||
const errorText = parseAndFormatApiError(
|
||||
event.value.error,
|
||||
this.config.getContentGeneratorConfig()?.authType,
|
||||
undefined,
|
||||
this.config.getModel(),
|
||||
);
|
||||
this.appendText(state, errorText, null);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ function createConfig(overrides: ConfigOverrides = {}): Config {
|
||||
getDebugMode: () => false,
|
||||
getApprovalMode: () => 'auto',
|
||||
getOutputFormat: () => 'stream-json',
|
||||
initialize: vi.fn(),
|
||||
};
|
||||
return { ...base, ...overrides } as unknown as Config;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
OutputFormat,
|
||||
InputFormat,
|
||||
uiTelemetryService,
|
||||
parseAndFormatApiError,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import type { Content, Part, PartListUnion } from '@google/genai';
|
||||
import type { CLIUserMessage, PermissionMode } from './nonInteractive/types.js';
|
||||
@@ -210,6 +211,15 @@ export async function runNonInteractive(
|
||||
process.stdout.write(event.value);
|
||||
} else if (event.type === GeminiEventType.ToolCallRequest) {
|
||||
toolCallRequests.push(event.value);
|
||||
} else if (event.type === GeminiEventType.Error) {
|
||||
// Format and output the error message for text mode
|
||||
const errorText = parseAndFormatApiError(
|
||||
event.value.error,
|
||||
config.getContentGeneratorConfig()?.authType,
|
||||
undefined,
|
||||
config.getModel(),
|
||||
);
|
||||
process.stderr.write(`${errorText}\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ execSync('tsc --project tsconfig.build.json', {
|
||||
|
||||
try {
|
||||
execSync(
|
||||
'npx dts-bundle-generator --project tsconfig.build.json -o dist/index.d.ts src/index.ts --no-check',
|
||||
'npx dts-bundle-generator --project tsconfig.build.json -o dist/index.d.ts src/index.ts',
|
||||
{
|
||||
stdio: 'inherit',
|
||||
cwd: rootDir,
|
||||
|
||||
@@ -38,7 +38,6 @@ export default defineConfig({
|
||||
},
|
||||
testTimeout: testTimeoutMs,
|
||||
hookTimeout: 10000,
|
||||
globalSetup: './test/e2e/globalSetup.ts',
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user