mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-25 11:09:13 +00:00
Compare commits
1 Commits
sdk-typesc
...
v0.4.0-nig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5f7cabeca |
@@ -1195,7 +1195,7 @@ describe('Permission Control (E2E)', () => {
|
||||
});
|
||||
|
||||
describe('mode comparison tests', () => {
|
||||
it.skip(
|
||||
it(
|
||||
'should demonstrate different behaviors across all modes for write operations',
|
||||
async () => {
|
||||
const modes: Array<'default' | 'auto-edit' | 'yolo'> = [
|
||||
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
@@ -16422,7 +16422,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"dependencies": {
|
||||
"@google/genai": "1.16.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
@@ -16537,7 +16537,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@qwen-code/qwen-code-core",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@google/genai": "1.16.0",
|
||||
@@ -16677,7 +16677,7 @@
|
||||
},
|
||||
"packages/sdk-typescript": {
|
||||
"name": "@qwen-code/sdk",
|
||||
"version": "0.1.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.4"
|
||||
@@ -19106,7 +19106,7 @@
|
||||
},
|
||||
"packages/test-utils": {
|
||||
"name": "@qwen-code/qwen-code-test-utils",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
@@ -19118,7 +19118,7 @@
|
||||
},
|
||||
"packages/vscode-ide-companion": {
|
||||
"name": "qwen-code-vscode-ide-companion",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"license": "LICENSE",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.15.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
@@ -13,7 +13,7 @@
|
||||
"url": "git+https://github.com/QwenLM/qwen-code.git"
|
||||
},
|
||||
"config": {
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.4.0"
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.4.0-nightly.20251206.ab228c68"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env node scripts/start.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"description": "Qwen Code",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -33,7 +33,7 @@
|
||||
"dist"
|
||||
],
|
||||
"config": {
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.4.0"
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.4.0-nightly.20251206.ab228c68"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/genai": "1.16.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code-core",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"description": "Qwen Code Core",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -59,7 +59,7 @@ Creates a new query session with the Qwen Code.
|
||||
| `model` | `string` | - | The AI model to use (e.g., `'qwen-max'`, `'qwen-plus'`, `'qwen-turbo'`). Takes precedence over `OPENAI_MODEL` and `QWEN_MODEL` environment variables. |
|
||||
| `pathToQwenExecutable` | `string` | Auto-detected | Path to the Qwen Code executable. Supports multiple formats: `'qwen'` (native binary from PATH), `'/path/to/qwen'` (explicit path), `'/path/to/cli.js'` (Node.js bundle), `'node:/path/to/cli.js'` (force Node.js runtime), `'bun:/path/to/cli.js'` (force Bun runtime). If not provided, auto-detects from: `QWEN_CODE_CLI_PATH` env var, `~/.volta/bin/qwen`, `~/.npm-global/bin/qwen`, `/usr/local/bin/qwen`, `~/.local/bin/qwen`, `~/node_modules/.bin/qwen`, `~/.yarn/bin/qwen`. |
|
||||
| `permissionMode` | `'default' \| 'plan' \| 'auto-edit' \| 'yolo'` | `'default'` | Permission mode controlling tool execution approval. See [Permission Modes](#permission-modes) for details. |
|
||||
| `canUseTool` | `CanUseTool` | - | Custom permission handler for tool execution approval. Invoked when a tool requires confirmation. Must respond within 60 seconds or the request will be auto-denied. See [Custom Permission Handler](#custom-permission-handler). |
|
||||
| `canUseTool` | `CanUseTool` | - | Custom permission handler for tool execution approval. Invoked when a tool requires confirmation. Must respond within 30 seconds or the request will be auto-denied. See [Custom Permission Handler](#custom-permission-handler). |
|
||||
| `env` | `Record<string, string>` | - | Environment variables to pass to the Qwen Code process. Merged with the current process environment. |
|
||||
| `mcpServers` | `Record<string, McpServerConfig>` | - | MCP (Model Context Protocol) servers to connect. Supports external servers (stdio/SSE/HTTP) and SDK-embedded servers. External servers are configured with transport options like `command`, `args`, `url`, `httpUrl`, etc. SDK servers use `{ type: 'sdk', name: string, instance: Server }`. |
|
||||
| `abortController` | `AbortController` | - | Controller to cancel the query session. Call `abortController.abort()` to terminate the session and cleanup resources. |
|
||||
@@ -76,12 +76,12 @@ Creates a new query session with the Qwen Code.
|
||||
|
||||
The SDK enforces the following default timeouts:
|
||||
|
||||
| Timeout | Default | Description |
|
||||
| ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `canUseTool` | 1 minute | Maximum time for `canUseTool` callback to respond. If exceeded, the tool request is auto-denied. |
|
||||
| `mcpRequest` | 1 minute | Maximum time for SDK MCP tool calls to complete. |
|
||||
| `controlRequest` | 1 minute | Maximum time for control operations like `initialize()`, `setModel()`, `setPermissionMode()`, and `interrupt()` to complete. |
|
||||
| `streamClose` | 1 minute | Maximum time to wait for initialization to complete before closing CLI stdin in multi-turn mode with SDK MCP servers. |
|
||||
| Timeout | Default | Description |
|
||||
| ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `canUseTool` | 30 seconds | Maximum time for `canUseTool` callback to respond. If exceeded, the tool request is auto-denied. |
|
||||
| `mcpRequest` | 1 minute | Maximum time for SDK MCP tool calls to complete. |
|
||||
| `controlRequest` | 30 seconds | Maximum time for control operations like `initialize()`, `setModel()`, `setPermissionMode()`, and `interrupt()` to complete. |
|
||||
| `streamClose` | 1 minute | Maximum time to wait for initialization to complete before closing CLI stdin in multi-turn mode with SDK MCP servers. |
|
||||
|
||||
You can customize these timeouts via the `timeout` option:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/sdk",
|
||||
"version": "0.1.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"description": "TypeScript SDK for programmatic access to qwen-code CLI",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.mjs",
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* Implements AsyncIterator protocol for message consumption.
|
||||
*/
|
||||
|
||||
const DEFAULT_CAN_USE_TOOL_TIMEOUT = 60_000;
|
||||
const DEFAULT_CAN_USE_TOOL_TIMEOUT = 30_000;
|
||||
const DEFAULT_MCP_REQUEST_TIMEOUT = 60_000;
|
||||
const DEFAULT_CONTROL_REQUEST_TIMEOUT = 60_000;
|
||||
const DEFAULT_CONTROL_REQUEST_TIMEOUT = 30_000;
|
||||
const DEFAULT_STREAM_CLOSE_TIMEOUT = 60_000;
|
||||
|
||||
import { randomUUID } from 'node:crypto';
|
||||
@@ -434,9 +434,8 @@ export class Query implements AsyncIterable<SDKMessage> {
|
||||
try {
|
||||
const canUseToolTimeout =
|
||||
this.options.timeout?.canUseTool ?? DEFAULT_CAN_USE_TOOL_TIMEOUT;
|
||||
let timeoutId: NodeJS.Timeout | undefined;
|
||||
const timeoutPromise = new Promise<never>((_, reject) => {
|
||||
timeoutId = setTimeout(
|
||||
setTimeout(
|
||||
() => reject(new Error('Permission callback timeout')),
|
||||
canUseToolTimeout,
|
||||
);
|
||||
@@ -452,10 +451,6 @@ export class Query implements AsyncIterable<SDKMessage> {
|
||||
timeoutPromise,
|
||||
]);
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
if (result.behavior === 'allow') {
|
||||
return {
|
||||
behavior: 'allow',
|
||||
@@ -794,20 +789,14 @@ export class Query implements AsyncIterable<SDKMessage> {
|
||||
) {
|
||||
const streamCloseTimeout =
|
||||
this.options.timeout?.streamClose ?? DEFAULT_STREAM_CLOSE_TIMEOUT;
|
||||
let timeoutId: NodeJS.Timeout | undefined;
|
||||
|
||||
const timeoutPromise = new Promise<void>((resolve) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
logger.info('streamCloseTimeout resolved');
|
||||
resolve();
|
||||
}, streamCloseTimeout);
|
||||
});
|
||||
|
||||
await Promise.race([this.firstResultReceivedPromise, timeoutPromise]);
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
await Promise.race([
|
||||
this.firstResultReceivedPromise,
|
||||
new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, streamCloseTimeout);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
this.endInput();
|
||||
|
||||
@@ -316,7 +316,7 @@ export interface QueryOptions {
|
||||
/**
|
||||
* Logging level for the SDK.
|
||||
* Controls the verbosity of log messages output by the SDK.
|
||||
* @default 'error'
|
||||
* @default 'info'
|
||||
*/
|
||||
logLevel?: 'debug' | 'info' | 'warn' | 'error';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
|
||||
|
||||
export class SdkLogger {
|
||||
private static config: LoggerConfig = {};
|
||||
private static effectiveLevel: LogLevel = 'error';
|
||||
private static effectiveLevel: LogLevel = 'info';
|
||||
|
||||
static configure(config: LoggerConfig): void {
|
||||
this.config = config;
|
||||
@@ -47,7 +47,7 @@ export class SdkLogger {
|
||||
return 'debug';
|
||||
}
|
||||
|
||||
return 'error';
|
||||
return 'info';
|
||||
}
|
||||
|
||||
private static isValidLogLevel(level: string): boolean {
|
||||
|
||||
@@ -542,16 +542,13 @@ describe('Query', () => {
|
||||
const canUseTool = vi.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => resolve({ behavior: 'allow' }), 15000);
|
||||
setTimeout(() => resolve({ behavior: 'allow' }), 35000); // Exceeds 30s timeout
|
||||
}),
|
||||
);
|
||||
|
||||
const query = new Query(transport, {
|
||||
cwd: '/test',
|
||||
canUseTool,
|
||||
timeout: {
|
||||
canUseTool: 10000,
|
||||
},
|
||||
});
|
||||
|
||||
const controlReq = createControlRequest('can_use_tool', 'perm-req-4');
|
||||
@@ -570,7 +567,7 @@ describe('Query', () => {
|
||||
});
|
||||
}
|
||||
},
|
||||
{ timeout: 15000 },
|
||||
{ timeout: 35000 },
|
||||
);
|
||||
|
||||
await query.close();
|
||||
@@ -1207,12 +1204,7 @@ describe('Query', () => {
|
||||
});
|
||||
|
||||
it('should handle control request timeout', async () => {
|
||||
const query = new Query(transport, {
|
||||
cwd: '/test',
|
||||
timeout: {
|
||||
controlRequest: 10000,
|
||||
},
|
||||
});
|
||||
const query = new Query(transport, { cwd: '/test' });
|
||||
|
||||
// Respond to initialize
|
||||
await vi.waitFor(() => {
|
||||
@@ -1232,7 +1224,7 @@ describe('Query', () => {
|
||||
await expect(interruptPromise).rejects.toThrow(/timeout/i);
|
||||
|
||||
await query.close();
|
||||
}, 15000);
|
||||
}, 35000);
|
||||
|
||||
it('should handle malformed control responses', async () => {
|
||||
const query = new Query(transport, { cwd: '/test' });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code-test-utils",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"private": true,
|
||||
"main": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "qwen-code-vscode-ide-companion",
|
||||
"displayName": "Qwen Code Companion",
|
||||
"description": "Enable Qwen Code with direct access to your VS Code workspace.",
|
||||
"version": "0.4.0",
|
||||
"version": "0.4.0-nightly.20251206.ab228c68",
|
||||
"publisher": "qwenlm",
|
||||
"icon": "assets/icon.png",
|
||||
"repository": {
|
||||
|
||||
Reference in New Issue
Block a user