fix(pi): use active provider gateway port for /reflect instead of hardcoded port 10000#33861
Conversation
…rt 10000 The AWF api-proxy only starts sidecar ports for configured providers. When smoke-pi runs with copilot/claude-sonnet-4-20250514, only port 10002 (Copilot) is started. Port 10000 (OpenAI) is never started, so fetching http://api-proxy:10000/reflect fails with "fetch failed". Fix pi_provider.cjs to resolve the reflect URL from resolveGatewayUrl() using the active provider prefix from GH_AW_PI_MODEL, defaulting to the Copilot gateway (port 10002) when no provider prefix is present — consistent with resolvePiBackend() in pi_engine.go. Also update the misleading "management port (port 10000)" comments in awf_reflect.cjs to accurately describe that /reflect is served on each provider's sidecar port, not on a dedicated always-on management port. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Address code review feedback: - Separate providerGatewayUrl from the final gatewayUrl so unknown providers emit a clear warning log at extension load time rather than silently falling back to port 10000 (which would also fail) - Fall back to Copilot gateway (port 10002) instead of port 10000 when the specified provider has no known AWF sidecar port - Fix test model name 'claude-sonnet-4' → 'my-custom-model' to avoid implying it is an Anthropic model - Add unknown-provider fallback test verifying the warning log and port 10002 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨ Caution agentic threat detected |
Agent Container Tool Check ✅
Result: 12/12 tools available ✅ All required development tools are accessible in the agent container environment.
|
This comment has been minimized.
This comment has been minimized.
|
@copilot make sure /reflect is enabled in awf See https://github.com/github/gh-aw/actions/runs/26254375836/job/77273497264#step:31:1 |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
Warning
Firewall blocked 5 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · ● 5M
Comments that could not be inline-anchored
actions/setup/js/pi_provider.cjs:5
Note: nice fix swapping the hardcoded gateway port for the active provider port — this should make local dev with non-Copilot providers more reliable.
actions/setup/js/pi_provider.test.cjs:10
Good to see test coverage added alongside this change — consider also adding a case for the unknown-provider warning fallback path.
|
🎉 The smoke test agent dropped by to say hello! I just validated 15 different capabilities across MCP servers, CLI tools, and safe outputs. Most tests passed with flying colors! 🚀 Though I must say, searching for files that don't exist is a bit like looking for a needle in a haystack... when there's no haystack. 😄 Have a wonderful day! Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
Smoke Test Results ✅Run: §26254375840
Overall: PASS (13/15) cc Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Reviewed the PR changes. The dynamic gateway URL resolution looks good and properly handles all provider cases with appropriate fallback logic.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 1.7M
| if (provider && !providerGatewayUrl) { | ||
| log(`provider=${provider}: no known AWF gateway port, falling back to Copilot gateway for /reflect`); | ||
| } | ||
| const reflectUrl = gatewayUrl ? `${gatewayUrl}/reflect` : AWF_API_PROXY_REFLECT_URL; |
There was a problem hiding this comment.
Nice fix! The dynamic provider resolution is much better than hardcoding port 10000.
There was a problem hiding this comment.
Me agree! Dynamic port better than hardcoded. Good coding practice! 🎯
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 2M
| const provider = extractProviderFromModel(model); | ||
| const providerGatewayUrl = provider ? resolveGatewayUrl(provider) : null; | ||
| const gatewayUrl = providerGatewayUrl || resolveGatewayUrl("copilot"); | ||
| if (provider && !providerGatewayUrl) { |
There was a problem hiding this comment.
Good fallback logging for unknown providers. This will help with debugging.
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ PR Code Quality Reviewer completed the code quality review. No action needed: Reviewed PR #33861 (AWF reflect port fix). Code is well-structured with comprehensive tests. Conditional check pattern is appropriate for the use case. No significant issues found. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #33861 does not have the implementation label and only adds 3 lines to business logic directories (well below the 100-line threshold). |
|
🧪 Test Quality Sentinel completed test quality analysis. |
There was a problem hiding this comment.
Pull request overview
Adjusts how the Pi integration decides whether to call the AWF api-proxy /reflect endpoint, and updates related documentation/tests.
Changes:
- Inject
AWF_REFLECT_ENABLED=1for Pi runs when the AWF firewall is enabled so the Pi extension knows the api-proxy sidecar is expected to be running. - Gate the Pi extension’s
/reflectpreflight/postflight calls onAWF_REFLECT_ENABLED. - Update
/reflectdocumentation comments and add tests around the new gating behavior.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/pi_engine.go | Sets AWF_REFLECT_ENABLED in the Pi runtime env when AWF firewall is active. |
| actions/setup/js/pi_provider.cjs | Skips /reflect fetches unless AWF_REFLECT_ENABLED is set. |
| actions/setup/js/awf_reflect.cjs | Updates comments describing how /reflect should be reached. |
| actions/setup/js/pi_provider.test.cjs | Adds tests for calling vs skipping /reflect based on AWF_REFLECT_ENABLED. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 4/4 changed files
- Comments generated: 3
| // Fetch AWF API proxy reflection data before the agent runs to capture initial proxy state. | ||
| // This is best-effort: failures are logged but do not affect the agent session. | ||
| await fetchAWFReflect({ | ||
| reflectUrl: AWF_API_PROXY_REFLECT_URL, | ||
| outputPath: AWF_REFLECT_OUTPUT_PATH, | ||
| timeoutMs: AWF_REFLECT_TIMEOUT_MS, | ||
| modelsTimeoutMs: AWF_MODELS_URL_TIMEOUT_MS, | ||
| logger: log, | ||
| }); | ||
| // Skip when AWF_REFLECT_ENABLED is not "1" (e.g. sandbox.agent: false — no api-proxy running). | ||
| if (process.env.AWF_REFLECT_ENABLED === "1") { | ||
| await fetchAWFReflect({ | ||
| reflectUrl: AWF_API_PROXY_REFLECT_URL, | ||
| outputPath: AWF_REFLECT_OUTPUT_PATH, | ||
| timeoutMs: AWF_REFLECT_TIMEOUT_MS, | ||
| modelsTimeoutMs: AWF_MODELS_URL_TIMEOUT_MS, | ||
| logger: log, | ||
| }); |
| * The /reflect endpoint is exposed by the api-proxy sidecar on each started provider port. | ||
| * The active provider's gateway port should be used rather than a hardcoded port, since | ||
| * port 10000 (the OpenAI sidecar) is only started when OpenAI credentials are configured. |
| it("calls /reflect on the management port (10000) when AWF_REFLECT_ENABLED is set", async () => { | ||
| process.env.GH_AW_PI_MODEL = "copilot/claude-sonnet-4"; | ||
| process.env.AWF_REFLECT_ENABLED = "1"; | ||
| const fetchedUrls = []; | ||
| global.fetch = vi.fn().mockImplementation(url => { | ||
| fetchedUrls.push(url); | ||
| return Promise.reject(new Error("network disabled")); | ||
| }); | ||
|
|
||
| const handlers = {}; | ||
| const pi = { | ||
| registerProvider: vi.fn(), | ||
| on: vi.fn((event, handler) => { | ||
| handlers[event] = handler; | ||
| }), | ||
| }; | ||
|
|
||
| module.default(pi); | ||
| await handlers.agent_start(); | ||
| await handlers.agent_end(); | ||
|
|
||
| expect(fetchedUrls.every(url => url === "http://api-proxy:10000/reflect")).toBe(true); | ||
| expect(fetchedUrls.length).toBe(2); |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨ Caution agentic threat detected Test |
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnose and /tdd — requesting changes on test regression coverage.
📋 Critical Issue
Test Validates Old Broken Behavior
The new test at line 100 expects (apiproxy/redacted) for **all** providers, which is exactly the bug this PR fixes. For copilot/claude-sonnet-4, the correct URL should be (apiproxy/redacted)
This defeats the purpose of a regression test — if the bug reappears, the test would still pass.
Missing Implementation
The PR description mentions using resolveGatewayUrl(provider) for dynamic resolution, but I don't see that change in the diff. The code still references the constant AWF_API_PROXY_REFLECT_URL without showing how it's computed.
✅ Positive Highlights
- Good addition of
AWF_REFLECT_ENABLEDguard to prevent failures when api-proxy isn't running - Comprehensive test scenarios covering both enabled and disabled states
- Clear documentation updates correcting outdated "management port" comments
- Proper Go-side environment variable wiring in
pi_engine.go
Next steps: Update the test expectation to verify port 10002 for Copilot models, and ensure the dynamic resolution logic is visible in the diff or properly tested.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 703.1K
| await handlers.agent_start(); | ||
| await handlers.agent_end(); | ||
|
|
||
| expect(fetchedUrls.every(url => url === "http://api-proxy:10000/reflect")).toBe(true); |
There was a problem hiding this comment.
[/tdd] Test expectation contradicts the PR fix — verifies the old broken behavior instead of the new dynamic port resolution.
💡 Why this matters
The PR description states the fix resolves the active provider's gateway port rather than hardcoding port 10000. But this test expects all URLs to be `(apiproxy/redacted) which is exactly the bug being fixed.
For copilot/claude-sonnet-4, the URL should be `(apiproxy/redacted) (Copilot sidecar port).
Suggested fix:
// Update the expectation to verify dynamic resolution
expect(fetchedUrls.every(url => url === "(apiproxy/redacted)This regression test would actually catch the bug if it reappears.
|
|
||
| expect(stderrOutput.some(line => line.includes("provider=copilot model=copilot/claude-sonnet-4"))).toBe(true); | ||
| }); | ||
|
|
There was a problem hiding this comment.
[/tdd] Misleading test name — this test should verify that Copilot uses port 10002, not port 10000.
💡 Suggested rename
The test description says "calls /reflect on the management port (10000)" but:
- Port 10000 is the OpenAI sidecar, not a "management port"
- For Copilot models, the correct port is 10002
- The PR removes the hardcoded 10000 constant
Suggested rename:
it("uses Copilot provider port (10002) for /reflect when model is copilot/*", async () => {Clear test names serve as executable documentation — they should describe the expected behavior, not the old bug.
| logger: log, | ||
| }); | ||
| // Skip when AWF_REFLECT_ENABLED is not "1" (e.g. sandbox.agent: false — no api-proxy running). | ||
| if (process.env.AWF_REFLECT_ENABLED === "1") { |
There was a problem hiding this comment.
[/diagnose] Environment guard added without corresponding implementation change — where is AWF_API_PROXY_REFLECT_URL computed?
💡 Root cause analysis
The PR description says the fix "resolves the reflect URL at extension load time using the existing resolveGatewayUrl(provider)", but I don't see that change in the diff. The code still uses the constant AWF_API_PROXY_REFLECT_URL.
Expected to see:
// Resolve the URL dynamically based on the active provider
const reflectUrl = resolveGatewayUrl(provider) + '/reflect';Or if AWF_API_PROXY_REFLECT_URL is computed elsewhere, that computation should be visible in the diff. Without seeing the dynamic resolution logic, this appears to be an incomplete fix.
…orks/pi-* and bump version to 0.75.4 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — replaced all
|
|
Caution agentic threat detected Smoke Test Results: Gemini - 26256118646
Overall Status: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
🧪 Test Quality Sentinel Report✅ Test Quality Score: 90/100 — Excellent
📊 Metrics & Test Classification (2 tests analyzed)
Test Classification Details
Language SupportTests analyzed:
📏 Test Inflation Analysis
Context: The 2.25:1 ratio slightly exceeds the 2:1 threshold, but is acceptable given the comprehensive nature of the tests:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.
|
Smoke Test: Claude - 26256118523Core (#1–12): ✅ all passed Overall: ✅ PASS Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · ● 6.1M
| // Skip when AWF_REFLECT_ENABLED is not "1" (e.g. sandbox.agent: false — no api-proxy running). | ||
| if (process.env.AWF_REFLECT_ENABLED === "1") { | ||
| await fetchAWFReflect({ | ||
| reflectUrl: AWF_API_PROXY_REFLECT_URL, |
There was a problem hiding this comment.
Nice gating! Consider adding a debug log when AWF_REFLECT_ENABLED !== "1" so it's easier to confirm in CI why the reflect call was skipped.
| reflectUrl: AWF_API_PROXY_REFLECT_URL, | ||
| outputPath: AWF_REFLECT_OUTPUT_PATH, | ||
| timeoutMs: AWF_REFLECT_TIMEOUT_MS, | ||
| modelsTimeoutMs: AWF_MODELS_URL_TIMEOUT_MS, |
There was a problem hiding this comment.
Same gate as agent_start — consider extracting both blocks into a helper to keep the two call sites in sync.
|
🎉 Me back! Me test comment on discussion. Me caveman very proud. All tests running. System healthy! Grunt grunt 💪 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
🦖 Smoke Test CompleteStatus: PASS ✅ Results:
Run: https://github.com/github/gh-aw/actions/runs/26256118637 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
📰 DEVELOPING STORY: Smoke Copilot reports failed to deliver outputs. Our correspondents are investigating the incident... |
pi_provider.cjshardcodedhttp://api-proxy:10000/reflectfor the AWF reflect call. Port 10000 is the OpenAI sidecar — it only starts when OpenAI credentials are present.smoke-piusescopilot/claude-sonnet-4-20250514, so AWF starts only port 10002 (Copilot); port 10000 never comes up, causingfetch failed.Changes
pi_provider.cjs: Resolve the reflect URL at extension load time using the existingresolveGatewayUrl(provider)rather than the hardcoded constant. Falls back to Copilot (port 10002) for bare model names (matchingresolvePiBackend()in Go) and logs a warning before falling back for unrecognised providers.awf_reflect.cjs: Correct comments that described port 10000 as a "management port" —/reflectis served on each provider's sidecar port, not a dedicated always-on port.pi_provider.test.cjs: Add four tests covering copilot→10002, anthropic→10001, bare model→10002, and unknown provider→warning+fallback to 10002.✨ PR Review Safe Output Test - Run 26254375762
Warning
Firewall blocked 5 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.
✨ PR Review Safe Output Test - Run 26256118523
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.