Files
OpenShell/crates/openshell-router
Adam Miller f061b1d923 feat(providers): add Google Vertex AI inference provider (#1568)
* feat(providers): add Google Vertex AI provider

Adds Vertex AI provider profiles, routing, credential refresh plumbing, CLI support, docs, and regression coverage. Keeps the related NETLINK_ROUTE seccomp allowance needed by Vertex client tooling that calls getifaddrs.

* docs: add Vertex AI sandbox usage for Claude Code and OpenCode

Cover the full end-to-end setup for running Claude Code and OpenCode
inside an OpenShell sandbox via inference.local with a Vertex AI backend:

- google-vertex-ai.mdx: add 'Use from a Sandbox' section with tabbed
  examples for Claude Code (--bare flag, no /v1 suffix) and OpenCode
  (/v1 suffix required). Add providers_v2_enabled prerequisite and
  --no-verify note for global region. Document policy proposals table
  covering metadata.google.internal (always blocked), downloads.claude.ai,
  and storage.googleapis.com.

- inference-routing.mdx: expand 'Use the Local Endpoint' section with
  tabbed examples for Claude Code, OpenCode, Python OpenAI SDK, and
  Python Anthropic SDK. Add notes explaining the /v1 path suffix
  difference between clients.

- supported-agents.mdx: update Claude Code and OpenCode rows to mention
  inference.local support and correct base URL requirements.

* fix: address vertex review findings

* test(sandbox): retry on spurious Ok in fork-exec ambiguity test

On arm64 under heavy CI load, the /proc fd scan in
find_socket_inode_owners can transiently miss the parent process's
socket fd entry, returning only the child as an owner. This causes
resolve_process_identity to return Ok (single owner, no ambiguity
check fires) instead of the expected ambiguous-ownership Err.

Extend the retry loop to also handle unexpected Ok results, mirroring
the existing retry for transient Err results. 10 retries at 50ms gives
a 500ms settling window, which is sufficient for procfs to stabilize
on loaded arm64 runners.

* fix: address vertex review regressions

* docs(router): clarify stream_response semantics for Vertex rawPredict routing

Document the three call sites of prepare_backend_request and their
stream_response values in a caller table:

- send_backend_request: false → :rawPredict (unary endpoint)
- send_backend_request_streaming: true → :streamRawPredict
- verify_backend_endpoint: explicitly false to probe the unary endpoint

Cross-reference the table from build_provider_url and
is_vertex_anthropic_rawpredict_route so the stream_response=true guard
in the suffix upgrade branch is understood in full context.

Also note that is_vertex_anthropic_rawpredict_route is a structural
predicate (model_in_path + anthropic_messages + :rawPredict suffix),
not a named-provider check, so any future provider with the same route
shape inherits the transforms automatically.
2026-06-02 10:45:50 -05:00
..

openshell-router

openshell-router is the inference routing and upstream execution engine used by the sandbox proxy and gateway inference validation paths.

Responsibilities

  • Select an upstream route from a candidate set (based on protocol compatibility).
  • Forward raw HTTP requests to the selected upstream backend.
  • Normalize upstream failures into router-level errors (unauthorized, unavailable, protocol/internal errors).
  • Keep routing decision logic in one place so strategies can evolve (fallbacks, scoring, health-based routing).

Non-responsibilities

  • Authentication and sandbox identity.
  • Authorization and policy enforcement.
  • Persistence of routes/entities.
  • Loading sandbox or policy objects.

These are owned by openshell-server and openshell-sandbox.

Integration Contract

Current split:

  • openshell-server:
    • authenticates user-facing inference configuration changes
    • resolves managed route candidates from provider records
    • validates backend endpoints
  • openshell-sandbox:
    • intercepts https://inference.local
    • detects the source inference protocol
    • passes sanitized requests and resolved route candidates to the router
  • openshell-router:
    • picks a route from candidates (proxy_with_candidates)
    • forwards the HTTP request upstream and returns the raw response

Public APIs

  • Router::proxy_with_candidates(source_protocol, method, path, headers, body, &[ResolvedRoute])
    • Filters candidates by protocol compatibility, then forwards the request to the first match.
    • Preferred path for entity-driven server routing.

Notes

  • Route selection matches candidates by protocol field (e.g. openai_chat_completions).
  • Route selection is intentionally simple and will evolve.