Documentation
¶
Overview ¶
Package vertex resolves Google Cloud Application Default Credentials into the short-lived OAuth access tokens Vertex AI requests carry.
Unlike every other provider yottacode talks to, Vertex has no API key: the credential is an access token that expires in ~1 hour, so it has to be minted per request rather than read once from api_key_env. That is the whole reason the vertex kinds exist separately from openai-compatible — see internal/adapter/vertex.go.
Index ¶
- Constants
- Variables
- func AccessMap(provider, baseURL string) (map[string]bool, bool)
- func DefaultModelsPath(provider, baseURL string) (string, error)
- func OKNames(results []ScanResult) []string
- func ProjectLocation(raw string) (project, location string)
- func SaveModels(path string, mf ModelsFile) error
- type Access
- type ModelsFile
- type ScanOptions
- type ScanResult
- type ScannerTokenSource
- type TokenSource
Constants ¶
const ( ProviderVertex = "vertex" ProviderVertexAnthropic = "vertex-anthropic" )
Model access scans are scoped to one Vertex provider kind plus one project/location base URL. Vertex's public model catalog says which models exist, but access is granted per GCP project and location, so the picker needs a local cache of what this project can actually call.
const Scope = "https://www.googleapis.com/auth/cloud-platform"
Scope is the OAuth scope every Vertex AI call needs. cloud-platform is the coarse grant Google documents for aiplatform.googleapis.com; there is no narrower scope that covers streamGenerateContent/streamRawPredict.
const SetupHint = "run `gcloud auth application-default login`, or point $GOOGLE_APPLICATION_CREDENTIALS at a service-account key"
SetupHint is the actionable half of every credential error here. Single source of truth so the adapter, /doctor, and the picker all say the same thing.
Variables ¶
var ErrModelsNotFound = errors.New("vertex: no models access file")
ErrModelsNotFound is returned when no scan cache exists for a provider base URL. Missing means access is unknown, not unavailable.
Functions ¶
func AccessMap ¶
AccessMap loads the last scan and returns a model id -> available map containing only models with a *definitive* verdict: reachable models map to true, models Vertex explicitly denied (403/404) map to false. Models whose probe was inconclusive (network error, cancellation, 5xx) are omitted, so the picker treats them as not-yet-scanned rather than denied. The second return is false only when no scan file exists at all, letting callers distinguish "never scanned" from "scanned, access known".
func DefaultModelsPath ¶
DefaultModelsPath returns the per-project/location model-access cache path under ~/.yottacode/auth/vertex-models/.
func OKNames ¶
func OKNames(results []ScanResult) []string
OKNames returns successful model ids in scan order.
func ProjectLocation ¶
ProjectLocation extracts the /projects/<p>/locations/<l> pair from a Vertex base_url. It tolerates extra suffixes such as /endpoints/openapi.
func SaveModels ¶
func SaveModels(path string, mf ModelsFile) error
SaveModels writes a Vertex access cache atomically with private file permissions; the file records project model access and may include provider error text.
Types ¶
type Access ¶
type Access string
Access is the three-state verdict a probe produces. Only AccessDenied greys a model out in the picker; AccessUnknown — a transport failure, a cancellation, a 5xx, or any status that isn't a per-model verdict — is indistinguishable from "never scanned" and must never disable a model that may well be callable.
type ModelsFile ¶
type ModelsFile struct {
ScannedAt time.Time `json:"scanned_at"`
Provider string `json:"provider"`
BaseURL string `json:"base_url"`
Project string `json:"project,omitempty"`
Location string `json:"location,omitempty"`
Candidates []string `json:"candidates"`
Models []string `json:"models"`
Results []ScanResult `json:"results,omitempty"`
}
ModelsFile is the on-disk shape of a successful Vertex access scan. Models is the OK-only list that pickers use; Results preserves the rejected rows so users can audit why a model is greyed out.
func LoadModels ¶
func LoadModels(path string) (ModelsFile, error)
LoadModels reads a Vertex access cache. ErrModelsNotFound means the user has not scanned this project/location yet.
func PersistScan ¶
func PersistScan(provider, baseURL string, candidates []string, results []ScanResult) (ModelsFile, string, error)
PersistScan writes the result of a completed scan to the cache path for provider/baseURL. It writes even when zero models are available, because that is useful evidence for the picker and for debugging IAM/location mistakes.
func ScanAndPersist ¶
func ScanAndPersist(ctx context.Context, opts ScanOptions) (ModelsFile, string, error)
ScanAndPersist runs Scan and writes the model-access cache for this provider/baseURL. It persists denials too (not just the reachable set) so the picker can grey out models Vertex explicitly refused; models whose probe was inconclusive are recorded as unknown and left enabled.
type ScanOptions ¶
type ScanOptions struct {
HTTPClient *http.Client
Provider string
BaseURL string
Candidates []string
TokenSource ScannerTokenSource
}
ScanOptions tunes Scan. Zero values use production defaults.
type ScanResult ¶
type ScanResult struct {
Name string `json:"name"`
OK bool `json:"ok"`
Access Access `json:"access"`
Status string `json:"status"`
Detail string `json:"detail,omitempty"`
}
ScanResult captures one candidate model's access probe outcome.
func Scan ¶
func Scan(ctx context.Context, opts ScanOptions) ([]ScanResult, error)
Scan probes each candidate model against one configured Vertex provider. It sends tiny non-streaming requests and records per-model access. A 200 proves the project/location can call the model; a 429 is also treated as accessible because quota/rate limiting means Vertex recognized the model for the project.
A 403 or 404 is a definitive denial (no permission / not published in this project+location); every other outcome — a transport error, a cancellation, a 400/401, or a 5xx — is recorded as unknown rather than denied, so an inconclusive probe never greys out a model that may be callable.
func (ScanResult) EffectiveAccess ¶
func (r ScanResult) EffectiveAccess() Access
EffectiveAccess returns the stored verdict, reconstructing it from the legacy ok/status fields when reading a pre-Access scan file so old caches degrade to the corrected (fail-open) semantics instead of the old "any non-OK means denied" conflation.
type ScannerTokenSource ¶
TokenSource is the token seam used by the scanner. *TokenSource from source.go satisfies it, while tests can inject static tokens.
type TokenSource ¶
type TokenSource struct {
// contains filtered or unexported fields
}
TokenSource hands out Vertex access tokens, resolving Application Default Credentials on first use.
Credential lookup is lazy, not done at construction: FindDefaultCredentials probes the GCE metadata server when no file or env var is present, and paying that timeout on every TUI startup — including for users who have never touched Vertex — is not worth failing a millisecond earlier.
Safe for concurrent use. The mutex guards the one-time credential load; token caching and refresh happen inside the oauth2 reuse-source, which is itself concurrency-safe.
func NewTokenSource ¶
func NewTokenSource() *TokenSource
NewTokenSource returns a TokenSource backed by Application Default Credentials.
func (*TokenSource) ProjectID ¶
func (s *TokenSource) ProjectID(ctx context.Context) string
ProjectID reports the project the resolved credentials belong to, or "" when the credentials carry none (user ADC often does not). Callers must not depend on it — yottacode takes the project from the provider's base_url, not from the credential.