fix(interactive): configure Docker sandbox networking for protocol tag retry test (#6684) (#6689)

The protocol-tags-interactive.test.ts started the fake OpenAI server
on 127.0.0.1 without Docker-aware host options, making it unreachable
from inside the Docker sandbox container. The CLI running in the
container tried to connect to 127.0.0.1 which resolved to the
container's own loopback, not the host where the test server listens.

Bind the fake server to 0.0.0.0 and advertise host.docker.internal
as the base URL host when QWEN_SANDBOX is docker or podman, matching
the established pattern in tool-control.test.ts. Also set NO_PROXY to
include host.docker.internal so the CLI does not route sandbox model
requests through an HTTP proxy.

Co-authored-by: qwen-autofix[bot] <qwen-autofix[bot]@users.noreply.github.com>
This commit is contained in:
qwen-code-dev-bot 2026-07-11 03:06:55 +08:00 committed by GitHub
parent ebd83f1d2d
commit b2601c8613
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -12,52 +12,85 @@ import {
} from '../fake-openai-server.js';
import { TestRig, type } from '../test-helper.js';
const SANDBOX_MODE = process.env['QWEN_SANDBOX']?.toLowerCase().trim();
const IS_CONTAINER_SANDBOX =
SANDBOX_MODE === 'docker' || SANDBOX_MODE === 'podman';
describe('Interactive protocol tag retry guard', () => {
let fakeServer: FakeOpenAIServer | undefined;
let rig: TestRig;
let savedNoProxy: string | undefined;
let savedNoProxyLower: string | undefined;
beforeEach(() => {
rig = new TestRig();
if (IS_CONTAINER_SANDBOX) {
savedNoProxy = process.env['NO_PROXY'];
savedNoProxyLower = process.env['no_proxy'];
const noProxy = '127.0.0.1,localhost,host.docker.internal';
process.env['NO_PROXY'] = noProxy;
process.env['no_proxy'] = noProxy;
}
});
afterEach(async () => {
await fakeServer?.close();
fakeServer = undefined;
if (IS_CONTAINER_SANDBOX) {
if (savedNoProxy !== undefined) {
process.env['NO_PROXY'] = savedNoProxy;
} else {
delete process.env['NO_PROXY'];
}
if (savedNoProxyLower !== undefined) {
process.env['no_proxy'] = savedNoProxyLower;
} else {
delete process.env['no_proxy'];
}
}
await rig.cleanup();
});
it.skipIf(process.platform === 'win32')(
'retries protocol leaks across SSE disconnect and completed streams',
async () => {
fakeServer = await startFakeOpenAIServer(({ requestIndex }) => {
if (requestIndex === 0) {
return {
contentChunks: [
'<analysis>hidden before disconnect',
'</analysis><summary>WRONG_FIRST_ATTEMPT</summary>',
],
disconnectAfterContentChunks: 1,
};
}
fakeServer = await startFakeOpenAIServer(
({ requestIndex }) => {
if (requestIndex === 0) {
return {
contentChunks: [
'<analysis>hidden before disconnect',
'</analysis><summary>WRONG_FIRST_ATTEMPT</summary>',
],
disconnectAfterContentChunks: 1,
};
}
if (requestIndex === 1) {
return {
contentChunks: [
'<analysis>hidden completed attempt</analysis>',
'<summary>WRONG_COMPLETED_SUMMARY</summary>',
],
};
}
if (requestIndex === 1) {
return {
contentChunks: [
'<analysis>hidden completed attempt</analysis>',
'<summary>WRONG_COMPLETED_SUMMARY</summary>',
],
};
}
return {
contentChunks: ['VISIBLE_TMUX_RETRY_RESPONSE_DONE'],
usage: {
prompt_tokens: 20,
completion_tokens: 8,
total_tokens: 28,
},
};
});
return {
contentChunks: ['VISIBLE_TMUX_RETRY_RESPONSE_DONE'],
usage: {
prompt_tokens: 20,
completion_tokens: 8,
total_tokens: 28,
},
};
},
IS_CONTAINER_SANDBOX
? {
listenHost: '0.0.0.0',
baseUrlHost: 'host.docker.internal',
}
: undefined,
);
await rig.setup('interactive-protocol-tag-filtering-http-retry', {
settings: {