diff --git a/README.md b/README.md index 3b2cef3..b2e64f2 100644 --- a/README.md +++ b/README.md @@ -210,14 +210,14 @@ Commands with JSON output support: - `kernel browsers list` - List running browsers - `--query ` - Search by name, session ID, profile ID, proxy ID, or pool name - - `--region us-east|eu-west` - Filter by geographic region; omit to list sessions in all regions + - `--region us-east|eu-west|ap-southeast` - Filter by geographic region; omit to list sessions in all regions - `--tag ` - Filter by tag, repeatable; a session must match every pair - `--output json`, `-o json` - Output raw JSON array - `kernel browsers create` - Create a new browser session - `-s, --stealth` - Launch browser in stealth mode to avoid detection - `-H, --headless` - Launch browser without GUI access - `--kiosk` - Launch browser in kiosk mode - - `--region us-east|eu-west` - Geographic region for the session. Fixed once the session is created; requires a Start-Up or Enterprise plan and defaults to `us-east`. + - `--region us-east|eu-west|ap-southeast` - Geographic region for the session. Fixed once the session is created; requires a Start-Up or Enterprise plan and defaults to `us-east`. - `--private-host ` - Destination the browser reaches directly through the session's own network instead of Kernel-managed egress, for private hosts on a VPN or tunnel the session joins (repeatable or comma-separated, max 32). Accepts hostname patterns (`*.example.ts.net`), IPs (`10.1.30.63`, `[fd00::1]`), and private CIDRs (`100.64.0.0/10`). Replaces the default private ranges (RFC1918, `100.64.0.0/10`, `fc00::/7`); omit to keep them. Fixed once the session is created. Unrelated to a proxy's `--bypass-host`, which only chooses between upstream proxy and Kernel-managed direct egress. - `--start-url ` - Initial page to open on launch - `--proxy-id ` / `--proxy-name ` - Use that proxy for the session regardless of stealth (mutually exclusive with each other and with `--proxy-mode`) @@ -270,7 +270,7 @@ Commands with JSON output support: ### Browser Pools - `kernel browser-pools list` - List browser pools - - `--region us-east|eu-west` - Filter by geographic region; omit to list pools in all regions + - `--region us-east|eu-west|ap-southeast` - Filter by geographic region; omit to list pools in all regions - `--output json`, `-o json` - Output raw JSON array - `kernel browser-pools create` - Create a browser pool - `--name ` - Optional unique name for the pool diff --git a/cmd/auth_connections.go b/cmd/auth_connections.go index 79a3456..dc2cb26 100644 --- a/cmd/auth_connections.go +++ b/cmd/auth_connections.go @@ -548,7 +548,7 @@ func (c AuthConnectionCmd) Get(ctx context.Context, in AuthConnectionGetInput) e Ref: f.Ref, Hint: f.Hint, Required: f.Required, - ReplaceExisting: f.ReplaceExisting, + ReplaceExisting: f.Reason == "rejected", })) } tableData = append(tableData, []string{"Fields", strings.Join(fields, "; ")}) @@ -1073,7 +1073,7 @@ func (c AuthConnectionCmd) Follow(ctx context.Context, in AuthConnectionFollowIn Ref: f.Ref, Hint: f.Hint, Required: f.Required, - ReplaceExisting: f.ReplaceExisting, + ReplaceExisting: f.Reason == "rejected", })) } pterm.Info.Printf(" Fields: %s\n", strings.Join(fields, ", ")) diff --git a/cmd/browser_pools.go b/cmd/browser_pools.go index c6f7051..d6d23f8 100644 --- a/cmd/browser_pools.go +++ b/cmd/browser_pools.go @@ -726,7 +726,7 @@ func init() { browserPoolsListCmd.Flags().String("query", "", "Search browser pools by name (IDs match by exact value)") browserPoolsListCmd.Flags().Int("limit", 0, "Maximum number of pools to return") browserPoolsListCmd.Flags().Int("offset", 0, "Number of pools to skip (for pagination)") - browserPoolsListCmd.Flags().String("region", "", "Filter by geographic region: 'us-east' or 'eu-west' (omit to list pools in all regions)") + browserPoolsListCmd.Flags().String("region", "", "Filter by geographic region: 'us-east', 'eu-west', or 'ap-southeast' (omit to list pools in all regions)") addJSONOutputFlag(browserPoolsCreateCmd) browserPoolsCreateCmd.Flags().String("name", "", "Optional unique name for the pool") @@ -741,7 +741,7 @@ func init() { browserPoolsCreateCmd.Flags().String("profile-id", "", "Profile ID") browserPoolsCreateCmd.Flags().String("profile-name", "", "Profile name") browserPoolsCreateCmd.Flags().String("proxy-id", "", "Proxy ID") - browserPoolsCreateCmd.Flags().String("region", "", "Geographic region for the pool: 'us-east' or 'eu-west'. Fixed once the pool is created; requires a Start-Up or Enterprise plan and defaults to us-east") + browserPoolsCreateCmd.Flags().String("region", "", "Geographic region for the pool: 'us-east', 'eu-west', or 'ap-southeast'. Fixed once the pool is created; requires a Start-Up or Enterprise plan and defaults to us-east") browserPoolsCreateCmd.Flags().StringSlice("private-host", nil, "Destinations browsers in the pool reach directly through their own network instead of Kernel-managed egress, for private hosts on a VPN or tunnel they join (repeat or comma-separated, max 32). Accepts hostname patterns ('*.example.ts.net'), IPs ('10.1.30.63', '[fd00::1]'), and private CIDRs ('100.64.0.0/10'). Replaces the default private ranges (RFC1918, 100.64.0.0/10, fc00::/7); omit to keep them") browserPoolsCreateCmd.Flags().String("start-url", "", "Initial page to open for new browsers") browserPoolsCreateCmd.Flags().StringSlice("extension", []string{}, "Extension IDs or names") diff --git a/cmd/browser_pools_test.go b/cmd/browser_pools_test.go index e0a143f..1df6e6e 100644 --- a/cmd/browser_pools_test.go +++ b/cmd/browser_pools_test.go @@ -137,17 +137,17 @@ func TestBrowserPoolsList_ForwardsRegion(t *testing.T) { ListFunc: func(ctx context.Context, query kernel.BrowserPoolListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserPool], error) { captured = query return &pagination.OffsetPagination[kernel.BrowserPool]{Items: []kernel.BrowserPool{ - {ID: "pool-1", Region: kernel.BrowserPoolRegionEuWest}, + {ID: "pool-1", Region: kernel.BrowserPoolRegionApSoutheast}, }}, nil }, } c := BrowserPoolsCmd{client: fake} - err := c.List(context.Background(), BrowserPoolsListInput{Region: "eu-west"}) + err := c.List(context.Background(), BrowserPoolsListInput{Region: "ap-southeast"}) assert.NoError(t, err) - assert.Equal(t, kernel.BrowserPoolListParamsRegionEuWest, captured.Region) - assert.Contains(t, outBuf.String(), "eu-west") + assert.Equal(t, kernel.BrowserPoolListParamsRegionApSoutheast, captured.Region) + assert.Contains(t, outBuf.String(), "ap-southeast") // Omitting the flag leaves the param unset, so all regions are listed. captured = kernel.BrowserPoolListParams{} @@ -167,13 +167,13 @@ func TestBrowserPoolsCreate_WithRegion(t *testing.T) { fake := &FakeBrowserPoolsService{ NewFunc: func(ctx context.Context, body kernel.BrowserPoolNewParams, opts ...option.RequestOption) (*kernel.BrowserPool, error) { captured = body - return &kernel.BrowserPool{ID: "pool-1", Region: kernel.BrowserPoolRegionEuWest}, nil + return &kernel.BrowserPool{ID: "pool-1", Region: kernel.BrowserPoolRegionApSoutheast}, nil }, } c := BrowserPoolsCmd{client: fake} - require.NoError(t, c.Create(context.Background(), BrowserPoolsCreateInput{Size: 1, Region: "eu-west"})) - assert.Equal(t, kernel.BrowserPoolNewParamsRegionEuWest, captured.Region) + require.NoError(t, c.Create(context.Background(), BrowserPoolsCreateInput{Size: 1, Region: "ap-southeast"})) + assert.Equal(t, kernel.BrowserPoolNewParamsRegionApSoutheast, captured.Region) // Omitting the flag leaves the region unset so the API default applies. require.NoError(t, c.Create(context.Background(), BrowserPoolsCreateInput{Size: 1})) diff --git a/cmd/browsers.go b/cmd/browsers.go index 326f88d..caf2cfe 100644 --- a/cmd/browsers.go +++ b/cmd/browsers.go @@ -165,7 +165,7 @@ func parseViewport(viewport string) (width, height, refreshRate int64, err error // availableRegions returns the geographic regions the API accepts for browser // sessions and pools. func availableRegions() []string { - return []string{"us-east", "eu-west"} + return []string{"us-east", "eu-west", "ap-southeast"} } // parseRegionFlag validates a --region value. An empty value means the flag was @@ -2659,7 +2659,7 @@ func init() { browsersListCmd.Flags().Int("limit", 0, "Maximum number of results to return (default 20, max 100)") browsersListCmd.Flags().Int("offset", 0, "Number of results to skip (for pagination)") browsersListCmd.Flags().String("query", "", "Search browsers by name, session ID, profile ID, proxy ID, or pool name") - browsersListCmd.Flags().String("region", "", "Filter by geographic region: 'us-east' or 'eu-west' (omit to list sessions in all regions)") + browsersListCmd.Flags().String("region", "", "Filter by geographic region: 'us-east', 'eu-west', or 'ap-southeast' (omit to list sessions in all regions)") browsersListCmd.Flags().StringArray("tag", nil, "Filter by tag KEY=VALUE (repeatable; a session must match every pair)") // get flags @@ -2954,7 +2954,7 @@ func init() { browsersCreateCmd.Flags().String("proxy-id", "", "Proxy ID to use for the browser session (mutually exclusive with --proxy-name and --proxy-mode)") browsersCreateCmd.Flags().String("proxy-name", "", "Proxy name to use for the browser session; must match exactly one active proxy in the project (mutually exclusive with --proxy-id and --proxy-mode)") browsersCreateCmd.Flags().String("proxy-mode", "", "Proxy egress mode instead of a selected proxy: 'direct' for no proxy regardless of stealth, or 'default' for the browser default (Kernel's stealth proxy when --stealth is set, direct egress otherwise)") - browsersCreateCmd.Flags().String("region", "", "Geographic region for the session: 'us-east' or 'eu-west'. Fixed once the session is created; requires a Start-Up or Enterprise plan and defaults to us-east") + browsersCreateCmd.Flags().String("region", "", "Geographic region for the session: 'us-east', 'eu-west', or 'ap-southeast'. Fixed once the session is created; requires a Start-Up or Enterprise plan and defaults to us-east") browsersCreateCmd.Flags().StringSlice("private-host", nil, "Destinations the browser reaches directly through its own network instead of Kernel-managed egress, for private hosts on a VPN or tunnel the session joins (repeat or comma-separated, max 32). Accepts hostname patterns ('*.example.ts.net'), IPs ('10.1.30.63', '[fd00::1]'), and private CIDRs ('100.64.0.0/10'). Replaces the default private ranges (RFC1918, 100.64.0.0/10, fc00::/7); omit to keep them. Fixed once the session is created") browsersCreateCmd.Flags().String("start-url", "", "Initial page to open on launch") browsersCreateCmd.Flags().StringSlice("extension", []string{}, "Extension IDs or names to load (repeatable; may be passed multiple times or comma-separated)") diff --git a/cmd/browsers_telemetry.go b/cmd/browsers_telemetry.go index 9a37ef3..4a51bcc 100644 --- a/cmd/browsers_telemetry.go +++ b/cmd/browsers_telemetry.go @@ -76,7 +76,7 @@ func parseTelemetryCategories(s string) (kernel.BrowserTelemetryCategoriesConfig case "interaction": p.Interaction = on() case "control": - p.Control = on() + p.Control = kernel.BrowserTelemetryControlConfigParam{Enabled: kernel.Opt(true)} case "connection": p.Connection = on() case "system": diff --git a/cmd/browsers_telemetry_test.go b/cmd/browsers_telemetry_test.go index fe3b88e..d052a2b 100644 --- a/cmd/browsers_telemetry_test.go +++ b/cmd/browsers_telemetry_test.go @@ -303,10 +303,12 @@ func TestParseTelemetryCategories_OptInList(t *testing.T) { assert.NoError(t, err) // Listed categories are enabled. - for _, c := range []kernel.BrowserTelemetryCategoryConfigParam{p.Network, p.Control, p.Captcha} { + for _, c := range []kernel.BrowserTelemetryCategoryConfigParam{p.Network, p.Captcha} { assert.True(t, c.Enabled.Valid()) assert.True(t, c.Enabled.Value) } + assert.True(t, p.Control.Enabled.Valid()) + assert.True(t, p.Control.Enabled.Value) // Unlisted categories are omitted (opt-in: the instance treats them as off). assert.False(t, p.Console.Enabled.Valid()) assert.False(t, p.Page.Enabled.Valid()) diff --git a/cmd/browsers_test.go b/cmd/browsers_test.go index b2b7599..a039f2f 100644 --- a/cmd/browsers_test.go +++ b/cmd/browsers_test.go @@ -467,9 +467,9 @@ func TestBrowsersList_WithRegion_PassesParam(t *testing.T) { } b := BrowsersCmd{browsers: fake} - err := b.List(context.Background(), BrowsersListInput{Region: "eu-west"}) + err := b.List(context.Background(), BrowsersListInput{Region: "ap-southeast"}) assert.NoError(t, err) - assert.Equal(t, kernel.BrowserListParamsRegionEuWest, captured.Region) + assert.Equal(t, kernel.BrowserListParamsRegionApSoutheast, captured.Region) // Omitting the flag leaves the param unset, so all regions are listed. captured = kernel.BrowserListParams{} @@ -573,13 +573,13 @@ func TestBrowsersCreate_WithRegion(t *testing.T) { } b := BrowsersCmd{browsers: fake} - err := b.Create(context.Background(), BrowsersCreateInput{Region: "eu-west"}) + err := b.Create(context.Background(), BrowsersCreateInput{Region: "ap-southeast"}) require.NoError(t, err) - assert.Equal(t, kernel.BrowserNewParamsRegionEuWest, captured.Region) + assert.Equal(t, kernel.BrowserNewParamsRegionApSoutheast, captured.Region) raw, err := captured.MarshalJSON() require.NoError(t, err) - assert.Contains(t, string(raw), `"region":"eu-west"`) + assert.Contains(t, string(raw), `"region":"ap-southeast"`) // Omitting the flag sends nothing; the server defaults to us-east. err = b.Create(context.Background(), BrowsersCreateInput{}) diff --git a/go.mod b/go.mod index 502421b..45ca6fa 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/joho/godotenv v1.5.1 - github.com/kernel/kernel-go-sdk v0.92.0 + github.com/kernel/kernel-go-sdk v0.95.0 github.com/klauspost/compress v1.18.5 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pterm/pterm v0.12.80 diff --git a/go.sum b/go.sum index 04679b8..8c92c4e 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kernel/kernel-go-sdk v0.92.0 h1:3EeoPahTcGEo97BCbwT50gu8QJnawfL166z12hc8Ucg= -github.com/kernel/kernel-go-sdk v0.92.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= +github.com/kernel/kernel-go-sdk v0.95.0 h1:VoEneqrqqT5i3cO1L6faoHo4PqrndG0pAEs6Abivd5A= +github.com/kernel/kernel-go-sdk v0.95.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=