Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';

vi.mock('vscode', () => ({
workspace: {
getConfiguration: vi.fn(),
},
}));

import { QwenConnectionHandler } from './qwenConnectionHandler.js';
import type { AcpConnection } from './acpConnection.js';

describe('QwenConnectionHandler', () => {
let handler: QwenConnectionHandler;
let mockConnection: AcpConnection;
let mockGetConfiguration: ReturnType<typeof vi.fn>;

beforeEach(async () => {
const vscode = await import('vscode');
mockGetConfiguration = vscode.workspace.getConfiguration as ReturnType<
typeof vi.fn
>;
mockGetConfiguration.mockReset();

handler = new QwenConnectionHandler();
mockConnection = {
connect: vi.fn().mockResolvedValue(undefined),
newSession: vi.fn().mockResolvedValue({ sessionId: 'test-session' }),
authenticate: vi.fn().mockResolvedValue({}),
} as unknown as AcpConnection;
});

afterEach(() => {
vi.clearAllMocks();
});

describe('proxy configuration', () => {
it('passes --proxy argument when http.proxy is set', async () => {
mockGetConfiguration.mockReturnValue({
get: (key: string) => {
if (key === 'proxy') {
return 'http://proxy.example.com:8080';
}
return undefined;
},
});

await handler.connect(mockConnection, '/workspace', '/path/to/cli.js');

expect(mockConnection.connect).toHaveBeenCalled();
const connectArgs = (mockConnection.connect as ReturnType<typeof vi.fn>)
.mock.calls[0];
expect(connectArgs[2]).toContain('--proxy');
expect(connectArgs[2]).toContain('http://proxy.example.com:8080');
});

it('passes --proxy argument when https.proxy is set (fallback)', async () => {
mockGetConfiguration.mockReturnValue({
get: (key: string) => {
if (key === 'proxy') {
return undefined;
}
if (key === 'https.proxy') {
return 'http://https-proxy.example.com:8080';
}
return undefined;
},
});

await handler.connect(mockConnection, '/workspace', '/path/to/cli.js');

expect(mockConnection.connect).toHaveBeenCalled();
const connectArgs = (mockConnection.connect as ReturnType<typeof vi.fn>)
.mock.calls[0];
expect(connectArgs[2]).toContain('--proxy');
expect(connectArgs[2]).toContain('http://https-proxy.example.com:8080');
});

it('prefers http.proxy over https.proxy', async () => {
mockGetConfiguration.mockReturnValue({
get: (key: string) => {
if (key === 'proxy') {
return 'http://http-proxy.example.com:8080';
}
if (key === 'https.proxy') {
return 'http://https-proxy.example.com:8080';
}
return undefined;
},
});

await handler.connect(mockConnection, '/workspace', '/path/to/cli.js');

const connectArgs = (mockConnection.connect as ReturnType<typeof vi.fn>)
.mock.calls[0];
expect(connectArgs[2]).toContain('http://http-proxy.example.com:8080');
expect(connectArgs[2]).not.toContain(
'http://https-proxy.example.com:8080',
);
});

it('does not pass --proxy argument when no proxy is configured', async () => {
mockGetConfiguration.mockReturnValue({
get: () => undefined,
});

await handler.connect(mockConnection, '/workspace', '/path/to/cli.js');

const connectArgs = (mockConnection.connect as ReturnType<typeof vi.fn>)
.mock.calls[0];
expect(connectArgs[2]).not.toContain('--proxy');
});

it('does not pass --proxy argument when proxy is empty string', async () => {
mockGetConfiguration.mockReturnValue({
get: (key: string) => {
if (key === 'proxy') {
return '';
}
return undefined;
},
});

await handler.connect(mockConnection, '/workspace', '/path/to/cli.js');

const connectArgs = (mockConnection.connect as ReturnType<typeof vi.fn>)
.mock.calls[0];
expect(connectArgs[2]).not.toContain('--proxy');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Handles Qwen Agent connection establishment, authentication, and session creation
*/

import * as vscode from 'vscode';
import type { AcpConnection } from './acpConnection.js';
import { isAuthenticationRequiredError } from '../utils/authErrors.js';
import { authMethod } from '../types/acpTypes.js';
Expand Down Expand Up @@ -73,6 +74,16 @@ export class QwenConnectionHandler {

// Build extra CLI arguments (only essential parameters)
const extraArgs: string[] = [];
const httpConfig = vscode.workspace.getConfiguration('http');
const proxyUrl =
httpConfig.get<string>('proxy') || httpConfig.get<string>('https.proxy');
if (proxyUrl) {
extraArgs.push('--proxy', proxyUrl);
console.log(
'[QwenAgentManager] Using proxy from VSCode settings:',
proxyUrl,
);
}

await connection.connect(cliEntryPath!, workingDir, extraArgs);

Expand Down
Loading