From fdeef4849821edbd9216ea8710e5e897e883d3a3 Mon Sep 17 00:00:00 2001 From: dinhkarate Date: Thu, 29 Jan 2026 11:38:08 +0700 Subject: [PATCH 1/3] feat(vertex): Add Prefix field to VertexCredentialStorage for per-file model namespacing --- .gitignore | 6 ++++++ internal/auth/vertex/vertex_credentials.go | 3 +++ 2 files changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index 183138f9..b1c2beef 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,9 @@ _bmad-output/* # macOS .DS_Store ._* + +# Opencode +.beads/ +.opencode/ +.cli-proxy-api/ +.venv/ \ No newline at end of file diff --git a/internal/auth/vertex/vertex_credentials.go b/internal/auth/vertex/vertex_credentials.go index 4853d340..3ae3288e 100644 --- a/internal/auth/vertex/vertex_credentials.go +++ b/internal/auth/vertex/vertex_credentials.go @@ -30,6 +30,9 @@ type VertexCredentialStorage struct { // Type is the provider identifier stored alongside credentials. Always "vertex". Type string `json:"type"` + + // Prefix optionally namespaces models for this credential (e.g., "teamA/gemini-2.0-flash"). + Prefix string `json:"prefix,omitempty"` } // SaveTokenToFile writes the credential payload to the given file path in JSON format. From 14cb2b95c6d8fec2128a9108a5d90ad7b467ecf9 Mon Sep 17 00:00:00 2001 From: dinhkarate Date: Thu, 29 Jan 2026 13:29:55 +0700 Subject: [PATCH 2/3] feat(vertex): add --vertex-import-prefix flag for model namespacing --- cmd/server/main.go | 4 +++- internal/cmd/vertex_import.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 385d7cfa..740a7511 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -65,6 +65,7 @@ func main() { var antigravityLogin bool var projectID string var vertexImport string + var vertexImportPrefix string var configPath string var password string @@ -81,6 +82,7 @@ func main() { flag.StringVar(&projectID, "project_id", "", "Project ID (Gemini only, not required)") flag.StringVar(&configPath, "config", DefaultConfigPath, "Configure File Path") flag.StringVar(&vertexImport, "vertex-import", "", "Import Vertex service account key JSON file") + flag.StringVar(&vertexImportPrefix, "vertex-import-prefix", "", "Prefix for Vertex model namespacing (use with -vertex-import)") flag.StringVar(&password, "password", "", "") flag.CommandLine.Usage = func() { @@ -449,7 +451,7 @@ func main() { if vertexImport != "" { // Handle Vertex service account import - cmd.DoVertexImport(cfg, vertexImport) + cmd.DoVertexImport(cfg, vertexImport, vertexImportPrefix) } else if login { // Handle Google/Gemini login cmd.DoLogin(cfg, projectID, options) diff --git a/internal/cmd/vertex_import.go b/internal/cmd/vertex_import.go index 32d782d8..034906ac 100644 --- a/internal/cmd/vertex_import.go +++ b/internal/cmd/vertex_import.go @@ -20,7 +20,7 @@ import ( // DoVertexImport imports a Google Cloud service account key JSON and persists // it as a "vertex" provider credential. The file content is embedded in the auth // file to allow portable deployment across stores. -func DoVertexImport(cfg *config.Config, keyPath string) { +func DoVertexImport(cfg *config.Config, keyPath string, prefix string) { if cfg == nil { cfg = &config.Config{} } @@ -69,6 +69,7 @@ func DoVertexImport(cfg *config.Config, keyPath string) { ProjectID: projectID, Email: email, Location: location, + Prefix: strings.TrimSpace(prefix), } metadata := map[string]any{ "service_account": sa, From 36efcc6e2860051c9976cf9aa5a4f5a08dc8bcec Mon Sep 17 00:00:00 2001 From: dinhkarate Date: Tue, 17 Mar 2026 15:06:04 +0700 Subject: [PATCH 3/3] fix(vertex): include prefix in auth filename and validate at import Address two blocking issues from PR review: - Auth file now named vertex-{prefix}-{project}.json so importing the same project with different prefixes no longer overwrites credentials - Prefix containing "/" is rejected at import time instead of being silently ignored at runtime - Add prefix to in-memory metadata map for consistency Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 2 +- internal/auth/vertex/vertex_credentials.go | 3 ++- internal/cmd/vertex_import.go | 19 +++++++++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 38152671..858577d0 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,4 @@ _bmad-output/* .beads/ .opencode/ .cli-proxy-api/ -.venv/ \ No newline at end of file +.venv/ diff --git a/internal/auth/vertex/vertex_credentials.go b/internal/auth/vertex/vertex_credentials.go index 3ae3288e..9f830994 100644 --- a/internal/auth/vertex/vertex_credentials.go +++ b/internal/auth/vertex/vertex_credentials.go @@ -31,7 +31,8 @@ type VertexCredentialStorage struct { // Type is the provider identifier stored alongside credentials. Always "vertex". Type string `json:"type"` - // Prefix optionally namespaces models for this credential (e.g., "teamA/gemini-2.0-flash"). + // Prefix optionally namespaces models for this credential (e.g., "teamA"). + // This results in model names like "teamA/gemini-2.0-flash". Prefix string `json:"prefix,omitempty"` } diff --git a/internal/cmd/vertex_import.go b/internal/cmd/vertex_import.go index 034906ac..4aa0d74b 100644 --- a/internal/cmd/vertex_import.go +++ b/internal/cmd/vertex_import.go @@ -62,14 +62,28 @@ func DoVertexImport(cfg *config.Config, keyPath string, prefix string) { // Default location if not provided by user. Can be edited in the saved file later. location := "us-central1" - fileName := fmt.Sprintf("vertex-%s.json", sanitizeFilePart(projectID)) + // Normalize and validate prefix: must be a single segment (no "/" allowed). + prefix = strings.TrimSpace(prefix) + prefix = strings.Trim(prefix, "/") + if prefix != "" && strings.Contains(prefix, "/") { + log.Errorf("vertex-import: prefix must be a single segment (no '/' allowed): %q", prefix) + return + } + + // Include prefix in filename so importing the same project with different + // prefixes creates separate credential files instead of overwriting. + baseName := sanitizeFilePart(projectID) + if prefix != "" { + baseName = sanitizeFilePart(prefix) + "-" + baseName + } + fileName := fmt.Sprintf("vertex-%s.json", baseName) // Build auth record storage := &vertex.VertexCredentialStorage{ ServiceAccount: sa, ProjectID: projectID, Email: email, Location: location, - Prefix: strings.TrimSpace(prefix), + Prefix: prefix, } metadata := map[string]any{ "service_account": sa, @@ -77,6 +91,7 @@ func DoVertexImport(cfg *config.Config, keyPath string, prefix string) { "email": email, "location": location, "type": "vertex", + "prefix": prefix, "label": labelForVertex(projectID, email), } record := &coreauth.Auth{