mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-16 20:24:50 +00:00
fix(core): avoid passing undici agent to Anthropic SDK
Anthropic's Node client uses node-fetch, which expects a Node http(s).Agent. Stop providing undici's Dispatcher as httpAgent; only set httpAgent when a proxy is configured (via https-proxy-agent), otherwise let the SDK use its default.
This commit is contained in:
parent
3c2e29931c
commit
48ca2d043e
2 changed files with 51 additions and 40 deletions
|
|
@ -30,6 +30,19 @@ vi.mock('undici', () => {
|
|||
};
|
||||
});
|
||||
|
||||
vi.mock('https-proxy-agent', () => {
|
||||
class MockHttpsProxyAgent {
|
||||
proxyUrl: string;
|
||||
constructor(proxyUrl: string) {
|
||||
this.proxyUrl = proxyUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
HttpsProxyAgent: MockHttpsProxyAgent,
|
||||
};
|
||||
});
|
||||
|
||||
describe('buildRuntimeFetchOptions (node runtime)', () => {
|
||||
it('disables undici timeouts for Agent in OpenAI options', () => {
|
||||
const result = buildRuntimeFetchOptions('openai');
|
||||
|
|
@ -60,17 +73,20 @@ describe('buildRuntimeFetchOptions (node runtime)', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('returns httpAgent with disabled timeouts for Anthropic options', () => {
|
||||
it('returns empty object for Anthropic without proxy (uses SDK default agent)', () => {
|
||||
const result = buildRuntimeFetchOptions('anthropic');
|
||||
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it('returns HttpsProxyAgent for Anthropic with proxy', () => {
|
||||
const result = buildRuntimeFetchOptions('anthropic', 'http://proxy.local');
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result && 'httpAgent' in result).toBe(true);
|
||||
|
||||
const httpAgent = (result as { httpAgent?: { options?: UndiciOptions } })
|
||||
const httpAgent = (result as { httpAgent?: { proxyUrl?: string } })
|
||||
.httpAgent;
|
||||
expect(httpAgent?.options).toMatchObject({
|
||||
headersTimeout: 0,
|
||||
bodyTimeout: 0,
|
||||
});
|
||||
expect(httpAgent?.proxyUrl).toBe('http://proxy.local');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Agent, ProxyAgent, type Dispatcher } from 'undici';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
|
||||
/**
|
||||
* JavaScript runtime type
|
||||
|
|
@ -113,48 +114,42 @@ export function buildRuntimeFetchOptions(
|
|||
}
|
||||
|
||||
case 'node': {
|
||||
// Node.js: Use ProxyAgent when proxy is configured, otherwise Agent.
|
||||
// undici timeouts are disabled to let SDK timeout control the request.
|
||||
try {
|
||||
const dispatcher = createDispatcher(proxyUrl);
|
||||
if (sdkType === 'openai') {
|
||||
return {
|
||||
dispatcher,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
httpAgent: dispatcher,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// If undici is not available, return appropriate default
|
||||
if (sdkType === 'openai') {
|
||||
// Node.js: Use appropriate agent based on SDK type.
|
||||
// OpenAI SDK uses undici internally, so we use undici Dispatcher.
|
||||
// Anthropic SDK uses node-fetch internally, so we use Node.js-compatible agents.
|
||||
if (sdkType === 'openai') {
|
||||
try {
|
||||
const dispatcher = createDispatcher(proxyUrl);
|
||||
return { dispatcher };
|
||||
} catch {
|
||||
return undefined;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
// Anthropic SDK: use HttpsProxyAgent when proxy is set,
|
||||
// otherwise let SDK use its default agentkeepalive agent.
|
||||
// The SDK's timeout option controls request-level timeouts.
|
||||
if (proxyUrl) {
|
||||
return { httpAgent: new HttpsProxyAgent(proxyUrl) };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
default: {
|
||||
// Unknown runtime: Use ProxyAgent when proxy is configured, otherwise Agent.
|
||||
try {
|
||||
const dispatcher = createDispatcher(proxyUrl);
|
||||
if (sdkType === 'openai') {
|
||||
return {
|
||||
dispatcher,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
httpAgent: dispatcher,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
if (sdkType === 'openai') {
|
||||
// Unknown runtime: treat as Node.js-like environment.
|
||||
if (sdkType === 'openai') {
|
||||
try {
|
||||
const dispatcher = createDispatcher(proxyUrl);
|
||||
return { dispatcher };
|
||||
} catch {
|
||||
return undefined;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
// Anthropic SDK: use HttpsProxyAgent when proxy is set
|
||||
if (proxyUrl) {
|
||||
return { httpAgent: new HttpsProxyAgent(proxyUrl) };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue