mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
feat(cli): add explicit proxy option in cli (#2526)
Co-authored-by: Dcatfly <dcatfly@gmail.com>
This commit is contained in:
@@ -34,6 +34,7 @@ vi.mock('node:readline');
|
||||
|
||||
const mockConfig = {
|
||||
getNoBrowser: () => false,
|
||||
getProxy: () => 'http://test.proxy.com:8080',
|
||||
} as unknown as Config;
|
||||
|
||||
// Mock fetch globally
|
||||
@@ -175,6 +176,7 @@ describe('oauth2', () => {
|
||||
it('should perform login with user code', async () => {
|
||||
const mockConfigWithNoBrowser = {
|
||||
getNoBrowser: () => true,
|
||||
getProxy: () => 'http://test.proxy.com:8080',
|
||||
} as unknown as Config;
|
||||
|
||||
const mockCodeVerifier = {
|
||||
|
||||
@@ -73,6 +73,9 @@ export async function getOauthClient(
|
||||
const client = new OAuth2Client({
|
||||
clientId: OAUTH_CLIENT_ID,
|
||||
clientSecret: OAUTH_CLIENT_SECRET,
|
||||
transporterOptions: {
|
||||
proxy: config.getProxy(),
|
||||
},
|
||||
});
|
||||
|
||||
client.on('tokens', async (tokens: Credentials) => {
|
||||
|
||||
@@ -68,6 +68,7 @@ describe('createContentGeneratorConfig', () => {
|
||||
getModel: vi.fn().mockReturnValue('gemini-pro'),
|
||||
setModel: vi.fn(),
|
||||
flashFallbackHandler: vi.fn(),
|
||||
getProxy: vi.fn(),
|
||||
} as unknown as Config;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -50,6 +50,7 @@ export type ContentGeneratorConfig = {
|
||||
apiKey?: string;
|
||||
vertexai?: boolean;
|
||||
authType?: AuthType | undefined;
|
||||
proxy?: string | undefined;
|
||||
};
|
||||
|
||||
export function createContentGeneratorConfig(
|
||||
@@ -67,6 +68,7 @@ export function createContentGeneratorConfig(
|
||||
const contentGeneratorConfig: ContentGeneratorConfig = {
|
||||
model: effectiveModel,
|
||||
authType,
|
||||
proxy: config?.getProxy(),
|
||||
};
|
||||
|
||||
// If we are using Google auth or we are in Cloud Shell, there is nothing else to validate for now
|
||||
@@ -83,11 +85,8 @@ export function createContentGeneratorConfig(
|
||||
getEffectiveModel(
|
||||
contentGeneratorConfig.apiKey,
|
||||
contentGeneratorConfig.model,
|
||||
).then((newModel) => {
|
||||
if (newModel !== contentGeneratorConfig.model) {
|
||||
config.flashFallbackHandler?.(contentGeneratorConfig.model, newModel);
|
||||
}
|
||||
});
|
||||
contentGeneratorConfig.proxy,
|
||||
);
|
||||
|
||||
return contentGeneratorConfig;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { setGlobalDispatcher, ProxyAgent } from 'undici';
|
||||
import {
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
@@ -20,6 +21,7 @@ import {
|
||||
export async function getEffectiveModel(
|
||||
apiKey: string,
|
||||
currentConfiguredModel: string,
|
||||
proxy?: string,
|
||||
): Promise<string> {
|
||||
if (currentConfiguredModel !== DEFAULT_GEMINI_MODEL) {
|
||||
// Only check if the user is trying to use the specific pro model we want to fallback from.
|
||||
@@ -43,6 +45,9 @@ export async function getEffectiveModel(
|
||||
const timeoutId = setTimeout(() => controller.abort(), 2000); // 500ms timeout for the request
|
||||
|
||||
try {
|
||||
if (proxy) {
|
||||
setGlobalDispatcher(new ProxyAgent(proxy));
|
||||
}
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
import { Buffer } from 'buffer';
|
||||
import * as https from 'https';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
|
||||
import {
|
||||
StartSessionEvent,
|
||||
EndSessionEvent,
|
||||
@@ -132,12 +134,18 @@ export class ClearcutLogger {
|
||||
headers: { 'Content-Length': Buffer.byteLength(body) },
|
||||
};
|
||||
const bufs: Buffer[] = [];
|
||||
const req = https.request(options, (res) => {
|
||||
res.on('data', (buf) => bufs.push(buf));
|
||||
res.on('end', () => {
|
||||
resolve(Buffer.concat(bufs));
|
||||
});
|
||||
});
|
||||
const req = https.request(
|
||||
{
|
||||
...options,
|
||||
agent: this.getProxyAgent(),
|
||||
},
|
||||
(res) => {
|
||||
res.on('data', (buf) => bufs.push(buf));
|
||||
res.on('end', () => {
|
||||
resolve(Buffer.concat(bufs));
|
||||
});
|
||||
},
|
||||
);
|
||||
req.on('error', (e) => {
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.log('Clearcut POST request error: ', e);
|
||||
@@ -499,6 +507,18 @@ export class ClearcutLogger {
|
||||
});
|
||||
}
|
||||
|
||||
getProxyAgent() {
|
||||
const proxyUrl = this.config?.getProxy();
|
||||
if (!proxyUrl) return undefined;
|
||||
// undici which is widely used in the repo can only support http & https proxy protocol,
|
||||
// https://github.com/nodejs/undici/issues/2224
|
||||
if (proxyUrl.startsWith('http')) {
|
||||
return new HttpsProxyAgent(proxyUrl);
|
||||
} else {
|
||||
throw new Error('Unsupported proxy type');
|
||||
}
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
const event = new EndSessionEvent(this.config);
|
||||
this.logEndSessionEvent(event);
|
||||
|
||||
@@ -13,6 +13,7 @@ describe('WebFetchTool', () => {
|
||||
const mockConfig = {
|
||||
getApprovalMode: vi.fn(),
|
||||
setApprovalMode: vi.fn(),
|
||||
getProxy: vi.fn(),
|
||||
} as unknown as Config;
|
||||
|
||||
describe('shouldConfirmExecute', () => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Config, ApprovalMode } from '../config/config.js';
|
||||
import { getResponseText } from '../utils/generateContentResponseUtilities.js';
|
||||
import { fetchWithTimeout, isPrivateIp } from '../utils/fetch.js';
|
||||
import { convert } from 'html-to-text';
|
||||
import { ProxyAgent, setGlobalDispatcher } from 'undici';
|
||||
|
||||
const URL_FETCH_TIMEOUT_MS = 10000;
|
||||
const MAX_CONTENT_LENGTH = 100000;
|
||||
@@ -81,6 +82,10 @@ export class WebFetchTool extends BaseTool<WebFetchToolParams, ToolResult> {
|
||||
type: Type.OBJECT,
|
||||
},
|
||||
);
|
||||
const proxy = config.getProxy();
|
||||
if (proxy) {
|
||||
setGlobalDispatcher(new ProxyAgent(proxy as string));
|
||||
}
|
||||
}
|
||||
|
||||
private async executeFallback(
|
||||
|
||||
Reference in New Issue
Block a user