From 5e31ba1d2a10bc6c936edf3ee9b9d9e1f7a52537 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 21:49:59 -0700 Subject: [PATCH 1/7] X-Smart-Branch-Parent: main From 420ff5b26c523ddaba755b11f0a1f747ddd507ac Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 21:52:37 -0700 Subject: [PATCH 2/7] fix: opencode uses direct Vertex AI, not inference.local (Anthropic-only) --- profiles/agent-opencode.yaml | 17 +++++++++++++---- profiles/images/sandbox-default/policy.yaml | 15 ++++++++++++++- test/configs/agent-opencode-vertex.yaml | 9 ++++----- test/suite/run.sh | 7 ++++--- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/profiles/agent-opencode.yaml b/profiles/agent-opencode.yaml index 797121f..9c86350 100644 --- a/profiles/agent-opencode.yaml +++ b/profiles/agent-opencode.yaml @@ -1,8 +1,15 @@ # OpenCode agent configuration. # +# NOTE: OpenCode uses the OpenAI chat completions format, but OpenShell's +# inference.local only supports the Anthropic messages format. OpenCode +# cannot use inference.local for LLM calls. It needs direct access to +# Vertex AI or another OpenAI-compatible endpoint. +# +# Until OpenShell adds OpenAI format support to inference.local, configure +# OpenCode with a direct Vertex AI endpoint or use a separate API key. +# # Usage: -# harness up -f agents/opencode.yaml -# harness up --agent opencode +# harness apply --agent opencode name: opencode-agent entrypoint: opencode @@ -17,6 +24,8 @@ providers: JIRA_USERNAME: ${JIRA_USERNAME} - profile: gws +# OpenCode needs GOOGLE_CLOUD_PROJECT + ADC for Vertex AI directly. +# inference.local does NOT support OpenAI format (/v1/chat/completions). env: - OPENAI_BASE_URL: https://inference.local/v1 - OPENAI_API_KEY: sk-ant-openshell-proxy-managed + GOOGLE_CLOUD_PROJECT: ${ANTHROPIC_VERTEX_PROJECT_ID} + VERTEX_LOCATION: global diff --git a/profiles/images/sandbox-default/policy.yaml b/profiles/images/sandbox-default/policy.yaml index 04a1952..6fbe1d8 100644 --- a/profiles/images/sandbox-default/policy.yaml +++ b/profiles/images/sandbox-default/policy.yaml @@ -37,7 +37,7 @@ process: run_as_group: sandbox network_policies: - # Agent telemetry (inference goes through inference.local, + # Agent telemetry (inference goes through inference.local for Claude, # but telemetry/updates still hit upstream directly) agent_telemetry: name: agent-telemetry @@ -54,6 +54,19 @@ network_policies: - { path: /usr/bin/node } - { path: /usr/lib/node_modules/opencode-ai/bin/opencode.exe } + # OpenCode inference (direct Vertex AI, not inference.local). + # inference.local only supports Anthropic format (/v1/messages). + # OpenCode uses OpenAI format (/v1/chat/completions) so it needs + # direct access to Vertex AI. + opencode_inference: + name: opencode-inference + endpoints: + - { host: "*.googleapis.com", port: 443 } + - { host: "*.cloud.google.com", port: 443 } + binaries: + - { path: /usr/lib/node_modules/opencode-ai/bin/opencode.exe } + - { path: /usr/bin/node } + # Git Smart HTTP transport — allows clone and fetch. # Push (git-receive-pack) is blocked by default. To enable push for # specific repos, use openshell policy set with explicit rules. See: diff --git a/test/configs/agent-opencode-vertex.yaml b/test/configs/agent-opencode-vertex.yaml index de88f6d..f2c46ae 100644 --- a/test/configs/agent-opencode-vertex.yaml +++ b/test/configs/agent-opencode-vertex.yaml @@ -1,11 +1,10 @@ -# OpenCode with Vertex AI via inference.local proxy. -# OpenCode uses OpenAI-compatible API at inference.local/v1. -# The proxy translates to Vertex AI Anthropic models. +# OpenCode with Vertex AI -- direct access (not inference.local). +# inference.local only supports Anthropic format; OpenCode uses OpenAI format. # Requires: gcloud auth application-default login, ANTHROPIC_VERTEX_PROJECT_ID. name: test-opencode entrypoint: opencode providers: - profile: vertex-local env: - OPENAI_BASE_URL: https://inference.local/v1 - OPENAI_API_KEY: sk-ant-openshell-proxy-managed + GOOGLE_CLOUD_PROJECT: ${ANTHROPIC_VERTEX_PROJECT_ID} + VERTEX_LOCATION: global diff --git a/test/suite/run.sh b/test/suite/run.sh index 2c5cbfa..c97be30 100755 --- a/test/suite/run.sh +++ b/test/suite/run.sh @@ -305,12 +305,13 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then "$CLI" sandbox exec --name test-agent-int -- \ bash -c 'result=$(echo "respond with ok" | claude --print 2>&1); test -n "$result"' - # OpenCode uses inference.local/v1 (OpenAI-compatible) via the proxy. + # OpenCode uses Vertex AI directly (not inference.local). + # inference.local only supports Anthropic format; OpenCode uses OpenAI format. SANDBOXES_TO_CLEAN+=(test-opencode-int) run_test "agent: opencode inference via vertex" \ bash -c '"$1" apply -f "$2" --name test-opencode-int >/dev/null 2>&1 && \ for i in $(seq 1 10); do "$1" describe test-opencode-int >/dev/null 2>&1 && break; sleep 0.5; done && \ - result=$("$3" sandbox exec --name test-opencode-int -- bash -c "opencode run \"respond with ok\" 2>&1") && \ + result=$("$3" sandbox exec --name test-opencode-int -- bash -c "opencode run -m google-vertex/claude-sonnet-4-6 \"respond with ok\" 2>&1") && \ test -n "$result"' _ "$HARNESS" "$CONFIGS/agent-opencode-vertex.yaml" "$CLI" if [[ -n "${GITHUB_TOKEN:-}" ]]; then @@ -353,7 +354,7 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then run_test "agent: opencode built-in profile" \ bash -c '"$1" apply --agent opencode --name test-oc-builtin >/dev/null 2>&1 && \ for i in $(seq 1 10); do "$1" describe test-oc-builtin >/dev/null 2>&1 && break; sleep 0.5; done && \ - result=$("$2" sandbox exec --name test-oc-builtin -- bash -c "opencode run \"respond with ok\" 2>&1") && \ + result=$("$2" sandbox exec --name test-oc-builtin -- bash -c "opencode run -m google-vertex/claude-sonnet-4-6 \"respond with ok\" 2>&1") && \ test -n "$result"' _ "$HARNESS" "$CLI" "$HARNESS" delete test-agent-int test-opencode-int test-oc-builtin >/dev/null 2>&1 || true From 24f0d808eddd49a9dc195ce4e9214b293c3768b8 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 21:59:29 -0700 Subject: [PATCH 3/7] fix: allow encoded slashes for npm registry endpoint --- profiles/images/sandbox-default/policy.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/profiles/images/sandbox-default/policy.yaml b/profiles/images/sandbox-default/policy.yaml index 6fbe1d8..6d25bda 100644 --- a/profiles/images/sandbox-default/policy.yaml +++ b/profiles/images/sandbox-default/policy.yaml @@ -134,7 +134,11 @@ network_policies: npm: name: npm endpoints: - - { host: registry.npmjs.org, port: 443 } + - host: registry.npmjs.org + port: 443 + protocol: rest + enforcement: enforce + allow_encoded_slash: true binaries: - { path: /usr/bin/npm } - { path: /usr/bin/node } From eedecb6e39cbf73a9d32510ed32998bbe265aefd Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 22:05:35 -0700 Subject: [PATCH 4/7] fix: document opencode+vertex limitation, skip tests honestly --- profiles/agent-opencode.yaml | 26 +++++++++++++------------- test/suite/run.sh | 22 +++++----------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/profiles/agent-opencode.yaml b/profiles/agent-opencode.yaml index 9c86350..392b1b8 100644 --- a/profiles/agent-opencode.yaml +++ b/profiles/agent-opencode.yaml @@ -1,12 +1,19 @@ # OpenCode agent configuration. # -# NOTE: OpenCode uses the OpenAI chat completions format, but OpenShell's -# inference.local only supports the Anthropic messages format. OpenCode -# cannot use inference.local for LLM calls. It needs direct access to -# Vertex AI or another OpenAI-compatible endpoint. +# LIMITATION: OpenCode inference via Vertex AI is not currently supported +# in OpenShell sandboxes. Two blockers: +# 1. inference.local only supports Anthropic format (/v1/messages). +# OpenCode uses OpenAI format (/v1/chat/completions). +# 2. Direct Vertex AI access requires ADC credentials on disk. +# OpenShell's proxy-managed credential model doesn't expose raw +# ADC files inside the sandbox. # -# Until OpenShell adds OpenAI format support to inference.local, configure -# OpenCode with a direct Vertex AI endpoint or use a separate API key. +# OpenCode CAN use the sandbox for MCP tools (Jira, GWS), GitHub, +# and other providers -- just not for inference via Vertex AI. +# +# Workarounds: +# - Use an OpenAI API key provider (e.g., groq, openrouter) instead +# - Wait for OpenShell to add OpenAI format support to inference.local # # Usage: # harness apply --agent opencode @@ -17,15 +24,8 @@ tty: true providers: - profile: github - - profile: vertex-local - profile: atlassian env: JIRA_URL: ${JIRA_URL} JIRA_USERNAME: ${JIRA_USERNAME} - profile: gws - -# OpenCode needs GOOGLE_CLOUD_PROJECT + ADC for Vertex AI directly. -# inference.local does NOT support OpenAI format (/v1/chat/completions). -env: - GOOGLE_CLOUD_PROJECT: ${ANTHROPIC_VERTEX_PROJECT_ID} - VERTEX_LOCATION: global diff --git a/test/suite/run.sh b/test/suite/run.sh index c97be30..bae562e 100755 --- a/test/suite/run.sh +++ b/test/suite/run.sh @@ -305,14 +305,9 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then "$CLI" sandbox exec --name test-agent-int -- \ bash -c 'result=$(echo "respond with ok" | claude --print 2>&1); test -n "$result"' - # OpenCode uses Vertex AI directly (not inference.local). - # inference.local only supports Anthropic format; OpenCode uses OpenAI format. - SANDBOXES_TO_CLEAN+=(test-opencode-int) - run_test "agent: opencode inference via vertex" \ - bash -c '"$1" apply -f "$2" --name test-opencode-int >/dev/null 2>&1 && \ - for i in $(seq 1 10); do "$1" describe test-opencode-int >/dev/null 2>&1 && break; sleep 0.5; done && \ - result=$("$3" sandbox exec --name test-opencode-int -- bash -c "opencode run -m google-vertex/claude-sonnet-4-6 \"respond with ok\" 2>&1") && \ - test -n "$result"' _ "$HARNESS" "$CONFIGS/agent-opencode-vertex.yaml" "$CLI" + # OpenCode + Vertex AI is not supported in sandboxes: + # inference.local is Anthropic-only, and direct Vertex needs ADC on disk. + skip_test "agent: opencode inference via vertex" "inference.local is Anthropic-only, ADC not available in sandbox" if [[ -n "${GITHUB_TOKEN:-}" ]]; then run_test "agent: github via gh cli" \ @@ -341,31 +336,24 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then fi else skip_test "agent: claude inference via vertex" "sandbox not ready" - skip_test "agent: opencode inference via vertex" "sandbox not ready" skip_test "agent: github via gh cli" "sandbox not ready" skip_test "agent: claude uses jira mcp" "sandbox not ready" skip_test "agent: gws gmail via proxy token" "sandbox not ready" - skip_test "agent: opencode built-in profile" "sandbox not ready" fi # Test the built-in opencode profile (--agent opencode) with all providers. # Verifies the shipped profile works end-to-end with Vertex via inference.local/v1. SANDBOXES_TO_CLEAN+=(test-oc-builtin) - run_test "agent: opencode built-in profile" \ - bash -c '"$1" apply --agent opencode --name test-oc-builtin >/dev/null 2>&1 && \ - for i in $(seq 1 10); do "$1" describe test-oc-builtin >/dev/null 2>&1 && break; sleep 0.5; done && \ - result=$("$2" sandbox exec --name test-oc-builtin -- bash -c "opencode run -m google-vertex/claude-sonnet-4-6 \"respond with ok\" 2>&1") && \ - test -n "$result"' _ "$HARNESS" "$CLI" + # OpenCode inference via Vertex not supported in sandbox (see agent-opencode.yaml) + skip_test "agent: opencode built-in profile" "inference.local is Anthropic-only" "$HARNESS" delete test-agent-int test-opencode-int test-oc-builtin >/dev/null 2>&1 || true "$HARNESS" delete --sandboxes --providers >/dev/null 2>&1 || true else skip_test "agent: claude inference via vertex" "ANTHROPIC_VERTEX_PROJECT_ID not set" - skip_test "agent: opencode inference via vertex" "ANTHROPIC_VERTEX_PROJECT_ID not set" skip_test "agent: github via gh cli" "ANTHROPIC_VERTEX_PROJECT_ID not set" skip_test "agent: claude uses jira mcp" "ANTHROPIC_VERTEX_PROJECT_ID not set" skip_test "agent: gws gmail via proxy token" "ANTHROPIC_VERTEX_PROJECT_ID not set" - skip_test "agent: opencode built-in profile" "ANTHROPIC_VERTEX_PROJECT_ID not set" fi echo "" From 03b0eaa2590d197726247bb5e68a44c7e17c4506 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 22:13:13 -0700 Subject: [PATCH 5/7] fix: opencode uses ANTHROPIC_BASE_URL with inference.local/v1 --- profiles/agent-opencode.yaml | 24 ++++++++++-------------- test/configs/agent-opencode-vertex.yaml | 8 ++++---- test/suite/run.sh | 18 +++++++++++++----- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/profiles/agent-opencode.yaml b/profiles/agent-opencode.yaml index 392b1b8..ffd96d4 100644 --- a/profiles/agent-opencode.yaml +++ b/profiles/agent-opencode.yaml @@ -1,19 +1,9 @@ # OpenCode agent configuration. # -# LIMITATION: OpenCode inference via Vertex AI is not currently supported -# in OpenShell sandboxes. Two blockers: -# 1. inference.local only supports Anthropic format (/v1/messages). -# OpenCode uses OpenAI format (/v1/chat/completions). -# 2. Direct Vertex AI access requires ADC credentials on disk. -# OpenShell's proxy-managed credential model doesn't expose raw -# ADC files inside the sandbox. -# -# OpenCode CAN use the sandbox for MCP tools (Jira, GWS), GitHub, -# and other providers -- just not for inference via Vertex AI. -# -# Workarounds: -# - Use an OpenAI API key provider (e.g., groq, openrouter) instead -# - Wait for OpenShell to add OpenAI format support to inference.local +# OpenCode uses ANTHROPIC_BASE_URL with inference.local/v1 (note the /v1 suffix). +# Without /v1, OpenCode sends POST /messages instead of POST /v1/messages, +# which doesn't match the inference route pattern. +# See: https://github.com/NVIDIA/OpenShell/blob/main/docs/providers/google-vertex-ai.mdx # # Usage: # harness apply --agent opencode @@ -24,8 +14,14 @@ tty: true providers: - profile: github + - profile: vertex-local - profile: atlassian env: JIRA_URL: ${JIRA_URL} JIRA_USERNAME: ${JIRA_USERNAME} - profile: gws + +# OpenCode needs /v1 suffix on ANTHROPIC_BASE_URL (different from Claude Code). +env: + ANTHROPIC_BASE_URL: https://inference.local/v1 + ANTHROPIC_API_KEY: sk-ant-openshell-proxy-managed diff --git a/test/configs/agent-opencode-vertex.yaml b/test/configs/agent-opencode-vertex.yaml index f2c46ae..06c9908 100644 --- a/test/configs/agent-opencode-vertex.yaml +++ b/test/configs/agent-opencode-vertex.yaml @@ -1,10 +1,10 @@ -# OpenCode with Vertex AI -- direct access (not inference.local). -# inference.local only supports Anthropic format; OpenCode uses OpenAI format. +# OpenCode with Vertex AI via inference.local/v1. +# OpenCode uses ANTHROPIC_BASE_URL (not OPENAI_BASE_URL) with /v1 suffix. # Requires: gcloud auth application-default login, ANTHROPIC_VERTEX_PROJECT_ID. name: test-opencode entrypoint: opencode providers: - profile: vertex-local env: - GOOGLE_CLOUD_PROJECT: ${ANTHROPIC_VERTEX_PROJECT_ID} - VERTEX_LOCATION: global + ANTHROPIC_BASE_URL: https://inference.local/v1 + ANTHROPIC_API_KEY: sk-ant-openshell-proxy-managed diff --git a/test/suite/run.sh b/test/suite/run.sh index bae562e..655f291 100755 --- a/test/suite/run.sh +++ b/test/suite/run.sh @@ -305,9 +305,13 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then "$CLI" sandbox exec --name test-agent-int -- \ bash -c 'result=$(echo "respond with ok" | claude --print 2>&1); test -n "$result"' - # OpenCode + Vertex AI is not supported in sandboxes: - # inference.local is Anthropic-only, and direct Vertex needs ADC on disk. - skip_test "agent: opencode inference via vertex" "inference.local is Anthropic-only, ADC not available in sandbox" + # OpenCode uses ANTHROPIC_BASE_URL=inference.local/v1 (note /v1 suffix) + SANDBOXES_TO_CLEAN+=(test-opencode-int) + run_test "agent: opencode inference via vertex" \ + bash -c '"$1" apply -f "$2" --name test-opencode-int >/dev/null 2>&1 && \ + for i in $(seq 1 10); do "$1" describe test-opencode-int >/dev/null 2>&1 && break; sleep 0.5; done && \ + result=$("$3" sandbox exec --name test-opencode-int -- bash -c "opencode run \"respond with ok\" 2>&1") && \ + test -n "$result"' _ "$HARNESS" "$CONFIGS/agent-opencode-vertex.yaml" "$CLI" if [[ -n "${GITHUB_TOKEN:-}" ]]; then run_test "agent: github via gh cli" \ @@ -344,8 +348,12 @@ if $LIVE && "$CLI" inference get >/dev/null 2>&1; then # Test the built-in opencode profile (--agent opencode) with all providers. # Verifies the shipped profile works end-to-end with Vertex via inference.local/v1. SANDBOXES_TO_CLEAN+=(test-oc-builtin) - # OpenCode inference via Vertex not supported in sandbox (see agent-opencode.yaml) - skip_test "agent: opencode built-in profile" "inference.local is Anthropic-only" + SANDBOXES_TO_CLEAN+=(test-oc-builtin) + run_test "agent: opencode built-in profile" \ + bash -c '"$1" apply --agent opencode --name test-oc-builtin >/dev/null 2>&1 && \ + for i in $(seq 1 10); do "$1" describe test-oc-builtin >/dev/null 2>&1 && break; sleep 0.5; done && \ + result=$("$2" sandbox exec --name test-oc-builtin -- bash -c "opencode run \"respond with ok\" 2>&1") && \ + test -n "$result"' _ "$HARNESS" "$CLI" "$HARNESS" delete test-agent-int test-opencode-int test-oc-builtin >/dev/null 2>&1 || true "$HARNESS" delete --sandboxes --providers >/dev/null 2>&1 || true From 4d9fa7879b5f587a703ae37b66788c20a8b5aa87 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 22:36:18 -0700 Subject: [PATCH 6/7] fix: revert policy changes that crash sandbox supervisor on 0.0.59 --- profiles/images/sandbox-default/policy.yaml | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/profiles/images/sandbox-default/policy.yaml b/profiles/images/sandbox-default/policy.yaml index 6d25bda..04a1952 100644 --- a/profiles/images/sandbox-default/policy.yaml +++ b/profiles/images/sandbox-default/policy.yaml @@ -37,7 +37,7 @@ process: run_as_group: sandbox network_policies: - # Agent telemetry (inference goes through inference.local for Claude, + # Agent telemetry (inference goes through inference.local, # but telemetry/updates still hit upstream directly) agent_telemetry: name: agent-telemetry @@ -54,19 +54,6 @@ network_policies: - { path: /usr/bin/node } - { path: /usr/lib/node_modules/opencode-ai/bin/opencode.exe } - # OpenCode inference (direct Vertex AI, not inference.local). - # inference.local only supports Anthropic format (/v1/messages). - # OpenCode uses OpenAI format (/v1/chat/completions) so it needs - # direct access to Vertex AI. - opencode_inference: - name: opencode-inference - endpoints: - - { host: "*.googleapis.com", port: 443 } - - { host: "*.cloud.google.com", port: 443 } - binaries: - - { path: /usr/lib/node_modules/opencode-ai/bin/opencode.exe } - - { path: /usr/bin/node } - # Git Smart HTTP transport — allows clone and fetch. # Push (git-receive-pack) is blocked by default. To enable push for # specific repos, use openshell policy set with explicit rules. See: @@ -134,11 +121,7 @@ network_policies: npm: name: npm endpoints: - - host: registry.npmjs.org - port: 443 - protocol: rest - enforcement: enforce - allow_encoded_slash: true + - { host: registry.npmjs.org, port: 443 } binaries: - { path: /usr/bin/npm } - { path: /usr/bin/node } From 582baee728db32a3b236f59c83a8034afa6a2da8 Mon Sep 17 00:00:00 2001 From: Robby Cochran Date: Tue, 16 Jun 2026 22:49:52 -0700 Subject: [PATCH 7/7] fix: opencode.json uses command array and environment key --- profiles/images/sandbox-default/opencode.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/profiles/images/sandbox-default/opencode.json b/profiles/images/sandbox-default/opencode.json index 8a8d30e..7e32ede 100644 --- a/profiles/images/sandbox-default/opencode.json +++ b/profiles/images/sandbox-default/opencode.json @@ -1,11 +1,11 @@ { + "$schema": "https://opencode.ai/config.json", "mcp": { "atlassian": { "type": "local", - "command": "/sandbox/.venv/bin/mcp-atlassian", - "args": [], + "command": ["/sandbox/.venv/bin/mcp-atlassian"], "enabled": true, - "env": { + "environment": { "READ_ONLY_MODE": "true" } }