Skip to content

fix(config): support QWEN_CODE_API_TIMEOUT_MS across OAuth and non-OAuth paths#3629

Merged
wenshao merged 3 commits into
QwenLM:mainfrom
B-A-M-N:fix/configurable-api-timeout
Apr 26, 2026
Merged

fix(config): support QWEN_CODE_API_TIMEOUT_MS across OAuth and non-OAuth paths#3629
wenshao merged 3 commits into
QwenLM:mainfrom
B-A-M-N:fix/configurable-api-timeout

Conversation

@B-A-M-N

@B-A-M-N B-A-M-N commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds QWEN_CODE_API_TIMEOUT_MS as an environment override for model generation timeout.

This is intended for slow local or OpenAI-compatible backends where editing settings.json is inconvenient.

What changed

  • Supports QWEN_CODE_API_TIMEOUT_MS timeout override

  • Preserves precedence:

    modelProvider > env var > settings > default

  • Applies the override to both:

    • standard/non-OAuth config resolution
    • AuthType.QWEN_OAUTH config resolution
  • Floors float values to integer milliseconds

  • Ignores invalid, zero, negative, or non-numeric values

  • Keeps default behavior unchanged when the env var is not set

Review feedback addressed

This updates the original implementation based on review feedback:

  • Fixed the OAuth-path bug where resolveModelConfig() returned early before the env override was applied
  • Added Qwen OAuth coverage so QWEN_CODE_API_TIMEOUT_MS is tested against the default auth path
  • Normalized timeout parsing with integer millisecond handling
  • Added edge-case coverage for invalid values, negative values, whitespace-padded values, large values, and precedence behavior

Validation

  • npx vitest run packages/core/src/models/modelConfigResolver.test.ts
  • npm run lint
  • full relevant test coverage passes locally

Scope / risk

Low risk. This only changes timeout resolution when QWEN_CODE_API_TIMEOUT_MS is explicitly provided.

No breaking changes.

Adds support for QWEN_CODE_API_TIMEOUT_MS as an environment override
for model generation timeout.

Qwen Code already supports timeout configuration via:
  settings.model.generationConfig.timeout

This change introduces an env-based override for users running slow
local/OpenAI-compatible backends where editing config is less convenient.

Precedence: modelProvider > env var > settings > default (120000ms)

Behavior:
- Valid positive env values override configured timeout
- Invalid values are ignored
- Default behavior remains unchanged (applied in buildClient())

Note: The 5-minute timeout reported in QwenLM#1045 originally came from
undici's default bodyTimeout, which is now disabled (bodyTimeout:0).
The modelConfigResolver default is 120000ms (2 minutes).

Includes unit tests covering precedence and validation.

Closes QwenLM#1045

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR successfully implements the QWEN_CODE_API_TIMEOUT_MS environment variable override for most authentication types. However, there are a few minor items to address for consistency and robustness, particularly regarding the QWEN_OAUTH code path.\n\n_— Gemini CLI /review_

sources,
);

// ---- Env override: QWEN_CODE_API_TIMEOUT_MS ----

@wenshao wenshao Apr 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The QWEN_CODE_API_TIMEOUT_MS override logic here is skipped for QWEN_OAUTH due to the early return at the start of resolveModelConfig. Consider moving this logic or applying it within resolveQwenOAuthConfig for consistency across all auth types.\n\n_— Gemini CLI /review_

const envTimeout = env['QWEN_CODE_API_TIMEOUT_MS'];
if (envTimeout !== undefined) {
const parsed = Number(envTimeout);
if (Number.isFinite(parsed) && parsed > 0) {

@wenshao wenshao Apr 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Nice to have] Use Math.floor(Number(envTimeout)) or parseInt(envTimeout, 10) to ensure the timeout value is an integer, which is the standard format for millisecond durations.\n\n_— Gemini CLI /review_

expect(result.config.timeout).toBe(60000);
expect(result.sources['timeout'].kind).toBe('modelProviders');
});

@wenshao wenshao Apr 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Add a test case to verify that QWEN_CODE_API_TIMEOUT_MS correctly overrides settings when authType is AuthType.QWEN_OAUTH. This would have helped catch the missing support in the implementation.\n\n_— Gemini CLI /review_

@@ -247,6 +247,24 @@ export function resolveModelConfig(
sources,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] The timeout env override is only applied in the non-OAuth path because resolveModelConfig() returns early for AuthType.QWEN_OAUTH before reaching this new block. resolveQwenOAuthConfig() never reads input.env, so Qwen OAuth users still cannot override API timeouts with QWEN_CODE_API_TIMEOUT_MS.

Please move this override into shared generation-config resolution used by both paths, preserving modelProvider > env > settings, and add a Qwen OAuth test for the env timeout override.

— gpt-5.5 via Qwen Code /review

sources,
);

// ---- Env override: QWEN_CODE_API_TIMEOUT_MS ----

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] This override is applied only after the AuthType.QWEN_OAUTH early return above, so QWEN_CODE_API_TIMEOUT_MS is ignored for Qwen OAuth sessions. That means the new env override does not work on the default Qwen auth path, even though the downstream provider can consume config.timeout.

Please apply the same env-timeout merge in resolveQwenOAuthConfig() as well, or factor this logic into a shared helper used by both resolver paths after resolveGenerationConfig(), while preserving modelProvider > env > settings precedence.

— gpt-5.5 via Qwen Code /review

wenshao
wenshao previously approved these changes Apr 26, 2026

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — gpt-5.5 via Qwen Code /review

Covers: large timeout values, whitespace-padded env values,
negative env values, and reinforces provider > env > settings precedence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@B-A-M-N B-A-M-N force-pushed the fix/configurable-api-timeout branch from 005d822 to 0a5b96d Compare April 26, 2026 15:46
Adds support for QWEN_CODE_API_TIMEOUT_MS as an environment
override for model generation timeout.

Closes QwenLM#13

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@B-A-M-N B-A-M-N force-pushed the fix/configurable-api-timeout branch from 0a5b96d to 5eb2406 Compare April 26, 2026 15:58
// Regression: when settings.model.name is set but doesn't match any
// provider, the code should NOT fall through to OPENAI_MODEL/QWEN_MODEL.
// The env-matched provider should only supply metadata when no model is requested.
const mockSettings = makeMockSettings({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] The new regression test is outside the describe('modelConfigUtils', ...) block where makeMockSettings is scoped. This makes npm run typecheck fail with TS2552: Cannot find name 'makeMockSettings', and the focused vitest run fails with ReferenceError: makeMockSettings is not defined. Move this test inside the existing describe('resolveCliGenerationConfig', ...) block, or hoist makeMockSettings to module scope.

— gpt-5.5 via Qwen Code /review

@B-A-M-N B-A-M-N changed the title feat(config): support API timeout env override fix(config): support QWEN_CODE_API_TIMEOUT_MS across OAuth and non-OAuth paths Apr 26, 2026
@B-A-M-N

B-A-M-N commented Apr 26, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up note: I've created a refactor PR (#3651, now closed) to dedupe the duplicated QWEN_CODE_API_TIMEOUT_MS logic into a shared applyTimeoutEnvOverride() helper. Realized this should be recreated after this PR merges to main rather than being based on the feature branch. Will open a clean refactor PR once #3629 lands.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — gpt-5.5 via Qwen Code /review

@wenshao wenshao merged commit 70127b5 into QwenLM:main Apr 26, 2026
24 of 25 checks passed
B-A-M-N added a commit to B-A-M-N/qwen-code that referenced this pull request Apr 27, 2026
…Override helper

Deduplicates the timeout env override logic that was duplicated in
resolveModelConfig() and resolveQwenOAuthConfig() after PR QwenLM#3629 merged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
…uth paths (QwenLM#3629)

* feat(config): support API timeout env override

Adds support for QWEN_CODE_API_TIMEOUT_MS as an environment override
for model generation timeout.

Qwen Code already supports timeout configuration via:
  settings.model.generationConfig.timeout

This change introduces an env-based override for users running slow
local/OpenAI-compatible backends where editing config is less convenient.

Precedence: modelProvider > env var > settings > default (120000ms)

Behavior:
- Valid positive env values override configured timeout
- Invalid values are ignored
- Default behavior remains unchanged (applied in buildClient())

Note: The 5-minute timeout reported in QwenLM#1045 originally came from
undici's default bodyTimeout, which is now disabled (bodyTimeout:0).
The modelConfigResolver default is 120000ms (2 minutes).

Includes unit tests covering precedence and validation.

Closes QwenLM#1045

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(core): add edge-case tests for QWEN_CODE_API_TIMEOUT_MS

Covers: large timeout values, whitespace-padded env values,
negative env values, and reinforces provider > env > settings precedence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(config): support QWEN_CODE_API_TIMEOUT_MS override

Adds support for QWEN_CODE_API_TIMEOUT_MS as an environment
override for model generation timeout.

Closes QwenLM#13

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants