Skip to content

fix(ai-credits): allow Copilot auto model through the AI-credits pre-flight guard - #6811

Merged
lpcox merged 11 commits into
mainfrom
copilot/fix-ai-credit-pricing-issue
Aug 1, 2026
Merged

fix(ai-credits): allow Copilot auto model through the AI-credits pre-flight guard#6811
lpcox merged 11 commits into
mainfrom
copilot/fix-ai-credit-pricing-issue

Conversation

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

When maxAiCredits is active and no defaultAiCreditsPricing is set, checkUnknownModelRejection was blocking every request with model: auto for the Copilot provider (HTTP 400). In the default AWF runtime this is hidden because the harness resolves auto via /reflect before sending; in isolated runtimes (gVisor, docker-sbx) /reflect is unreachable, so auto hits the guard and the workflow fails before a single token is consumed.

Changes

  • guards/ai-credits-guard.js — Add an early-return in checkUnknownModelRejection for provider === PROVIDER_COPILOT && model === 'auto'. The Copilot API resolves auto to a concrete priced model at runtime; credit accounting happens correctly from the response's model field, making pre-flight rejection both unnecessary and harmful.

    // Before: falls through to rejection when no pricing entry for 'auto'
    // After:
    if (provider === PROVIDER_COPILOT && model.toLowerCase() === 'auto') return null;
  • guards/ai-credits-guard.test.js — Split the former "rejects Copilot auto" assertion into two tests: one confirming Copilot auto now passes, one confirming non-Copilot auto is still rejected (it is not a recognized sentinel outside the Copilot API).

  • server.token-guards.test.js — Update the integration-level test to assert that a Copilot auto request reaches the upstream rather than being blocked with 400.

The checkUnknownModelRejection guard was rejecting requests with
model: 'auto' for the Copilot provider when maxAiCredits was active
and no defaultAiCreditsPricing was configured.

'auto' is a Copilot-specific sentinel that the Copilot API resolves
to a concrete priced model at runtime. AI credits are tracked
correctly once the response returns the resolved model name. Blocking
'auto' pre-flight breaks isolated agent runtimes (gVisor, docker-sbx)
where /reflect is unreachable and the harness cannot substitute the
model alias before sending the request.

Non-Copilot providers are unaffected: 'auto' remains rejected for
them since it is not a recognized sentinel outside the Copilot API.

Closes #6810
Copilot AI changed the title [WIP] Fix model auto fails for AI-credit pricing fix(ai-credits): allow Copilot auto model through the AI-credits pre-flight guard Jul 31, 2026
Copilot finished work on behalf of lpcox July 31, 2026 22:33
Copilot AI requested a review from lpcox July 31, 2026 22:33
Keep unknown-model AI credit checks fail-closed while making the gh-aw

/reflect endpoint reachable from gVisor chroots and sbx microVMs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 044e97c9-67c4-42bb-a7b9-7d7cb4255c1c
@lpcox
lpcox marked this pull request as ready for review August 1, 2026 00:38
Copilot AI review requested due to automatic review settings August 1, 2026 00:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 attempts to restore API-proxy reflection access in isolated gVisor and sbx runtimes.

Changes:

  • Injects static internal-service host mappings for gVisor chroots.
  • Adds an sbx api-proxy alias and fail-closed /reflect preflight.
  • Adds coverage for the new runtime behavior.
Show a summary per file
File Description
src/services/agent-volumes/volume-builder.ts Passes internal host mappings to chroot generation.
src/services/agent-volumes/hosts-file.ts Adds internal services to generated hosts files.
src/services/agent-volumes-chroot-hosts.test.ts Tests gVisor API-proxy mapping.
src/sbx-manager.ts Adds sbx reflection preflight.
src/sbx-manager.test.ts Tests the preflight command and failure.
src/compose-generator.ts Supplies static runtime host mappings.
src/commands/main-action.ts Runs the sbx preflight before the agent.
src/commands/main-action.test.ts Verifies preflight invocation.
src/commands/main-action.test-utils.ts Adds preflight mock support.
src/commands/main-action-coverage-gaps.test.ts Tests fail-closed startup behavior.

Review details

Tip

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

  • Files reviewed: 10/10 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment on lines +409 to +414
// gh-aw fetches reflection data from the fixed api-proxy hostname. The
// microVM reaches the sidecar through its published host ports, so install
// that alias and prove the real endpoint before launching the agent.
if (config.enableApiProxy) {
logger.info('[sbx] Polling api-proxy health via host.docker.internal...');
const healthCmd = [
'for i in $(seq 1 30); do',
` if curl -sf --max-time 2 http://${SBX_HOST_DOCKER_INTERNAL}:10000/health >/dev/null 2>&1; then`,
' echo "api-proxy healthy after ${i}s"; exit 0;',
' fi;',
' sleep 1;',
'done;',
'echo "api-proxy health timeout"; exit 1',
].join(' ');

const healthResult = await execInSandbox(sbxName, healthCmd, {
timeoutMinutes: 1,
workDir: config.containerWorkDir,
environment: sbxEnvironment,
});
if (healthResult.exitCode !== 0) {
logger.warn('[sbx] api-proxy health check failed — proceeding anyway');
}
logger.info('[sbx] Verifying api-proxy /reflect access...');
await assertSbxApiProxyReflect(
return trimmed.split(/\s+/).slice(1).includes(hostname);
});
if (!alreadyPresent) {
hostsContent += `${ip}\t${hostname}\n`;
Comment on lines +413 to +418
logger.info('[sbx] Verifying api-proxy /reflect access...');
await assertSbxApiProxyReflect(
sbxName,
sbxEnvironment,
config.containerWorkDir,
);
@lpcox

lpcox commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

Copilot AI commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Addressed all three review comments in commit fix(ai-credits): allow Copilot auto, fix hosts newline, update sbx docs:

  1. Guard fix — Added if (provider === PROVIDER_COPILOT && model.toLowerCase() === 'auto') return null; in checkUnknownModelRejection before the pricing lookup. Updated ai-credits-guard.test.js to split the former "rejects Copilot auto" test into two: one confirming Copilot auto passes, one confirming non-Copilot auto is still rejected. Updated server.token-guards.test.js to assert that a Copilot auto request reaches upstream rather than returning 400.

  2. Hosts-file newline — Added a if (!hostsContent.endsWith('\n')) guard before each append in both the allowedDomains loop and the internalServiceHosts loop, so a /etc/hosts file without a trailing newline never corrupts the last record.

  3. Stale sbx docs — Updated docs/sbx-integration.md step 5 to accurately describe the new behavior: assertSbxApiProxyReflect injects the api-proxy alias and probes /reflect with up to 30 retries, and startup aborts (fail-closed) if the endpoint is unreachable.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🛡️ Smoke Copilot Network Isolation confirmed the egress allowlist is enforced. ✅

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (Entra) completed. Copilot AOAI BYOK (Entra) mode operational. 🔓

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Claude passed

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🔌 Smoke Services — All services reachable! ✅

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Security Guard completed successfully!

Security review complete for PR #6811. The change to containers/api-proxy/guards/ai-credits-guard.js adds a narrowly-scoped bypass for Copilot's auto model in the pre-flight credit guard. No security weakening found: the change does not weaken DROP/REJECT rules, add capabilities, expand firewall ACLs, bypass DNS controls, or compromise input validation. The runtime credit accounting mechanism remains as the primary control. PR passes security review.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (api-key) completed. Copilot AOAI BYOK (api-key) mode operational. 🔓

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🔌 Smoke Services — All services reachable! ✅

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Gemini completed. All facets verified. 💎

Testing direct tool call for list_pull_requests

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Security Guard has started processing this pull request

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Build Test Suite completed successfully!

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Contribution Check completed successfully!

Contribution check complete: PR #6811 appears to meet the applicable CONTRIBUTING.md guidelines. It includes tests for the new behavior, updates documentation, keeps new source in the expected directories, and the description references a related issue.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Docker Sbx has concluded. All systems operational. This is a developing story. 🎤

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (Entra) completed. Copilot AOAI BYOK (Entra) mode operational. 🔓

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Claude passed

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Copilot BYOK (Direct) Mode

✅ MCP connectivity verified
✅ GitHub.com reachable (HTTP 200)
✅ File write/read verified
✅ BYOK inference path working (api-proxy → api.githubcopilot.com)

Running in direct BYOK mode via COPILOT_PROVIDER_API_KEY.

Status: PASS

🔑 BYOK report filed by Smoke Copilot BYOK
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

EGRESS_RESULT allow=pass deny=pass

✅ Allowed domain (github.com) reachable: allowed=200
✅ Blocked domain (example.com) denied: CONNECT 403

Overall: PASS

@lpcox

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • example.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "example.com"

See Network Configuration for more information.

🛡️ Egress verdict from Smoke Copilot Network Isolation
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Copilot Engine@lpcox

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Claude Engine Validation

Check Result
API status ✅ PASS
gh check ✅ PASS
File status ✅ PASS

Overall result: PASS

Generated by Smoke Claude for #6811 · haiku45 · 54.9 AIC · ⊞ 3.6K ·
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test Results: GitHub Actions Services Connectivity

  • Redis PING: ❌ (Temporary failure in name resolution)
  • PostgreSQL pg_isready: ❌ (no response)
  • PostgreSQL SELECT 1: ❌ (could not translate host name)

Overall: FAILhost.docker.internal did not resolve from within the AWF sandbox.

🔌 Service connectivity validated by Smoke Services
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@lpcox

  • GitHub MCP Connectivity: ✅ (pre-fetched data validated)
  • GitHub.com HTTP Connectivity: ✅
  • File Write/Read Test: ✅
  • BYOK Inference Test: ✅

Running in direct BYOK mode (AWF_AUTH_TYPE=github-oidc + AWF_AUTH_AZURE_* + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw) authenticated via Microsoft Entra

Overall: PASS

🪪 BYOK (AOAI Entra) report filed by Smoke Copilot BYOK AOAI (Entra)
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "registry.npmjs.org"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Gemini Engine Validation

  • GitHub MCP Testing: ❌ (PRs filtered by integrity policy)
  • GitHub.com Connectivity: ❌ (HTTP 000/Failed to connect)
  • File Writing Testing: ✅
  • Bash Tool Testing: ✅

Overall Status: FAIL

💎 Faceted by Smoke Gemini

💎 Faceted by Smoke Gemini
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.13 ✅ YES
Node.js v24.18.0 v22.23.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: FAILED — Node.js version mismatch between host and chroot environments. smoke-chroot label not applied.

Tested by Smoke Chroot
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: API Proxy OpenTelemetry Tracing

Scenario Result
1. Module Loading otel.js loads; isEnabled() → true; exports include startRequestSpan, setTokenAttributes, endSpan, _FanOutSpanExporter, etc.
2. Test Suite ✅ 2 suites / 59 tests passed (otel.test.js, otel-fanout.test.js)
3. Env Var Forwarding src/services/api-proxy-service.ts does not forward OTEL_EXPORTER_OTLP_ENDPOINT or GITHUB_AW_OTEL_TRACE_ID to the api-proxy container — spans can be created in the sidecar but trace context/export endpoint aren't wired from the CLI yet
4. Token Tracker Integration token-tracker-http.js contains the onUsage callback hook (4 references) used as the OTEL integration point
5. OTEL Diagnostics i️ No otel.jsonl/spans found under api-proxy-logs/ for this run (expected, since env var forwarding is not yet implemented — no endpoint was configured for the sidecar to export to)

Overall: 4/5 as expected for current development state; 1 real gap identified (env var forwarding), consistent with why no spans were exported in diagnostics. No new issue filed — this appears to be known in-progress work already tracked by this smoke test.

📡 OTel tracing validated by Smoke OTel Tracing
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color ok ✅ PASS
Go env ok ✅ PASS
Go uuid ok ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx passed ✅ PASS
Node.js execa passed ✅ PASS
Node.js p-limit passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — PASS

Notes
  • Java (mvn compile/mvn test) initially failed with Could not create local repository at /home/runner/.m2/repository because /home/runner/.m2 is owned by root and not writable by the runner user in this environment. Worked around by passing -Dmaven.repo.local=<writable tmp path>; after that both gson and caffeine compiled and tested successfully (1/1 tests each). This is an environment permissions quirk, not a firewall/network issue — all Maven traffic went through the Squid proxy as configured in ~/.m2/settings.xml without any domain blocks.
  • All other ecosystems (Bun, C++, Deno, .NET, Go, Node.js, Rust) built/installed and passed tests with no network or firewall issues.

Generated by Build Test Suite for #6811 · aut00 · 41.8 AIC · ⊞ 11.3K ·
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Docker Sbx@lpcox

Overall: PASS

📰 BREAKING: Report filed by Smoke Docker Sbx
Add label ready-for-aw to run again

@lpcox
lpcox enabled auto-merge (squash) August 1, 2026 22:35
@lpcox
lpcox merged commit 313eeed into main Aug 1, 2026
143 of 146 checks passed
@lpcox
lpcox deleted the copilot/fix-ai-credit-pricing-issue branch August 1, 2026 22:37
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.

Model auto fails AI-credit pricing in isolated agent runtimes

3 participants