diff --git a/.github/workflows/smoke-copilot-byok.lock.yml b/.github/workflows/smoke-copilot-byok.lock.yml
index ed51cbc5..91f81998 100644
--- a/.github/workflows/smoke-copilot-byok.lock.yml
+++ b/.github/workflows/smoke-copilot-byok.lock.yml
@@ -1,4 +1,4 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"de7d4c7e7e258e37b0372086619480163a1e39f2639650ef7d3cbfe2471710fa","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot"}
+# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"92f6aa4829de1e7ceadea14f9854fe57299c56bd360c084eee95650731f35fb3","compiler_version":"v0.68.3","strict":true,"agent_id":"copilot"}
# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba90f2186d7ad780ec640f364005fa24e797b360","version":"v0.68.3"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]}
# ___ _ _
# / _ \ | | (_)
@@ -26,6 +26,7 @@
#
# Frontmatter env variables:
# - COPILOT_API_KEY: (main workflow)
+# - COPILOT_MODEL: (main workflow)
#
# Secrets used:
# - COPILOT_GITHUB_TOKEN
@@ -77,6 +78,7 @@ run-name: "Smoke Copilot BYOK"
env:
COPILOT_API_KEY: dummy-byok-key-for-offline-mode
+ COPILOT_MODEL: claude-opus-4.6
jobs:
activation:
@@ -192,6 +194,8 @@ jobs:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
GH_AW_EXPR_2805DAC9: ${{ steps.smoke-data.outputs.SMOKE_FILE_PATH }}
+ GH_AW_EXPR_7EA93000: ${{ steps.smoke-data.outputs.SMOKE_HTTP_CODE }}
+ GH_AW_EXPR_ABDF8D58: ${{ steps.smoke-data.outputs.SMOKE_PR_DATA }}
GH_AW_EXPR_EC16C26C: ${{ steps.smoke-data.outputs.SMOKE_FILE_CONTENT }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
@@ -205,14 +209,14 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_2fb68bae1c8f1b53_EOF'
+ cat << 'GH_AW_PROMPT_c7171ddd49346715_EOF'
- GH_AW_PROMPT_2fb68bae1c8f1b53_EOF
+ GH_AW_PROMPT_c7171ddd49346715_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_2fb68bae1c8f1b53_EOF'
+ cat << 'GH_AW_PROMPT_c7171ddd49346715_EOF'
Tools: add_comment, add_labels, missing_tool, missing_data, noop
@@ -244,12 +248,12 @@ jobs:
{{/if}}
- GH_AW_PROMPT_2fb68bae1c8f1b53_EOF
+ GH_AW_PROMPT_c7171ddd49346715_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_2fb68bae1c8f1b53_EOF'
+ cat << 'GH_AW_PROMPT_c7171ddd49346715_EOF'
{{#runtime-import .github/workflows/smoke-copilot-byok.md}}
- GH_AW_PROMPT_2fb68bae1c8f1b53_EOF
+ GH_AW_PROMPT_c7171ddd49346715_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9
@@ -258,6 +262,8 @@ jobs:
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_EXPR_EC16C26C: ${{ steps.smoke-data.outputs.SMOKE_FILE_CONTENT }}
GH_AW_EXPR_2805DAC9: ${{ steps.smoke-data.outputs.SMOKE_FILE_PATH }}
+ GH_AW_EXPR_7EA93000: ${{ steps.smoke-data.outputs.SMOKE_HTTP_CODE }}
+ GH_AW_EXPR_ABDF8D58: ${{ steps.smoke-data.outputs.SMOKE_PR_DATA }}
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -269,6 +275,8 @@ jobs:
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_EXPR_2805DAC9: ${{ steps.smoke-data.outputs.SMOKE_FILE_PATH }}
+ GH_AW_EXPR_7EA93000: ${{ steps.smoke-data.outputs.SMOKE_HTTP_CODE }}
+ GH_AW_EXPR_ABDF8D58: ${{ steps.smoke-data.outputs.SMOKE_PR_DATA }}
GH_AW_EXPR_EC16C26C: ${{ steps.smoke-data.outputs.SMOKE_FILE_CONTENT }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
@@ -290,6 +298,8 @@ jobs:
file: process.env.GH_AW_PROMPT,
substitutions: {
GH_AW_EXPR_2805DAC9: process.env.GH_AW_EXPR_2805DAC9,
+ GH_AW_EXPR_7EA93000: process.env.GH_AW_EXPR_7EA93000,
+ GH_AW_EXPR_ABDF8D58: process.env.GH_AW_EXPR_ABDF8D58,
GH_AW_EXPR_EC16C26C: process.env.GH_AW_EXPR_EC16C26C,
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
@@ -376,9 +386,11 @@ jobs:
run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh"
env:
GH_TOKEN: ${{ github.token }}
- - id: smoke-data
+ - env:
+ GH_TOKEN: ${{ github.token }}
+ id: smoke-data
name: Pre-compute BYOK smoke test data
- run: "echo \"::group::Verify BYOK configuration\"\necho \"COPILOT_API_KEY=${COPILOT_API_KEY:+set (${#COPILOT_API_KEY} chars)}\"\necho \"COPILOT_API_TARGET=${COPILOT_API_TARGET:-api.githubcopilot.com (default)}\"\necho \"::endgroup::\"\n\necho \"::group::File write/read test\"\nTEST_DIR=\"/tmp/gh-aw/agent\"\nTEST_FILE=\"$TEST_DIR/smoke-test-copilot-byok-${GITHUB_RUN_ID}.txt\"\nmkdir -p \"$TEST_DIR\"\necho \"BYOK smoke test passed at $(date)\" > \"$TEST_FILE\"\nFILE_CONTENT=$(cat \"$TEST_FILE\")\necho \"Wrote and read back: $FILE_CONTENT\"\necho \"::endgroup::\"\n\n{\n echo \"SMOKE_FILE_CONTENT=$FILE_CONTENT\"\n echo \"SMOKE_FILE_PATH=$TEST_FILE\"\n} >> \"$GITHUB_OUTPUT\"\n"
+ run: "echo \"::group::Verify BYOK configuration\"\necho \"COPILOT_API_KEY=${COPILOT_API_KEY:+set (${#COPILOT_API_KEY} chars)}\"\necho \"COPILOT_API_TARGET=${COPILOT_API_TARGET:-api.githubcopilot.com (default)}\"\necho \"::endgroup::\"\n\necho \"::group::Fetching last 2 merged PRs\"\nPR_DATA=$(gh pr list --repo \"$GITHUB_REPOSITORY\" --state merged --limit 2 \\\n --json number,title,author,mergedAt \\\n --jq '.[] | \"PR #\\(.number): \\(.title) (by @\\(.author.login), merged \\(.mergedAt))\"')\necho \"$PR_DATA\"\necho \"::endgroup::\"\n\necho \"::group::GitHub.com connectivity check\"\nHTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 https://github.com)\necho \"github.com returned HTTP $HTTP_CODE\"\necho \"::endgroup::\"\n\necho \"::group::File write/read test\"\nTEST_DIR=\"/tmp/gh-aw/agent\"\nTEST_FILE=\"$TEST_DIR/smoke-test-copilot-byok-${GITHUB_RUN_ID}.txt\"\nmkdir -p \"$TEST_DIR\"\necho \"BYOK smoke test passed at $(date)\" > \"$TEST_FILE\"\nFILE_CONTENT=$(cat \"$TEST_FILE\")\necho \"Wrote and read back: $FILE_CONTENT\"\necho \"::endgroup::\"\n\n{\n echo \"SMOKE_PR_DATA<> \"$GITHUB_OUTPUT\"\n"
- name: Configure Git credentials
env:
@@ -408,7 +420,7 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
await main();
- name: Install GitHub Copilot CLI
- run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.21
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.28
env:
GH_HOST: github.com
- name: Install awf dependencies
@@ -453,9 +465,9 @@ jobs:
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
- cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_109df9f4f636e998_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_949b89c0812a87fb_EOF'
{"add_comment":{"hide_older_comments":true,"max":1},"add_labels":{"allowed":["smoke-copilot-byok"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_109df9f4f636e998_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_949b89c0812a87fb_EOF
- name: Write Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -656,7 +668,7 @@ jobs:
export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19'
mkdir -p /home/runner/.copilot
- cat << GH_AW_MCP_CONFIG_d97b07431cee7350_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh"
+ cat << GH_AW_MCP_CONFIG_249b3156ded81d6a_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh"
{
"mcpServers": {
"safeoutputs": {
@@ -681,7 +693,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_d97b07431cee7350_EOF
+ GH_AW_MCP_CONFIG_249b3156ded81d6a_EOF
- name: Download activation artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
@@ -712,7 +724,7 @@ jobs:
env:
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
diff --git a/.github/workflows/smoke-copilot-byok.md b/.github/workflows/smoke-copilot-byok.md
index 0d6eeee4..40319143 100644
--- a/.github/workflows/smoke-copilot-byok.md
+++ b/.github/workflows/smoke-copilot-byok.md
@@ -38,6 +38,7 @@ safe-outputs:
timeout-minutes: 5
env:
COPILOT_API_KEY: dummy-byok-key-for-offline-mode
+ COPILOT_MODEL: claude-opus-4.6
features:
cli-proxy: true
strict: true
@@ -50,6 +51,18 @@ steps:
echo "COPILOT_API_TARGET=${COPILOT_API_TARGET:-api.githubcopilot.com (default)}"
echo "::endgroup::"
+ echo "::group::Fetching last 2 merged PRs"
+ PR_DATA=$(gh pr list --repo "$GITHUB_REPOSITORY" --state merged --limit 2 \
+ --json number,title,author,mergedAt \
+ --jq '.[] | "PR #\(.number): \(.title) (by @\(.author.login), merged \(.mergedAt))"')
+ echo "$PR_DATA"
+ echo "::endgroup::"
+
+ echo "::group::GitHub.com connectivity check"
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 https://github.com)
+ echo "github.com returned HTTP $HTTP_CODE"
+ echo "::endgroup::"
+
echo "::group::File write/read test"
TEST_DIR="/tmp/gh-aw/agent"
TEST_FILE="$TEST_DIR/smoke-test-copilot-byok-${GITHUB_RUN_ID}.txt"
@@ -60,9 +73,15 @@ steps:
echo "::endgroup::"
{
+ echo "SMOKE_PR_DATA<> "$GITHUB_OUTPUT"
+ env:
+ GH_TOKEN: ${{ github.token }}
post-steps:
- name: Validate safe outputs were invoked
run: |
@@ -105,21 +124,34 @@ This smoke test validates that Copilot CLI runs in **offline BYOK mode** — wit
## Pre-Computed Test Results
-### 1. File Write/Read Test
+The following tests were already executed in a deterministic pre-agent step. Your job is to verify the results and produce the summary comment.
+
+### 1. GitHub MCP Testing
+Verify MCP connectivity by calling `github-list_pull_requests` for ${{ github.repository }} (limit 1, state merged). Confirm the result matches the pre-fetched data below.
+
+### 2. GitHub.com Connectivity
+Pre-step result: HTTP ${{ steps.smoke-data.outputs.SMOKE_HTTP_CODE }} from github.com.
+✅ if HTTP 200 or 301, ❌ otherwise.
+
+### 3. File Write/Read Test
Pre-step wrote and read back: "${{ steps.smoke-data.outputs.SMOKE_FILE_CONTENT }}"
File path: ${{ steps.smoke-data.outputs.SMOKE_FILE_PATH }}
Verify by running `cat` on the file path using bash to confirm it exists.
-### 2. GitHub MCP Testing
-Verify MCP connectivity by calling `github-list_pull_requests` for ${{ github.repository }} (limit 1, state merged). Confirm the result returns data.
-
-### 3. BYOK Inference Test
+### 4. BYOK Inference Test
You are running in offline BYOK mode right now. The fact that you can read this prompt and respond means the BYOK inference path (agent → api-proxy sidecar → api.githubcopilot.com) is working. Confirm ✅.
+## Pre-Fetched PR Data
+
+```
+${{ steps.smoke-data.outputs.SMOKE_PR_DATA }}
+```
+
## Output
Add a **very brief** comment (max 5-10 lines) to the current pull request with:
-- ✅ or ❌ for each test result (file I/O, MCP, inference)
+- PR titles only (no descriptions)
+- ✅ or ❌ for each test result
- Note: "Running in BYOK offline mode (COPILOT_OFFLINE=true) via api-proxy → api.githubcopilot.com"
- Overall status: PASS or FAIL
- Mention the pull request author and any assignees
diff --git a/containers/api-proxy/server.js b/containers/api-proxy/server.js
index 84889129..010ba5f1 100644
--- a/containers/api-proxy/server.js
+++ b/containers/api-proxy/server.js
@@ -78,6 +78,7 @@ function resolveCopilotAuthToken(env = process.env) {
}
const COPILOT_AUTH_TOKEN = resolveCopilotAuthToken(process.env);
+const COPILOT_INTEGRATION_ID = process.env.COPILOT_INTEGRATION_ID || 'copilot-developer-cli';
const GEMINI_API_KEY = (process.env.GEMINI_API_KEY || '').trim() || undefined;
/**
@@ -337,7 +338,7 @@ function resolveOpenCodeRoute(openaiKey, anthropicKey, copilotToken, openaiTarge
return { target: anthropicTarget, headers: { 'x-api-key': anthropicKey }, basePath: anthropicBasePath, needsAnthropicVersion: true };
}
if (copilotToken) {
- return { target: copilotTarget, headers: { 'Authorization': `Bearer ${copilotToken}` }, basePath: undefined, needsAnthropicVersion: false };
+ return { target: copilotTarget, headers: { 'Authorization': `Bearer ${copilotToken}`, 'Copilot-Integration-Id': COPILOT_INTEGRATION_ID }, basePath: undefined, needsAnthropicVersion: false };
}
return null;
}
@@ -1012,18 +1013,21 @@ if (require.main === module) {
if (isModelsPath && req.method === 'GET' && COPILOT_GITHUB_TOKEN) {
proxyRequest(req, res, COPILOT_API_TARGET, {
'Authorization': `Bearer ${COPILOT_GITHUB_TOKEN}`,
+ 'Copilot-Integration-Id': COPILOT_INTEGRATION_ID,
}, 'copilot');
return;
}
proxyRequest(req, res, COPILOT_API_TARGET, {
'Authorization': `Bearer ${COPILOT_AUTH_TOKEN}`,
+ 'Copilot-Integration-Id': COPILOT_INTEGRATION_ID,
}, 'copilot');
});
copilotServer.on('upgrade', (req, socket, head) => {
proxyWebSocket(req, socket, head, COPILOT_API_TARGET, {
'Authorization': `Bearer ${COPILOT_AUTH_TOKEN}`,
+ 'Copilot-Integration-Id': COPILOT_INTEGRATION_ID,
}, 'copilot');
});