Files
OpenShell/proto/inference.proto
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

126 lines
4.2 KiB
Protocol Buffer

// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
syntax = "proto3";
package openshell.inference.v1;
import "datamodel.proto";
// Inference service provides cluster inference configuration and bundle delivery.
service Inference {
// Return the resolved inference route bundle for sandbox-local execution.
rpc GetInferenceBundle(GetInferenceBundleRequest)
returns (GetInferenceBundleResponse);
// Set cluster-level inference configuration.
//
// This controls how requests sent to `inference.local` are routed.
rpc SetClusterInference(SetClusterInferenceRequest)
returns (SetClusterInferenceResponse);
// Get cluster-level inference configuration.
rpc GetClusterInference(GetClusterInferenceRequest)
returns (GetClusterInferenceResponse);
}
// Persisted cluster inference configuration.
//
// Only `provider_name` and `model_id` are stored; endpoint, protocols,
// credentials, and auth style are resolved from the provider at bundle time.
message ClusterInferenceConfig {
// Provider record name backing this route.
string provider_name = 1;
// Model identifier to force on generation calls.
string model_id = 2;
// Per-route request timeout in seconds. 0 means use default (60s).
uint64 timeout_secs = 3;
}
// Storage envelope for the managed cluster inference route.
message InferenceRoute {
openshell.datamodel.v1.ObjectMeta metadata = 1;
ClusterInferenceConfig config = 2;
// Monotonic version incremented on every update.
uint64 version = 3;
}
message SetClusterInferenceRequest {
// Provider record name to use for credentials + endpoint mapping.
string provider_name = 1;
// Model identifier to force on generation calls.
string model_id = 2;
// Route name to target. Empty string defaults to "inference.local" (user-facing).
// Use "sandbox-system" for the sandbox system-level inference route.
string route_name = 3;
// Verify the resolved upstream endpoint synchronously before persistence.
bool verify = 4;
// Skip synchronous endpoint validation before persistence.
bool no_verify = 5;
// Per-route request timeout in seconds. 0 means use default (60s).
uint64 timeout_secs = 6;
}
message ValidatedEndpoint {
string url = 1;
string protocol = 2;
}
message SetClusterInferenceResponse {
string provider_name = 1;
string model_id = 2;
uint64 version = 3;
// Route name that was configured.
string route_name = 4;
// Whether endpoint verification ran as part of this request.
bool validation_performed = 5;
// The concrete endpoints that were probed during validation, when available.
repeated ValidatedEndpoint validated_endpoints = 6;
// Per-route request timeout in seconds that was persisted.
uint64 timeout_secs = 7;
}
message GetClusterInferenceRequest {
// Route name to query. Empty string defaults to "inference.local" (user-facing).
// Use "sandbox-system" for the sandbox system-level inference route.
string route_name = 1;
}
message GetClusterInferenceResponse {
string provider_name = 1;
string model_id = 2;
uint64 version = 3;
// Route name that was queried.
string route_name = 4;
// Per-route request timeout in seconds. 0 means default (60s).
uint64 timeout_secs = 5;
}
message GetInferenceBundleRequest {}
// A single resolved route ready for sandbox-local execution.
message ResolvedRoute {
string name = 1;
string base_url = 2;
repeated string protocols = 3;
string api_key = 4;
string model_id = 5;
string provider_type = 6;
// Per-route request timeout in seconds. 0 means use default (60s).
uint64 timeout_secs = 7;
// When true, the model identifier is embedded in the URL path (e.g. Vertex AI).
bool model_in_path = 8;
// Optional override for the request path. When set, replaces the protocol-derived path.
// An empty string means POST directly to base_url/model_id with no additional path.
optional string request_path_override = 9;
}
message GetInferenceBundleResponse {
repeated ResolvedRoute routes = 1;
// Opaque revision tag for cache freshness checks.
string revision = 2;
// Timestamp (epoch ms) when this bundle was generated.
int64 generated_at_ms = 3;
}