From 6c38268f4ca51a14f63854a1dea0e974d071ab6a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 02:18:45 +0000 Subject: [PATCH 1/8] Route antigravity AWF target through gemini provider Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/awf_config.go | 12 ++++++--- pkg/workflow/awf_config_test.go | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/pkg/workflow/awf_config.go b/pkg/workflow/awf_config.go index 4d7d4e93de6..52a341fe2f6 100644 --- a/pkg/workflow/awf_config.go +++ b/pkg/workflow/awf_config.go @@ -166,7 +166,7 @@ type AWFAPIProxyConfig struct { ModelMultipliers map[string]float64 `json:"modelMultipliers,omitempty"` // Targets holds per-provider API target overrides. - // Supported keys: "openai", "anthropic", "copilot", "antigravity", "gemini" (deprecated, use "antigravity") + // Supported keys: "openai", "anthropic", "copilot", "gemini" Targets map[string]*AWFAPITargetConfig `json:"targets,omitempty"` // Models contains model alias and fallback policy definitions. @@ -300,11 +300,15 @@ func BuildAWFConfigJSON(config AWFCommandConfig) (string, error) { targets["copilot"] = &AWFAPITargetConfig{Host: copilotTarget} awfConfigLog.Printf("API proxy: custom copilot target=%s", copilotTarget) } + geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName) if antigravityTarget := GetAntigravityAPITarget(config.WorkflowData, config.EngineName); antigravityTarget != "" { - targets["antigravity"] = &AWFAPITargetConfig{Host: antigravityTarget} - awfConfigLog.Printf("API proxy: custom antigravity target=%s", antigravityTarget) + // Antigravity CLI now uses the Gemini provider/endpoint in AWS. Route the + // Antigravity-resolved API target through the "gemini" provider key to match + // AWF's supported target providers. + geminiTarget = antigravityTarget + awfConfigLog.Printf("API proxy: mapped antigravity target to gemini provider target=%s", antigravityTarget) } - if geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName); geminiTarget != "" { + if geminiTarget != "" { targets["gemini"] = &AWFAPITargetConfig{Host: geminiTarget} awfConfigLog.Printf("API proxy: custom gemini target=%s", geminiTarget) } diff --git a/pkg/workflow/awf_config_test.go b/pkg/workflow/awf_config_test.go index 9aca201ba51..86a36bca237 100644 --- a/pkg/workflow/awf_config_test.go +++ b/pkg/workflow/awf_config_test.go @@ -293,6 +293,51 @@ func TestBuildAWFConfigJSON(t *testing.T) { assert.Contains(t, jsonStr, "corp-gateway.example.com", "should include the anthropic host") }) + t.Run("antigravity engine routes API target through gemini provider", func(t *testing.T) { + config := AWFCommandConfig{ + EngineName: "antigravity", + AllowedDomains: "github.com", + WorkflowData: &WorkflowData{ + EngineConfig: &EngineConfig{ID: "antigravity"}, + NetworkPermissions: &NetworkPermissions{ + Firewall: &FirewallConfig{Enabled: true}, + }, + }, + } + + jsonStr, err := BuildAWFConfigJSON(config) + require.NoError(t, err) + + assert.Contains(t, jsonStr, `"gemini"`, "should include gemini target for antigravity engine") + assert.Contains(t, jsonStr, "generativelanguage.googleapis.com", "should include default Gemini API hostname") + assert.NotContains(t, jsonStr, `"antigravity"`, "should not include unsupported antigravity target key") + }) + + t.Run("antigravity custom base URL maps to gemini provider target", func(t *testing.T) { + config := AWFCommandConfig{ + EngineName: "antigravity", + AllowedDomains: "github.com", + WorkflowData: &WorkflowData{ + EngineConfig: &EngineConfig{ + ID: "antigravity", + Env: map[string]string{ + "ANTIGRAVITY_API_BASE_URL": "https://antigravity-proxy.internal.example.com/v1", + }, + }, + NetworkPermissions: &NetworkPermissions{ + Firewall: &FirewallConfig{Enabled: true}, + }, + }, + } + + jsonStr, err := BuildAWFConfigJSON(config) + require.NoError(t, err) + + assert.Contains(t, jsonStr, `"gemini"`, "should include gemini target for antigravity engine") + assert.Contains(t, jsonStr, "antigravity-proxy.internal.example.com", "should include host from ANTIGRAVITY_API_BASE_URL") + assert.NotContains(t, jsonStr, `"antigravity"`, "should not include unsupported antigravity target key") + }) + t.Run("no API targets section when no custom endpoints are configured", func(t *testing.T) { config := AWFCommandConfig{ EngineName: "copilot", From 4776d19eae3e83efea2270c40a9a77daa3f81792 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 02:19:43 +0000 Subject: [PATCH 2/8] Refine antigravity-to-gemini target mapping logs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/awf_config.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/workflow/awf_config.go b/pkg/workflow/awf_config.go index 52a341fe2f6..362fdfa5084 100644 --- a/pkg/workflow/awf_config.go +++ b/pkg/workflow/awf_config.go @@ -302,9 +302,11 @@ func BuildAWFConfigJSON(config AWFCommandConfig) (string, error) { } geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName) if antigravityTarget := GetAntigravityAPITarget(config.WorkflowData, config.EngineName); antigravityTarget != "" { - // Antigravity CLI now uses the Gemini provider/endpoint in AWS. Route the - // Antigravity-resolved API target through the "gemini" provider key to match - // AWF's supported target providers. + // Route the Antigravity-resolved API target through the "gemini" provider key + // to match AWF's supported target providers. + if geminiTarget != "" && geminiTarget != antigravityTarget { + awfConfigLog.Printf("API proxy: overriding gemini target %s with antigravity target %s", geminiTarget, antigravityTarget) + } geminiTarget = antigravityTarget awfConfigLog.Printf("API proxy: mapped antigravity target to gemini provider target=%s", antigravityTarget) } From f6f6b44c87a88b5e2ac1148a5b4135cece0ba73b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 02:20:45 +0000 Subject: [PATCH 3/8] Clarify gemini target mapping for antigravity Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/awf_config.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/workflow/awf_config.go b/pkg/workflow/awf_config.go index 362fdfa5084..a8be6133fdc 100644 --- a/pkg/workflow/awf_config.go +++ b/pkg/workflow/awf_config.go @@ -167,6 +167,7 @@ type AWFAPIProxyConfig struct { // Targets holds per-provider API target overrides. // Supported keys: "openai", "anthropic", "copilot", "gemini" + // The "gemini" target is also used for Antigravity engine routing. Targets map[string]*AWFAPITargetConfig `json:"targets,omitempty"` // Models contains model alias and fallback policy definitions. @@ -300,19 +301,18 @@ func BuildAWFConfigJSON(config AWFCommandConfig) (string, error) { targets["copilot"] = &AWFAPITargetConfig{Host: copilotTarget} awfConfigLog.Printf("API proxy: custom copilot target=%s", copilotTarget) } - geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName) if antigravityTarget := GetAntigravityAPITarget(config.WorkflowData, config.EngineName); antigravityTarget != "" { // Route the Antigravity-resolved API target through the "gemini" provider key // to match AWF's supported target providers. + geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName) if geminiTarget != "" && geminiTarget != antigravityTarget { - awfConfigLog.Printf("API proxy: overriding gemini target %s with antigravity target %s", geminiTarget, antigravityTarget) + awfConfigLog.Printf("API proxy: overriding gemini target %s with antigravity target %s; configure only one of GEMINI_API_BASE_URL or ANTIGRAVITY_API_BASE_URL to avoid ambiguity", geminiTarget, antigravityTarget) } - geminiTarget = antigravityTarget awfConfigLog.Printf("API proxy: mapped antigravity target to gemini provider target=%s", antigravityTarget) - } - if geminiTarget != "" { - targets["gemini"] = &AWFAPITargetConfig{Host: geminiTarget} + targets["gemini"] = &AWFAPITargetConfig{Host: antigravityTarget} + } else if geminiTarget := GetGeminiAPITarget(config.WorkflowData, config.EngineName); geminiTarget != "" { awfConfigLog.Printf("API proxy: custom gemini target=%s", geminiTarget) + targets["gemini"] = &AWFAPITargetConfig{Host: geminiTarget} } if len(targets) > 0 { From 36e20fd53a2dc0b66d849b4ee6425259f643067f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 02:36:39 +0000 Subject: [PATCH 4/8] Recompile smoke antigravity lock workflow Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-antigravity.lock.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-antigravity.lock.yml b/.github/workflows/smoke-antigravity.lock.yml index c8219ec2283..224b76d2b2d 100644 --- a/.github/workflows/smoke-antigravity.lock.yml +++ b/.github/workflows/smoke-antigravity.lock.yml @@ -914,7 +914,7 @@ jobs: printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/agent-stdio.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.googleapis.com","*.grafana.net","*.sentry.io","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","docs.github.com","generativelanguage.googleapis.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","patch-diff.githubusercontent.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"targets":{"antigravity":{"host":"generativelanguage.googleapis.com"}},"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/awf-config.schema.json","network":{"allowDomains":["*.githubusercontent.com","*.googleapis.com","*.grafana.net","*.sentry.io","api.snapcraft.io","archive.ubuntu.com","azure.archive.ubuntu.com","codeload.github.com","crl.geotrust.com","crl.globalsign.com","crl.identrust.com","crl.sectigo.com","crl.thawte.com","crl.usertrust.com","crl.verisign.com","crl3.digicert.com","crl4.digicert.com","crls.ssl.com","docs.github.com","generativelanguage.googleapis.com","github-cloud.githubusercontent.com","github-cloud.s3.amazonaws.com","github.blog","github.com","github.githubassets.com","host.docker.internal","json-schema.org","json.schemastore.org","keyserver.ubuntu.com","lfs.github.com","objects.githubusercontent.com","ocsp.digicert.com","ocsp.geotrust.com","ocsp.globalsign.com","ocsp.identrust.com","ocsp.sectigo.com","ocsp.ssl.com","ocsp.thawte.com","ocsp.usertrust.com","ocsp.verisign.com","packagecloud.io","packages.cloud.google.com","packages.microsoft.com","patch-diff.githubusercontent.com","ppa.launchpad.net","raw.githubusercontent.com","registry.npmjs.org","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"targets":{"gemini":{"host":"generativelanguage.googleapis.com"}},"models":{"agent":["sonnet-6x","gpt-5.4","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-4.1":["copilot/gpt-4.1*","openai/gpt-4.1*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"large":["sonnet","gpt-5-pro","gpt-5","gemini-pro"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"vision":["copilot/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then @@ -1450,7 +1450,7 @@ jobs: printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt touch /tmp/gh-aw/agent-step-summary.md (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/awf-config.schema.json","network":{"allowDomains":["*.googleapis.com","generativelanguage.googleapis.com","github.com","host.docker.internal","raw.githubusercontent.com","registry.npmjs.org"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"targets":{"antigravity":{"host":"generativelanguage.googleapis.com"}}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.25.55/awf-config.schema.json","network":{"allowDomains":["*.googleapis.com","generativelanguage.googleapis.com","github.com","host.docker.internal","raw.githubusercontent.com","registry.npmjs.org"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":500,"maxEffectiveTokens":25000000,"targets":{"gemini":{"host":"generativelanguage.googleapis.com"}}},"container":{"imageTag":"0.25.55"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then From 13f69a27912af36abefd9b275ae946d0875aa271 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 02:58:48 +0000 Subject: [PATCH 5/8] Fix antigravity CLI arguments in generated workflow Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-antigravity.lock.yml | 4 ++-- pkg/workflow/antigravity_engine.go | 17 +++-------------- pkg/workflow/antigravity_engine_test.go | 9 +++++---- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/.github/workflows/smoke-antigravity.lock.yml b/.github/workflows/smoke-antigravity.lock.yml index 224b76d2b2d..6c85944402c 100644 --- a/.github/workflows/smoke-antigravity.lock.yml +++ b/.github/workflows/smoke-antigravity.lock.yml @@ -922,7 +922,7 @@ jobs: fi # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ - -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --yolo --skip-trust --output-format stream-json --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --dangerously-skip-permissions --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: ANTIGRAVITY_API_BASE_URL: http://host.docker.internal:10003 ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} @@ -1458,7 +1458,7 @@ jobs: fi # shellcheck disable=SC1003 sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ - -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --yolo --skip-trust --output-format stream-json --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --dangerously-skip-permissions --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log env: ANTIGRAVITY_API_BASE_URL: http://host.docker.internal:10003 ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 915ed593fdb..0f0f65f7c92 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -164,20 +164,9 @@ func (e *AntigravityEngine) GetExecutionSteps(workflowData *WorkflowData, logFil // The conversion script (convert_gateway_config_antigravity.sh) writes settings.json // during the MCP setup step, so no --mcp-config flag is needed here. - // Auto-approve all tool executions (equivalent to Codex's --dangerously-bypass-approvals-and-sandbox) - // Without this, Antigravity CLI's default approval mode rejects tool calls with "Tool execution denied by policy" - agyArgs = append(agyArgs, "--yolo") - - // Skip the workspace trust check so --yolo is not overridden to "default" approval mode. - // Antigravity CLI v1.x checks whether the working directory is trusted and overrides --yolo - // with "default" approval mode (exit code 55) when the folder is untrusted. - // ANTIGRAVITY_CLI_TRUST_WORKSPACE=true (also set in the step env) handles the same case via - // environment variable, but --skip-trust is more reliable when AWF's sandbox does not - // forward all host environment variables into the container. - agyArgs = append(agyArgs, "--skip-trust") - - // Add streaming JSON output (JSONL format, compatible with the log parser) - agyArgs = append(agyArgs, "--output-format", "stream-json") + // Auto-approve all tool executions. + // agy does not support the Gemini-style --yolo/--skip-trust flags. + agyArgs = append(agyArgs, "--dangerously-skip-permissions") // Note: the --prompt argument is appended raw after shellJoinArgs below because it contains // a shell command substitution ("$(cat ...)") that must NOT go through shellEscapeArg — diff --git a/pkg/workflow/antigravity_engine_test.go b/pkg/workflow/antigravity_engine_test.go index a043756c058..06c10ac45a0 100644 --- a/pkg/workflow/antigravity_engine_test.go +++ b/pkg/workflow/antigravity_engine_test.go @@ -151,10 +151,11 @@ func TestAntigravityEngineExecution(t *testing.T) { assert.Contains(t, stepContent, "name: Execute Antigravity CLI", "Should have correct step name") assert.Contains(t, stepContent, "id: agentic_execution", "Should have agentic_execution ID") - assert.Contains(t, stepContent, "agy --yolo", "Should invoke the agy CLI binary as the first token in the command") - assert.Contains(t, stepContent, "--yolo", "Should include --yolo flag for auto-approving tool executions") - assert.Contains(t, stepContent, "--skip-trust", "Should include --skip-trust flag to prevent workspace trust check from overriding --yolo") - assert.Contains(t, stepContent, "--output-format stream-json", "Should use streaming JSON output format") + assert.Contains(t, stepContent, "agy --dangerously-skip-permissions", "Should invoke agy with auto-approval enabled") + assert.Contains(t, stepContent, "--dangerously-skip-permissions", "Should include auto-approval flag for tool executions") + assert.NotContains(t, stepContent, "--yolo", "Should not include unsupported --yolo flag") + assert.NotContains(t, stepContent, "--skip-trust", "Should not include unsupported --skip-trust flag") + assert.NotContains(t, stepContent, "--output-format stream-json", "Should not include unsupported output format flag") assert.Contains(t, stepContent, `--prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"`, "Should include prompt argument with correct shell quoting") assert.Contains(t, stepContent, "/tmp/test.log", "Should include log file") assert.Contains(t, stepContent, "ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }}", "Should set ANTIGRAVITY_API_KEY env var") From a015dfdc0ca380bece00e1168951df3c542484ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 03:02:36 +0000 Subject: [PATCH 6/8] Clarify antigravity permission flag rationale Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/antigravity_engine.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 0f0f65f7c92..8988aac2eb4 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -164,8 +164,9 @@ func (e *AntigravityEngine) GetExecutionSteps(workflowData *WorkflowData, logFil // The conversion script (convert_gateway_config_antigravity.sh) writes settings.json // during the MCP setup step, so no --mcp-config flag is needed here. - // Auto-approve all tool executions. + // Auto-approve all tool executions so non-interactive CI runs don't block on permission prompts. // agy does not support the Gemini-style --yolo/--skip-trust flags. + // This flag grants broad tool permission inside the workflow sandbox, so it is only used in AWF-managed runs. agyArgs = append(agyArgs, "--dangerously-skip-permissions") // Note: the --prompt argument is appended raw after shellJoinArgs below because it contains From 4aeed011daa5a21b917cfdfc28cc9284fc91f585 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 03:34:53 +0000 Subject: [PATCH 7/8] Map antigravity key to Gemini proxy auth env Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-antigravity.lock.yml | 6 ++++-- pkg/workflow/antigravity_engine.go | 10 ++++++++-- pkg/workflow/antigravity_engine_test.go | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/smoke-antigravity.lock.yml b/.github/workflows/smoke-antigravity.lock.yml index 6c85944402c..4dd3d847f7d 100644 --- a/.github/workflows/smoke-antigravity.lock.yml +++ b/.github/workflows/smoke-antigravity.lock.yml @@ -921,13 +921,14 @@ jobs: GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" fi # shellcheck disable=SC1003 - sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --exclude-env GEMINI_API_KEY --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull --difc-proxy-host host.docker.internal:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ -- /bin/bash -c 'export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --dangerously-skip-permissions --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: ANTIGRAVITY_API_BASE_URL: http://host.docker.internal:10003 ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} ANTIGRAVITY_CLI_TRUST_WORKSPACE: true DEBUG: antigravity-cli:* + GEMINI_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} GH_AW_MCP_CONFIG: ${{ github.workspace }}/.antigravity/settings.json GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -1457,13 +1458,14 @@ jobs: GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" fi # shellcheck disable=SC1003 - sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ + sudo -E awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS} --env-all --exclude-env ANTIGRAVITY_API_KEY --exclude-env GEMINI_API_KEY --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --audit-dir /tmp/gh-aw/sandbox/firewall/audit --enable-host-access --allow-host-ports 80,443,8080 --skip-pull \ -- /bin/bash -c 'export PATH="$(find /opt/hostedtoolcache /home/runner/work/_tool -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true && agy --dangerously-skip-permissions --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log env: ANTIGRAVITY_API_BASE_URL: http://host.docker.internal:10003 ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} ANTIGRAVITY_CLI_TRUST_WORKSPACE: true DEBUG: antigravity-cli:* + GEMINI_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_VERSION: dev diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 8988aac2eb4..8020c1852ba 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -223,7 +223,7 @@ func (e *AntigravityEngine) GetExecutionSteps(workflowData *WorkflowData, logFil PathSetup: "touch " + AgentStepSummaryPath, // Exclude every env var whose step-env value is a secret so the agent // cannot read raw token values via bash tools (env / printenv). - ExcludeEnvVarNames: ComputeAWFExcludeEnvVarNames(workflowData, []string{"ANTIGRAVITY_API_KEY"}), + ExcludeEnvVarNames: ComputeAWFExcludeEnvVarNames(workflowData, []string{"ANTIGRAVITY_API_KEY", "GEMINI_API_KEY"}), }) } else { command = fmt.Sprintf(`set -o pipefail @@ -310,6 +310,12 @@ touch %s maps.Copy(env, agentConfig.Env) antigravityLog.Printf("Added %d custom env vars from agent config", len(agentConfig.Env)) } + // The Antigravity CLI and AWF's Gemini API proxy both rely on a Gemini provider key. + // Keep GEMINI_API_KEY aligned with the effective ANTIGRAVITY_API_KEY by default so the + // workflow can authenticate non-interactively without requiring users to duplicate secrets. + if _, hasGeminiKey := env["GEMINI_API_KEY"]; !hasGeminiKey { + env["GEMINI_API_KEY"] = env["ANTIGRAVITY_API_KEY"] + } // Generate the execution step stepLines := []string{ @@ -318,7 +324,7 @@ touch %s } // Filter environment variables for security - allowedSecrets := e.GetRequiredSecretNames(workflowData) + allowedSecrets := append(e.GetRequiredSecretNames(workflowData), "GEMINI_API_KEY") filteredEnv := FilterEnvForSecrets(env, allowedSecrets) // Inject GH_TOKEN for CLI proxy (added after filtering since it uses a special diff --git a/pkg/workflow/antigravity_engine_test.go b/pkg/workflow/antigravity_engine_test.go index 06c10ac45a0..8bd5beb36d9 100644 --- a/pkg/workflow/antigravity_engine_test.go +++ b/pkg/workflow/antigravity_engine_test.go @@ -159,6 +159,7 @@ func TestAntigravityEngineExecution(t *testing.T) { assert.Contains(t, stepContent, `--prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"`, "Should include prompt argument with correct shell quoting") assert.Contains(t, stepContent, "/tmp/test.log", "Should include log file") assert.Contains(t, stepContent, "ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }}", "Should set ANTIGRAVITY_API_KEY env var") + assert.Contains(t, stepContent, "GEMINI_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }}", "Should map GEMINI_API_KEY to the Antigravity secret for proxy auth") }) t.Run("with model", func(t *testing.T) { @@ -227,6 +228,7 @@ func TestAntigravityEngineExecution(t *testing.T) { stepContent := strings.Join(steps[1], "\n") assert.Contains(t, stepContent, "ANTIGRAVITY_API_KEY:", "Should include ANTIGRAVITY_API_KEY") + assert.Contains(t, stepContent, "GEMINI_API_KEY:", "Should include GEMINI_API_KEY alias for proxy auth") assert.Contains(t, stepContent, "GH_AW_PROMPT:", "Should include GH_AW_PROMPT") assert.Contains(t, stepContent, "GITHUB_WORKSPACE:", "Should include GITHUB_WORKSPACE") assert.Contains(t, stepContent, "DEBUG: antigravity-cli:*", "Should include DEBUG env var for verbose diagnostics") @@ -279,6 +281,7 @@ func TestAntigravityEngineExecution(t *testing.T) { // The user-provided value should override the default token expression assert.Contains(t, stepContent, "ANTIGRAVITY_API_KEY: ${{ secrets.MY_ORG_ANTIGRAVITY_KEY }}", "engine.env should override the default ANTIGRAVITY_API_KEY expression") assert.NotContains(t, stepContent, "ANTIGRAVITY_API_KEY: ${{ secrets.ANTIGRAVITY_API_KEY }}", "Default ANTIGRAVITY_API_KEY expression should be replaced by engine.env") + assert.Contains(t, stepContent, "GEMINI_API_KEY: ${{ secrets.MY_ORG_ANTIGRAVITY_KEY }}", "GEMINI_API_KEY alias should track the effective Antigravity key expression") }) t.Run("validates ANTIGRAVITY_API_KEY secret", func(t *testing.T) { @@ -351,6 +354,7 @@ func TestAntigravityEngineFirewallIntegration(t *testing.T) { // With config file support, domains and apiProxy are in the JSON config assert.Contains(t, stepContent, "allowDomains", "Should include allowDomains in config JSON") assert.Contains(t, stepContent, `"enabled":true`, "Should include apiProxy enabled in config JSON") + assert.Contains(t, stepContent, "--exclude-env GEMINI_API_KEY", "Should exclude GEMINI_API_KEY from sandbox env") assert.Contains(t, stepContent, "ANTIGRAVITY_API_BASE_URL: http://host.docker.internal:10003", "Should set ANTIGRAVITY_API_BASE_URL to LLM gateway URL") }) From 875ea786533197b2db687b690cbcc3574a4f5563 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 03:38:46 +0000 Subject: [PATCH 8/8] Avoid mutating required-secrets slice in antigravity env filtering Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/antigravity_engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 8020c1852ba..5061f6a6232 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -324,7 +324,7 @@ touch %s } // Filter environment variables for security - allowedSecrets := append(e.GetRequiredSecretNames(workflowData), "GEMINI_API_KEY") + allowedSecrets := append([]string{"GEMINI_API_KEY"}, e.GetRequiredSecretNames(workflowData)...) filteredEnv := FilterEnvForSecrets(env, allowedSecrets) // Inject GH_TOKEN for CLI proxy (added after filtering since it uses a special