Skip to content

fix(copilot): respect COPILOT_API_BASE_URL and fix follow-up failing check regressions#664

Open
badMade wants to merge 4 commits into
mainfrom
badmade/propose-fix-for-copilot-base-url-bypass
Open

fix(copilot): respect COPILOT_API_BASE_URL and fix follow-up failing check regressions#664
badMade wants to merge 4 commits into
mainfrom
badmade/propose-fix-for-copilot-base-url-bypass

Conversation

@badMade
Copy link
Copy Markdown
Owner

@badMade badMade commented May 31, 2026

Motivation

  • Prevent operator-configured COPILOT_API_BASE_URL from being bypassed when Copilot credentials come from GH_TOKEN or gh auth token sources.
  • Ensure env-sourced Copilot tokens remain associated with env base-URL overrides while preserving the Copilot token-exchange path.
  • Unblock failing CI checks on this branch by fixing regressions surfaced after the merge update.

Description

  • Seed copilot singleton entries in agent/credential_pool.py now classifies gh auth token explicitly as gh_cli and treats GH_TOKEN (and other env variants) as env:…; it reads the provider's base_url_env_var and applies that value before falling back to the provider inference_base_url when creating pool entries.
  • The env-seeding path in agent/credential_pool.py uses get_copilot_api_token() for Copilot env tokens and stores the resolved API token in the pool entry's access_token.
  • Runtime resolution in hermes_cli/runtime_provider.py now treats Copilot specially: when a pool entry's base_url is empty or equals the provider default, it first prefers model.base_url (if the configured provider matches), then the COPILOT_API_BASE_URL env override (via get_env_value), and only then the provider default.
  • Added regression tests covering GH_TOKEN env seeding, gh auth token seeding, and runtime resolution override behavior in tests/agent/test_credential_pool.py and tests/hermes_cli/test_runtime_provider_resolution.py.
  • Additional failing-check fixes:
    • gateway/run.py: initialize the missing team_id scope in _is_user_authorized to eliminate NameError in authorization paths.
    • gateway/platforms/webhook.py: reject empty/unresolved placeholder webhook secrets during signature validation.
    • gateway/platforms/qqbot/adapter.py: avoid attachment processing for unauthorized QQ C2C traffic.
    • tools/process_registry.py: harden stdin guard handling for empty/malformed approval responses.

Testing

  • Added unit tests: tests/agent/test_credential_pool.py (new Copilot env/gh_cli cases) and tests/hermes_cli/test_runtime_provider_resolution.py (Copilot base_url override cases).
  • Ran targeted regression tests with scripts/run_tests.sh for:
    • Copilot credential/runtime-provider tests
    • Gateway auth regressions (feishu, discord, wecom_callback, unauthorized DM behavior, pre-dispatch, signal)
    • Webhook placeholder signature validation
    • QQ unauthorized C2C attachment handling
    • Process registry stdin guard/EOF behavior
  • Ran ruff check on modified modules (passed).

Codex Task

Copilot AI review requested due to automatic review settings May 31, 2026 22:31
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request ensures that Copilot base URL overrides (such as COPILOT_API_BASE_URL) are correctly respected during credential pool seeding and runtime provider resolution, and updates Copilot token resolution logic. The review feedback suggests simplifying the environment variable resolution in both agent/credential_pool.py and hermes_cli/runtime_provider.py by removing redundant os.getenv fallbacks and preferring .env file lookups during pool seeding to prevent persisting stale inherited environment variables.

Comment thread agent/credential_pool.py
Comment on lines +1278 to +1282
if pconfig and pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

During pool seeding, we should prefer the .env file over os.environ to prevent stale inherited environment variables from being persisted into auth.json (consistent with the fix for NousResearch#18254). Additionally, get_env_value already falls back to .env if not in os.environ, making the or os.getenv(...) redundant.

We can use load_env() (which is already imported) to check the .env file first.

Suggested change
if pconfig and pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
if pconfig and pconfig.base_url_env_var:
env_file = load_env()
env_url = (
env_file.get(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")

Comment on lines +231 to +235
if pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

At runtime, get_env_value already checks os.environ first and then falls back to .env. Therefore, the or os.getenv(...) check is redundant and can be simplified.

            if pconfig.base_url_env_var:
                env_url = (get_env_value(pconfig.base_url_env_var) or "").strip().rstrip("/")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@gemini-code-assist, is this suggestion still valid? If so, what are the steps and line numbers to make this fix?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes, the suggestion remains valid. get_env_value is designed to handle the environment lookup internally, making the explicit os.getenv fallback redundant. You can apply this simplification to hermes_cli/runtime_provider.py at lines 231-235.

Suggested change
if pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
if pconfig.base_url_env_var:
env_url = (get_env_value(pconfig.base_url_env_var) or "").strip().rstrip("/")

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

🔎 Lint report: badmade/propose-fix-for-copilot-base-url-bypass vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8256 on HEAD, 8257 on base (✅ -1)

🆕 New issues (4):

Rule Count
invalid-argument-type 3
unresolved-attribute 1
First entries
run_agent.py:13568: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:7311: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
gateway/platforms/qqbot/adapter.py:1142: [unresolved-attribute] unresolved-attribute: Object of type `Self@_handle_c2c_message` has no attribute `gateway_runner`
run_agent.py:13565: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`

✅ Fixed issues (4):

Rule Count
invalid-argument-type 3
unresolved-reference 1
First entries
run_agent.py:13568: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:7311: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`
gateway/run.py:5544: [unresolved-reference] unresolved-reference: Name `team_id` used when not defined
run_agent.py:13565: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`

Unchanged: 4354 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR ensures operator-configured Copilot base URL overrides (COPILOT_API_BASE_URL) are respected consistently when Copilot credentials are sourced from GH_TOKEN / other env vars or from gh auth token, both during credential-pool seeding and at runtime provider resolution.

Changes:

  • Update Copilot credential-pool seeding to classify token sources more precisely (gh_cli vs env:…), apply COPILOT_API_BASE_URL when creating pool entries, and store the exchanged Copilot API token for env-seeded entries.
  • Update runtime provider resolution for Copilot to prefer (when the pool base URL is empty/default) model.base_url (if configured provider is Copilot), then COPILOT_API_BASE_URL, then the provider default.
  • Add regression tests for GH_TOKEN/env seeding + base URL override behavior and runtime resolution override precedence.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
agent/credential_pool.py Adjusts Copilot seeding source classification and base URL selection; exchanges env Copilot tokens before storing in the pool entry.
hermes_cli/runtime_provider.py Adds Copilot-specific base URL override precedence using config/env/provider-default rules when pool URL is empty/default.
tests/agent/test_credential_pool.py Adds tests for GH_TOKEN and gh auth token pool seeding with COPILOT_API_BASE_URL and API-token exchange.
tests/hermes_cli/test_runtime_provider_resolution.py Adds tests asserting Copilot runtime resolution respects env/config base URL overrides when pool URL is default.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread agent/credential_pool.py
Comment on lines +1277 to +1283
env_url = ""
if pconfig and pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
base_url = env_url or (pconfig.inference_base_url if pconfig else "")
Comment on lines +111 to +115
monkeypatch.setenv("COPILOT_API_BASE_URL", "https://enterprise-proxy.example/copilot/")
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "copilot")
monkeypatch.setattr(rp, "load_pool", lambda provider: _Pool())
monkeypatch.setattr(rp, "_copilot_runtime_api_mode", lambda *a, **k: "chat_completions")

Comment on lines +231 to +235
if pconfig.base_url_env_var:
env_url = (
get_env_value(pconfig.base_url_env_var)
or os.getenv(pconfig.base_url_env_var, "")
).strip().rstrip("/")
@badMade
Copy link
Copy Markdown
Owner Author

badMade commented May 31, 2026

@claude code review

@badMade
Copy link
Copy Markdown
Owner Author

badMade commented May 31, 2026

@jules code review

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

Auto-merge: review received — action required

Review activity detected (6 inline comment(s) by non-author(s); 2 comment(s)/review(s) from review bot(s): gemini-code-assist[bot], copilot-pull-request-reviewer[bot]).

To confirm you have reviewed and accepted the feedback, please add the reviewed label to this PR. Auto-merge will then proceed.

View workflow run

@badMade
Copy link
Copy Markdown
Owner Author

badMade commented Jun 1, 2026

@copilot, fix all failing checks.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Auto-merge: checks failing

The following checks did not pass:

  • test (failure)

Please fix the failing checks before this PR can be merged.

View workflow run

Copy link
Copy Markdown

Copilot AI commented Jun 1, 2026

@copilot, fix all failing checks.

Implemented fixes for the failing checks in commit e8d4217.

Copilot AI changed the title fix(copilot): respect COPILOT_API_BASE_URL for GH_TOKEN and gh auth token fix(copilot): respect COPILOT_API_BASE_URL and fix follow-up failing check regressions Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants