Skip to content

Commit d3e7048

Browse files
Update Go SDK to v0.141.0 and CLI coverage
1 parent 480a5e3 commit d3e7048

16 files changed

Lines changed: 548 additions & 91 deletions

‎cmd/browsers.go‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,14 @@ func parseMemoryFlag(memory string) (kernel.BrowserMemoryRequest, error) {
203203
}
204204

205205
// availableVideoMemorySizes returns the video memory (VRAM) sizes the API
206-
// accepts for a GPU browser session.
206+
// accepts for a GPU browser session. 2GiB and 4GiB are deprecated create-time
207+
// aliases for 3GiB and 6GiB.
207208
func availableVideoMemorySizes() []string {
208-
return []string{"2GiB", "4GiB"}
209+
return []string{"3GiB", "6GiB", "2GiB", "4GiB"}
209210
}
210211

211212
// parseVideoMemoryFlag validates a --video-memory value. An empty value means the
212-
// flag was not set, which lets the API apply its default (2GiB).
213+
// flag was not set, which lets the API apply its default (3GiB).
213214
func parseVideoMemoryFlag(videoMemory string) (kernel.BrowserVideoMemory, error) {
214215
if videoMemory == "" {
215216
return "", nil
@@ -3560,7 +3561,7 @@ unrestricted code execution inside the browser VM and is not sandboxed.`,
35603561
browsersCreateCmd.Flags().BoolP("headless", "H", false, "Launch browser without GUI access")
35613562
browsersCreateCmd.Flags().Bool("gpu", false, "Launch browser with hardware-accelerated GPU rendering")
35623563
browsersCreateCmd.Flags().String("memory", "", "Memory for a non-GPU browser session. Headless: '1GiB' (default), '2GiB' or '4GiB'. Headful: '8GiB' (default) or '16GiB'")
3563-
browsersCreateCmd.Flags().String("video-memory", "", "Video memory (VRAM) for a GPU browser session (requires --gpu): '2GiB' (default, 4 vCPU/6GiB memory) or '4GiB' (8 vCPU/12GiB memory)")
3564+
browsersCreateCmd.Flags().String("video-memory", "", "Video memory (VRAM) for a GPU browser session (requires --gpu): '3GiB' (default, 4 vCPU/6GiB memory) or '6GiB' (8 vCPU/12GiB memory). Deprecated create-only aliases '2GiB' and '4GiB' are accepted, but responses use 3GiB or 6GiB")
35643565
browsersCreateCmd.Flags().String("fingerprint-os", "", "Closed beta browser fingerprint OS override: macos. Contact Kernel to enable; requires --stealth=true, --headless=false, --gpu=false, and default memory")
35653566
browsersCreateCmd.Flags().String("invocation-id", "", "Associate the browser session with an invocation")
35663567
browsersCreateCmd.Flags().Bool("kiosk", false, "Launch browser in kiosk mode")

‎cmd/browsers_test.go‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,15 @@ func TestBrowsersCreate_WithMemory(t *testing.T) {
10361036
assert.Error(t, b.Create(context.Background(), BrowsersCreateInput{Memory: "3GiB"}))
10371037
}
10381038

1039+
func TestBrowsersVideoMemoryHelpMatchesCurrentSpec(t *testing.T) {
1040+
usage := browsersCreateCmd.Flags().Lookup("video-memory").Usage
1041+
for _, value := range []string{"3GiB", "6GiB", "2GiB", "4GiB"} {
1042+
assert.Contains(t, usage, value)
1043+
}
1044+
assert.Contains(t, usage, "Deprecated create-only aliases")
1045+
assert.Contains(t, usage, "responses use 3GiB or 6GiB")
1046+
}
1047+
10391048
func TestBrowsersCreate_WithVideoMemory(t *testing.T) {
10401049
setupStdoutCapture(t)
10411050

@@ -1048,15 +1057,25 @@ func TestBrowsersCreate_WithVideoMemory(t *testing.T) {
10481057
}
10491058
b := BrowsersCmd{browsers: fake}
10501059

1051-
err := b.Create(context.Background(), BrowsersCreateInput{GPU: BoolFlag{Set: true, Value: true}, VideoMemory: "4gib"})
1060+
err := b.Create(context.Background(), BrowsersCreateInput{GPU: BoolFlag{Set: true, Value: true}, VideoMemory: "6gib"})
10521061
require.NoError(t, err)
1053-
assert.Equal(t, kernel.BrowserVideoMemory4GiB, captured.VideoMemory)
1062+
assert.Equal(t, kernel.BrowserVideoMemory6GiB, captured.VideoMemory)
10541063

10551064
raw, err := captured.MarshalJSON()
10561065
require.NoError(t, err)
1057-
assert.Contains(t, string(raw), `"video_memory":"4GiB"`)
1066+
assert.Contains(t, string(raw), `"video_memory":"6GiB"`)
1067+
1068+
// The lower canonical size is accepted too.
1069+
err = b.Create(context.Background(), BrowsersCreateInput{GPU: BoolFlag{Set: true, Value: true}, VideoMemory: "3GiB"})
1070+
require.NoError(t, err)
1071+
assert.Equal(t, kernel.BrowserVideoMemory3GiB, captured.VideoMemory)
1072+
1073+
// Deprecated aliases remain accepted on create; the API canonicalizes responses.
1074+
err = b.Create(context.Background(), BrowsersCreateInput{GPU: BoolFlag{Set: true, Value: true}, VideoMemory: "4gib"})
1075+
require.NoError(t, err)
1076+
assert.Equal(t, kernel.BrowserVideoMemory4GiB, captured.VideoMemory)
10581077

1059-
// Omitting the flag sends nothing; the server defaults to 2GiB.
1078+
// Omitting the flag sends nothing; the server defaults to 3GiB.
10601079
err = b.Create(context.Background(), BrowsersCreateInput{GPU: BoolFlag{Set: true, Value: true}})
10611080
require.NoError(t, err)
10621081
assert.Empty(t, captured.VideoMemory)

‎cmd/search.go‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/spf13/pflag"
1818
)
1919

20+
var searchProviderSlugs = []string{"brave", "exa", "perplexity", "context", "parallel", "octen", "you", "tavily"}
21+
2022
func newSearchCommand() *cobra.Command {
2123
cmd := &cobra.Command{
2224
Use: "search [query]",
@@ -29,7 +31,7 @@ func newSearchCommand() *cobra.Command {
2931
RunE: runSearch,
3032
}
3133
cmd.PersistentFlags().StringP("output", "o", "", util.JSONOutputFlagDescription)
32-
cmd.Flags().String("provider", "", "Pin a provider slug (default: automatic routing)")
34+
cmd.Flags().String("provider", "", "Pin a provider slug: brave, exa, perplexity, context, parallel, octen, you, or tavily (default: automatic routing)")
3335
cmd.Flags().Int("max-results", 10, "Requested result count (1–100; subject to provider cap)")
3436
cmd.Flags().String("request", "", "Complete Search API request as a JSON object; cannot be combined with query flags")
3537
cmd.MarkFlagsMutuallyExclusive("request", "provider")
@@ -48,7 +50,7 @@ func newSearchCommand() *cobra.Command {
4850
}
4951
return executeSearchRequest(cmd, http.MethodGet, path, nil)
5052
}}
51-
providers.Flags().String("slug", "", "Filter by provider slug")
53+
providers.Flags().String("slug", "", "Filter by provider slug: brave, exa, perplexity, context, parallel, octen, you, or tavily")
5254
contents := &cobra.Command{
5355
Use: "contents <id>",
5456
Short: "Fetch content for selected results of a retained search as JSON",
@@ -213,8 +215,9 @@ func runSearch(cmd *cobra.Command, args []string) error {
213215
}
214216
if cmd.Flags().Changed("provider") {
215217
provider, _ := cmd.Flags().GetString("provider")
216-
if strings.TrimSpace(provider) == "" {
217-
return fmt.Errorf("--provider must not be empty")
218+
provider = strings.ToLower(strings.TrimSpace(provider))
219+
if !slices.Contains(searchProviderSlugs, provider) {
220+
return fmt.Errorf("--provider must be one of: %s", strings.Join(searchProviderSlugs, ", "))
218221
}
219222
request["strategy"] = map[string]any{"type": "pinned", "provider": map[string]string{"provider": provider}}
220223
}

‎cmd/search_test.go‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func TestSearchCreate(t *testing.T) {
4040
stdin, want string
4141
}{
4242
{"auto", []string{"test"}, "", `{"query":"test"}`},
43-
{"pinned", []string{"test", "--provider", "exa", "--max-results", "5"}, "", `{"query":"test","max_results":5,"strategy":{"type":"pinned","provider":{"provider":"exa"}}}`},
43+
{"pinned", []string{"test", "--provider", "EXA", "--max-results", "5"}, "", `{"query":"test","max_results":5,"strategy":{"type":"pinned","provider":{"provider":"exa"}}}`},
4444
{"advanced request", []string{"--request", advanced}, "", advanced},
4545
} {
4646
t.Run(tc.name, func(t *testing.T) {
@@ -132,6 +132,7 @@ func TestSearchContents(t *testing.T) {
132132
func TestSearchInvalidInput(t *testing.T) {
133133
for _, args := range [][]string{
134134
{}, {" "}, {strings.Repeat("x", 2049)}, {"a", "b"}, {"test", "--provider", ""},
135+
{"test", "--provider", "valyu"}, {"test", "--provider", "serpapi"}, {"test", "--provider", "unknown"},
135136
{"test", "--max-results", "0"}, {"test", "--max-results", "101"},
136137
{"test", "-o", "yaml"}, {"get", "srch_test", "-o", "yaml"}, {"contents", "srch_test", "--limit", "1", "-o", "yaml"},
137138
{"--request", "null"}, {"--request", "[]"}, {"--request", "{"}, {"--request", `{}`}, {"--request", `{"query":1}`},
@@ -176,6 +177,16 @@ func TestSearchErrorsDoNotRetryCreate(t *testing.T) {
176177
}
177178
}
178179

180+
func TestSearchProviderHelpMatchesCurrentSpec(t *testing.T) {
181+
cmd := newSearchCommand()
182+
usage := cmd.Flags().Lookup("provider").Usage
183+
for _, provider := range searchProviderSlugs {
184+
assert.Contains(t, usage, provider)
185+
}
186+
assert.NotContains(t, usage, "valyu")
187+
assert.NotContains(t, usage, "serpapi")
188+
}
189+
179190
func TestSearchWiring(t *testing.T) {
180191
for _, path := range [][]string{{"search"}, {"search", "get"}, {"search", "providers"}, {"search", "contents"}} {
181192
cmd, remaining, err := rootCmd.Find(path)

‎cmd/vault_provider_configs.go‎

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/spf13/cobra"
1515
)
1616

17-
var vaultProviderConfigFields = vaultFieldsOf("id name provider client_id publishable_key test_mode created_at updated_at")
17+
var vaultProviderConfigFields = vaultFieldsOf("id name provider client_id publishable_key test_mode vault_id environment created_at updated_at")
1818

1919
type VaultProviderConfigsCmd struct {
2020
configs *kernel.VaultProviderConfigService
@@ -33,11 +33,12 @@ func getVaultProviderConfigsHandler(cmd *cobra.Command) VaultProviderConfigsCmd
3333
func newVaultProviderConfigsCommand() *cobra.Command {
3434
cmd := &cobra.Command{
3535
Use: "vault-provider-configs", Short: "Manage organization-owned vault provider configurations",
36-
Long: `Manage Link OAuth clients and AgentCard application credentials, shared across projects.
36+
Long: `Manage Link OAuth clients, AgentCard application credentials, and VGS service accounts shared across projects.
3737
Config credentials are not wallet grants. Link grants are imported separately when creating a wallet.
38+
VGS configurations identify one customer-managed vault and environment for alias reveal.
3839
Writes require organization-scoped authentication; --project does not elevate a project API key.
39-
Provider and client ID are immutable. Rename or rotate a secret without changing wallet bindings.
40-
Rotation affects all bound wallets and must preserve client identity and AgentCard mode.
40+
Provider and client ID are immutable. VGS vault ID and environment are immutable too.
41+
Rename or rotate a secret without changing wallet bindings; rotation revalidates the same provider identity and mode.
4142
Secrets are accepted only from a file or stdin and are never displayed. Protect credential files.`,
4243
}
4344
preRun := func(cmd *cobra.Command, args []string) error {
@@ -49,34 +50,44 @@ Secrets are accepted only from a file or stdin and are never displayed. Protect
4950
}
5051
return nil
5152
}
52-
create := &cobra.Command{Use: "create --name <name> --provider <link|agentcard> --credentials-file <path|->", Short: "Register a provider configuration", Args: cobra.NoArgs, PreRunE: preRun,
53-
Long: "Register a configuration; duplicate names return a conflict without replacing credentials.\n--credentials-file must contain a JSON object with client_id and client_secret strings.\nUse a protected file or pipe from a secret manager; never put credentials in shell arguments.\nFor Link, pass --publishable-key so imported wallet grants keep working after their access token expires.",
53+
create := &cobra.Command{Use: "create --name <name> --provider <link|agentcard|vgs> --credentials-file <path|->", Short: "Register a provider configuration", Args: cobra.NoArgs, PreRunE: preRun,
54+
Long: "Register a configuration; duplicate names return a conflict without replacing credentials.\n--credentials-file must contain client_id and client_secret strings. For VGS it must also contain vault_id and environment (sandbox or live); the service account needs aliases:read access to that vault. Kernel validates the VGS scope and vault access before storing anything.\nUse a protected file or pipe from a secret manager; never put credentials in shell arguments.\nFor Link, pass --publishable-key so imported wallet grants keep working after their access token expires.",
5455
RunE: func(cmd *cobra.Command, args []string) error {
5556
name, _ := cmd.Flags().GetString("name")
5657
if err := validateVaultName(name, "--name"); err != nil {
5758
return err
5859
}
5960
provider, _ := cmd.Flags().GetString("provider")
60-
if provider != "link" && provider != "agentcard" {
61-
return fmt.Errorf("--provider must be link or agentcard")
61+
if provider != "link" && provider != "agentcard" && provider != "vgs" {
62+
return fmt.Errorf("--provider must be link, agentcard, or vgs")
6263
}
6364
publishableKey, _ := cmd.Flags().GetString("publishable-key")
6465
if cmd.Flags().Changed("publishable-key") && (provider != "link" || publishableKey == "") {
6566
return fmt.Errorf("--publishable-key requires --provider link and a non-empty value")
6667
}
67-
credentials, err := readVaultSecrets(cmd, "credentials-file", "client_id", "client_secret")
68+
credentialFields := []string{"client_id", "client_secret"}
69+
if provider == "vgs" {
70+
credentialFields = append(credentialFields, "vault_id", "environment")
71+
}
72+
credentials, err := readVaultSecrets(cmd, "credentials-file", credentialFields...)
6873
if err != nil {
6974
return err
7075
}
7176
params := kernel.VaultProviderConfigNewParams{}
72-
if provider == "link" {
77+
switch provider {
78+
case "link":
7379
linkCredentials := kernel.VaultProviderConfigNewParamsBodyLinkCredentials{ClientID: credentials["client_id"], ClientSecret: credentials["client_secret"]}
7480
if publishableKey != "" {
7581
linkCredentials.PublishableKey = kernel.Opt(publishableKey)
7682
}
7783
params.OfLink = &kernel.VaultProviderConfigNewParamsBodyLink{Name: name, Credentials: linkCredentials}
78-
} else {
84+
case "agentcard":
7985
params.OfAgentcard = &kernel.VaultProviderConfigNewParamsBodyAgentcard{Name: name, Credentials: kernel.VaultProviderConfigNewParamsBodyAgentcardCredentials{ClientID: credentials["client_id"], ClientSecret: credentials["client_secret"]}}
86+
case "vgs":
87+
params.OfVgs = &kernel.VaultProviderConfigNewParamsBodyVgs{Name: name, Credentials: kernel.VaultProviderConfigNewParamsBodyVgsCredentials{
88+
ClientID: credentials["client_id"], ClientSecret: credentials["client_secret"],
89+
VaultID: credentials["vault_id"], Environment: credentials["environment"],
90+
}}
8091
}
8192
c := getVaultProviderConfigsHandler(cmd)
8293
config, err := c.configs.New(cmd.Context(), params, vaultWriteRequestOptions()...)
@@ -86,8 +97,8 @@ Secrets are accepted only from a file or stdin and are never displayed. Protect
8697
return printVaultProviderConfig(config, vaultOutput(cmd))
8798
}}
8899
create.Flags().String("name", "", "Organization-unique configuration name (required)")
89-
create.Flags().String("provider", "", "Provider: link or agentcard (required)")
90-
create.Flags().String("credentials-file", "", "Read client_id and client_secret JSON from a file (use '-' for stdin)")
100+
create.Flags().String("provider", "", "Provider: link, agentcard, or vgs (required)")
101+
create.Flags().String("credentials-file", "", "Read provider credential JSON from a file (use '-' for stdin); VGS also requires vault_id and environment")
91102
create.Flags().String("publishable-key", "", "Link only. Stripe publishable key for the account that owns the Link OAuth client; required for Kernel to refresh or revoke imported wallet grants")
92103
for _, flag := range []string{"name", "provider", "credentials-file"} {
93104
_ = create.MarkFlagRequired(flag)
@@ -116,7 +127,7 @@ Secrets are accepted only from a file or stdin and are never displayed. Protect
116127
addVaultJSONOutputFlag(list)
117128

118129
update := &cobra.Command{Use: "update <id-or-name>", Short: "Rename a configuration or rotate its secret", Args: cobra.ExactArgs(1), PreRunE: preRun,
119-
Long: "Omitted fields remain unchanged. --credentials-file accepts only a client_secret JSON string field.\n--publishable-key sets the Stripe publishable key on Link configurations.\nProvider, client ID, and mode cannot change. Rotation affects all wallets using this configuration.",
130+
Long: "Omitted fields remain unchanged. --credentials-file accepts only a client_secret JSON string field.\n--publishable-key sets the Stripe publishable key on Link configurations.\nProvider and client ID cannot change. AgentCard mode is preserved. VGS vault_id and environment are immutable; rotating its secret repeats the aliases:read and vault-access checks against the same vault and environment. Rotation affects all wallets using this configuration.",
120131
RunE: func(cmd *cobra.Command, args []string) error {
121132
if !cmd.Flags().Changed("name") && !cmd.Flags().Changed("credentials-file") && !cmd.Flags().Changed("publishable-key") {
122133
return fmt.Errorf("provide --name, --credentials-file, or --publishable-key")
@@ -208,13 +219,13 @@ func (c VaultProviderConfigsCmd) List(ctx context.Context, limit, offset int64,
208219
if len(page.Items) == 0 {
209220
pterm.Info.Println("No vault provider configurations found")
210221
} else {
211-
rows := pterm.TableData{{"ID", "Name", "Provider", "Client ID", "Test mode"}}
222+
rows := pterm.TableData{{"ID", "Name", "Provider", "Client ID", "Vault ID", "Environment", "Test mode"}}
212223
for _, config := range page.Items {
213224
mode := "—"
214225
if config.JSON.TestMode.Valid() {
215226
mode = fmt.Sprint(config.TestMode)
216227
}
217-
rows = append(rows, []string{config.ID, config.Name, config.Provider, config.ClientID, mode})
228+
rows = append(rows, []string{config.ID, config.Name, config.Provider, config.ClientID, util.OrDash(config.VaultID), util.OrDash(config.Environment), mode})
218229
}
219230
PrintTableNoPad(rows, true)
220231
}
@@ -239,6 +250,12 @@ func printVaultProviderConfig(config *kernel.VaultProviderConfigUnion, output st
239250
if config.JSON.TestMode.Valid() {
240251
rows = append(rows, []string{"Test mode (introspected)", fmt.Sprint(config.TestMode)})
241252
}
253+
if config.JSON.VaultID.Valid() {
254+
rows = append(rows, []string{"VGS vault ID (immutable)", config.VaultID})
255+
}
256+
if config.JSON.Environment.Valid() {
257+
rows = append(rows, []string{"VGS environment (immutable)", config.Environment})
258+
}
242259
rows = append(rows, []string{"Created At", util.FormatLocal(config.CreatedAt)}, []string{"Updated At", util.FormatLocal(config.UpdatedAt)})
243260
PrintTableNoPad(rows, true)
244261
return nil

0 commit comments

Comments
 (0)