diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5eb5472..ee48f67 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/kernel-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: |-
github.repository == 'stainless-sdks/kernel-go' &&
- (github.event_name == 'push' || github.event.pull_request.head.repo.fork)
+ (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
steps:
- uses: actions/checkout@v6
diff --git a/.gitignore b/.gitignore
index c6d0501..8554aff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.prism.log
+.stdy.log
codegen.log
Brewfile.lock.json
.idea/
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index cc51f6f..fc0d7ff 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.44.0"
+ ".": "0.45.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index be60802..8ed1b33 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 104
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-bb2ac8e0d3a1c08e8afcbcbad7cb733d0f84bd22a8d233c1ec3100a01ee078ae.yml
-openapi_spec_hash: a83f7d1c422c85d6dc6158af7afe1d09
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-20310988401243aa5c4a2e2ac6cba5dd90873fb7b83497a2d50c691352c0dd7b.yml
+openapi_spec_hash: e19e650b4b2c8c8fde1f739c4aab6b33
config_hash: 16e4457a0bb26e98a335a1c2a572290a
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7785f78..36ae3e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,31 @@
# Changelog
+## 0.45.0 (2026-03-30)
+
+Full Changelog: [v0.44.0...v0.45.0](https://github.com/kernel/kernel-go-sdk/compare/v0.44.0...v0.45.0)
+
+### Features
+
+* [kernel-1008] browser pools add custom policy ([e740db7](https://github.com/kernel/kernel-go-sdk/commit/e740db79ec07414b5b0b5ff3be98b9e089a9bb45))
+* Add disable_default_proxy for stealth browsers ([f584af5](https://github.com/kernel/kernel-go-sdk/commit/f584af5155e3fe8bb6dd87f48e1c5ee6cfe47111))
+* **internal:** support comma format in multipart form encoding ([74f5c6a](https://github.com/kernel/kernel-go-sdk/commit/74f5c6a22be0f953416968dfc92b0354f66d5cd9))
+
+
+### Bug Fixes
+
+* prevent duplicate ? in query params ([66d97d3](https://github.com/kernel/kernel-go-sdk/commit/66d97d350f30d933b1cd4596da6e3fb4cac8c4a1))
+
+
+### Chores
+
+* **ci:** skip lint on metadata-only changes ([8296238](https://github.com/kernel/kernel-go-sdk/commit/8296238ce0b45903e3d40420100aa29a3ab105fd))
+* **ci:** support opting out of skipping builds on metadata-only commits ([708da0f](https://github.com/kernel/kernel-go-sdk/commit/708da0fffff51a8f20905f9983e5beb1181a6a48))
+* **client:** fix multipart serialisation of Default() fields ([cabda49](https://github.com/kernel/kernel-go-sdk/commit/cabda49a25334cd3fa3fc747f69b8a515e2b77d9))
+* **internal:** support default value struct tag ([dd77af4](https://github.com/kernel/kernel-go-sdk/commit/dd77af45f77a98e96f5d140bb737377f1d72456a))
+* **internal:** update gitignore ([48baab7](https://github.com/kernel/kernel-go-sdk/commit/48baab7aa0e23ed519a08b52142927340a8d451b))
+* remove unnecessary error check for url parsing ([05d2048](https://github.com/kernel/kernel-go-sdk/commit/05d2048b0cc9027c63a4036b9f722044423f4e25))
+* update docs for api:"required" ([abfd988](https://github.com/kernel/kernel-go-sdk/commit/abfd9883774e74c2d4c2cc482377364432318e27))
+
## 0.44.0 (2026-03-20)
Full Changelog: [v0.43.0...v0.44.0](https://github.com/kernel/kernel-go-sdk/compare/v0.43.0...v0.44.0)
diff --git a/README.md b/README.md
index 9594193..c114a13 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/kernel/kernel-go-sdk@v0.44.0'
+go get -u 'github.com/kernel/kernel-go-sdk@v0.45.0'
```
@@ -73,7 +73,7 @@ func main() {
The kernel library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson)
semantics from the Go 1.24+ `encoding/json` release for request fields.
-Required primitive fields (`int64`, `string`, etc.) feature the tag \`json:"...,required"\`. These
+Required primitive fields (`int64`, `string`, etc.) feature the tag \`api:"required"\`. These
fields are always serialized, even their zero values.
Optional primitive types are wrapped in a `param.Opt[T]`. These fields can be set with the provided constructors, `kernel.String(string)`, `kernel.Int(int64)`, etc.
diff --git a/app.go b/app.go
index d3f4230..bac9291 100644
--- a/app.go
+++ b/app.go
@@ -76,7 +76,7 @@ type AppListResponse struct {
// Environment variables configured for this app version
EnvVars map[string]string `json:"env_vars" api:"required"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Version label for the application
Version string `json:"version" api:"required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
diff --git a/authconnection.go b/authconnection.go
index a9df222..ed76924 100644
--- a/authconnection.go
+++ b/authconnection.go
@@ -875,7 +875,7 @@ func (r *AuthConnectionFollowResponseUnion) UnmarshalJSON(data []byte) error {
// An event representing the current state of a managed auth flow.
type AuthConnectionFollowResponseManagedAuthState struct {
// Event type identifier (always "managed_auth_state").
- Event constant.ManagedAuthState `json:"event" api:"required"`
+ Event constant.ManagedAuthState `json:"event" default:"managed_auth_state"`
// Current flow status.
//
// Any of "IN_PROGRESS", "SUCCESS", "FAILED", "EXPIRED", "CANCELED".
diff --git a/browser.go b/browser.go
index 4aef02f..87daf2e 100644
--- a/browser.go
+++ b/browser.go
@@ -671,6 +671,9 @@ type BrowserUpdateParams struct {
// ID of the proxy to use. Omit to leave unchanged, set to empty string to remove
// proxy.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
+ // If true, stealth browsers connect directly instead of using the default stealth
+ // proxy.
+ DisableDefaultProxy param.Opt[bool] `json:"disable_default_proxy,omitzero"`
// Profile to load into the browser session. Only allowed if the session does not
// already have a profile loaded.
Profile shared.BrowserProfileParam `json:"profile,omitzero"`
diff --git a/browser_test.go b/browser_test.go
index a649334..40b7829 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -110,6 +110,7 @@ func TestBrowserUpdateWithOptionalParams(t *testing.T) {
context.TODO(),
"htzv5orfit78e1m2biiifpbv",
kernel.BrowserUpdateParams{
+ DisableDefaultProxy: kernel.Bool(true),
Profile: shared.BrowserProfileParam{
ID: kernel.String("id"),
Name: kernel.String("name"),
diff --git a/browserpool.go b/browserpool.go
index 303f117..54ac2aa 100644
--- a/browserpool.go
+++ b/browserpool.go
@@ -173,6 +173,11 @@ type BrowserPoolBrowserPoolConfig struct {
// your organization's pooled sessions limit (the sum of all pool sizes cannot
// exceed your limit).
Size int64 `json:"size" api:"required"`
+ // Custom Chrome enterprise policy overrides applied to all browsers in this pool.
+ // Keys are Chrome enterprise policy names; values must match their expected types.
+ // Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See
+ // https://chromeenterprise.google/policies/
+ ChromePolicy map[string]any `json:"chrome_policy"`
// List of browser extensions to load into the session. Provide each by id or name.
Extensions []shared.BrowserExtension `json:"extensions"`
// Percentage of the pool to fill per minute. Defaults to 10%.
@@ -213,6 +218,7 @@ type BrowserPoolBrowserPoolConfig struct {
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Size respjson.Field
+ ChromePolicy respjson.Field
Extensions respjson.Field
FillRatePerMinute respjson.Field
Headless respjson.Field
@@ -337,6 +343,11 @@ type BrowserPoolNewParams struct {
// Default idle timeout in seconds for browsers acquired from this pool before they
// are destroyed. Defaults to 600 seconds if not specified
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,omitzero"`
+ // Custom Chrome enterprise policy overrides applied to all browsers in this pool.
+ // Keys are Chrome enterprise policy names; values must match their expected types.
+ // Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See
+ // https://chromeenterprise.google/policies/
+ ChromePolicy map[string]any `json:"chrome_policy,omitzero"`
// List of browser extensions to load into the session. Provide each by id or name.
Extensions []shared.BrowserExtensionParam `json:"extensions,omitzero"`
// Profile selection for the browser session. Provide either id or name. If
@@ -393,6 +404,11 @@ type BrowserPoolUpdateParams struct {
// Default idle timeout in seconds for browsers acquired from this pool before they
// are destroyed. Defaults to 600 seconds if not specified
TimeoutSeconds param.Opt[int64] `json:"timeout_seconds,omitzero"`
+ // Custom Chrome enterprise policy overrides applied to all browsers in this pool.
+ // Keys are Chrome enterprise policy names; values must match their expected types.
+ // Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See
+ // https://chromeenterprise.google/policies/
+ ChromePolicy map[string]any `json:"chrome_policy,omitzero"`
// List of browser extensions to load into the session. Provide each by id or name.
Extensions []shared.BrowserExtensionParam `json:"extensions,omitzero"`
// Profile selection for the browser session. Provide either id or name. If
diff --git a/browserpool_test.go b/browserpool_test.go
index 0bed0f3..fd59d64 100644
--- a/browserpool_test.go
+++ b/browserpool_test.go
@@ -29,6 +29,9 @@ func TestBrowserPoolNewWithOptionalParams(t *testing.T) {
)
_, err := client.BrowserPools.New(context.TODO(), kernel.BrowserPoolNewParams{
Size: 10,
+ ChromePolicy: map[string]any{
+ "foo": "bar",
+ },
Extensions: []shared.BrowserExtensionParam{{
ID: kernel.String("id"),
Name: kernel.String("name"),
@@ -100,7 +103,10 @@ func TestBrowserPoolUpdateWithOptionalParams(t *testing.T) {
context.TODO(),
"id_or_name",
kernel.BrowserPoolUpdateParams{
- Size: 10,
+ Size: 10,
+ ChromePolicy: map[string]any{
+ "foo": "bar",
+ },
DiscardAllIdle: kernel.Bool(false),
Extensions: []shared.BrowserExtensionParam{{
ID: kernel.String("id"),
diff --git a/deployment.go b/deployment.go
index 37b7e64..5d0380c 100644
--- a/deployment.go
+++ b/deployment.go
@@ -130,7 +130,7 @@ type DeploymentStateEvent struct {
// Deployment record information.
Deployment DeploymentStateEventDeployment `json:"deployment" api:"required"`
// Event type identifier (always "deployment_state").
- Event constant.DeploymentState `json:"event" api:"required"`
+ Event constant.DeploymentState `json:"event" default:"deployment_state"`
// Time the state was reported.
Timestamp time.Time `json:"timestamp" api:"required" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
@@ -156,7 +156,7 @@ type DeploymentStateEventDeployment struct {
// Timestamp when the deployment was created
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Current status of the deployment
//
// Any of "queued", "in_progress", "running", "failed", "stopped".
@@ -197,7 +197,7 @@ type DeploymentNewResponse struct {
// Timestamp when the deployment was created
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Current status of the deployment
//
// Any of "queued", "in_progress", "running", "failed", "stopped".
@@ -249,7 +249,7 @@ type DeploymentGetResponse struct {
// Timestamp when the deployment was created
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Current status of the deployment
//
// Any of "queued", "in_progress", "running", "failed", "stopped".
@@ -301,7 +301,7 @@ type DeploymentListResponse struct {
// Timestamp when the deployment was created
CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Current status of the deployment
//
// Any of "queued", "in_progress", "running", "failed", "stopped".
@@ -433,9 +433,9 @@ type DeploymentFollowResponseAppVersionSummaryEvent struct {
// Name of the application
AppName string `json:"app_name" api:"required"`
// Event type identifier (always "app_version_summary").
- Event constant.AppVersionSummary `json:"event" api:"required"`
+ Event constant.AppVersionSummary `json:"event" default:"app_version_summary"`
// Deployment region code
- Region constant.AwsUsEast1a `json:"region" api:"required"`
+ Region constant.AwsUsEast1a `json:"region" default:"aws.us-east-1a"`
// Time the state was reported.
Timestamp time.Time `json:"timestamp" api:"required" format:"date-time"`
// Version label for the application
diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go
index b93e5a3..5cf185c 100644
--- a/internal/apiform/encoder.go
+++ b/internal/apiform/encoder.go
@@ -183,6 +183,18 @@ func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc {
func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
itemEncoder := e.typeEncoder(t.Elem())
keyFn := e.arrayKeyEncoder()
+ if e.arrayFmt == "comma" {
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ if v.Len() == 0 {
+ return nil
+ }
+ elements := make([]string, v.Len())
+ for i := 0; i < v.Len(); i++ {
+ elements[i] = fmt.Sprint(v.Index(i).Interface())
+ }
+ return writer.WriteField(key, strings.Join(elements, ","))
+ }
+ }
return func(key string, v reflect.Value, writer *multipart.Writer) error {
if keyFn == nil {
return fmt.Errorf("apiform: unsupported array format")
@@ -265,6 +277,14 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
}
return typeEncoderFn(key, value, writer)
}
+ } else if ptag.defaultValue != nil {
+ typeEncoderFn := e.typeEncoder(field.Type)
+ encoderFn = func(key string, value reflect.Value, writer *multipart.Writer) error {
+ if value.IsZero() {
+ return typeEncoderFn(key, reflect.ValueOf(ptag.defaultValue), writer)
+ }
+ return typeEncoderFn(key, value, writer)
+ }
} else {
encoderFn = e.typeEncoder(field.Type)
}
diff --git a/internal/apiform/form_test.go b/internal/apiform/form_test.go
index 76d8a92..0660fd1 100644
--- a/internal/apiform/form_test.go
+++ b/internal/apiform/form_test.go
@@ -123,6 +123,11 @@ type StructUnion struct {
param.APIUnion
}
+type ConstantStruct struct {
+ Anchor string `form:"anchor" default:"created_at"`
+ Seconds int `form:"seconds"`
+}
+
type MultipartMarshalerParent struct {
Middle MultipartMarshalerMiddleNext `form:"middle"`
}
@@ -554,6 +559,37 @@ Content-Disposition: form-data; name="union"
Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)),
},
},
+ "constant_zero_value": {
+ `--xxx
+Content-Disposition: form-data; name="anchor"
+
+created_at
+--xxx
+Content-Disposition: form-data; name="seconds"
+
+3600
+--xxx--
+`,
+ ConstantStruct{
+ Seconds: 3600,
+ },
+ },
+ "constant_explicit_value": {
+ `--xxx
+Content-Disposition: form-data; name="anchor"
+
+created_at_override
+--xxx
+Content-Disposition: form-data; name="seconds"
+
+3600
+--xxx--
+`,
+ ConstantStruct{
+ Anchor: "created_at_override",
+ Seconds: 3600,
+ },
+ },
"deeply-nested-struct,brackets": {
`--xxx
Content-Disposition: form-data; name="middle[middleNext][child]"
diff --git a/internal/apiform/tag.go b/internal/apiform/tag.go
index d9915d4..f0c9d14 100644
--- a/internal/apiform/tag.go
+++ b/internal/apiform/tag.go
@@ -9,13 +9,15 @@ const apiStructTag = "api"
const jsonStructTag = "json"
const formStructTag = "form"
const formatStructTag = "format"
+const defaultStructTag = "default"
type parsedStructTag struct {
- name string
- required bool
- extras bool
- metadata bool
- omitzero bool
+ name string
+ required bool
+ extras bool
+ metadata bool
+ omitzero bool
+ defaultValue any
}
func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
@@ -45,9 +47,23 @@ func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool
}
parseApiStructTag(field, &tag)
+ parseDefaultStructTag(field, &tag)
return tag, ok
}
+func parseDefaultStructTag(field reflect.StructField, tag *parsedStructTag) {
+ if field.Type.Kind() != reflect.String {
+ // Only strings are currently supported
+ return
+ }
+
+ raw, ok := field.Tag.Lookup(defaultStructTag)
+ if !ok {
+ return
+ }
+ tag.defaultValue = raw
+}
+
func parseApiStructTag(field reflect.StructField, tag *parsedStructTag) {
raw, ok := field.Tag.Lookup(apiStructTag)
if !ok {
diff --git a/internal/apijson/encoder.go b/internal/apijson/encoder.go
index 0decb73..afe611e 100644
--- a/internal/apijson/encoder.go
+++ b/internal/apijson/encoder.go
@@ -12,6 +12,8 @@ import (
"time"
"github.com/tidwall/sjson"
+
+ shimjson "github.com/kernel/kernel-go-sdk/internal/encoding/json"
)
var encoders sync.Map // map[encoderEntry]encoderFunc
@@ -271,6 +273,12 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
if err != nil {
return nil, err
}
+ if ef.tag.defaultValue != nil && (!field.IsValid() || field.IsZero()) {
+ encoded, err = shimjson.Marshal(ef.tag.defaultValue)
+ if err != nil {
+ return nil, err
+ }
+ }
if encoded == nil {
continue
}
diff --git a/internal/apijson/json_test.go b/internal/apijson/json_test.go
index 19b3614..2853bf9 100644
--- a/internal/apijson/json_test.go
+++ b/internal/apijson/json_test.go
@@ -614,3 +614,20 @@ func TestEncode(t *testing.T) {
})
}
}
+
+type StructWithDefault struct {
+ Type string `json:"type" default:"foo"`
+}
+
+func TestDefault(t *testing.T) {
+ value := StructWithDefault{}
+ expected := `{"type":"foo"}`
+
+ raw, err := Marshal(value)
+ if err != nil {
+ t.Fatalf("serialization of %v failed with error %v", value, err)
+ }
+ if string(raw) != expected {
+ t.Fatalf("expected %+#v to serialize to %s but got %s", value, expected, string(raw))
+ }
+}
diff --git a/internal/apijson/tag.go b/internal/apijson/tag.go
index 17b2130..efcaf8c 100644
--- a/internal/apijson/tag.go
+++ b/internal/apijson/tag.go
@@ -8,13 +8,15 @@ import (
const apiStructTag = "api"
const jsonStructTag = "json"
const formatStructTag = "format"
+const defaultStructTag = "default"
type parsedStructTag struct {
- name string
- required bool
- extras bool
- metadata bool
- inline bool
+ name string
+ required bool
+ extras bool
+ metadata bool
+ inline bool
+ defaultValue any
}
func parseJSONStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
@@ -42,9 +44,23 @@ func parseJSONStructTag(field reflect.StructField) (tag parsedStructTag, ok bool
// the `api` struct tag is only used alongside `json` for custom behaviour
parseApiStructTag(field, &tag)
+ parseDefaultStructTag(field, &tag)
return tag, ok
}
+func parseDefaultStructTag(field reflect.StructField, tag *parsedStructTag) {
+ if field.Type.Kind() != reflect.String {
+ // Only strings are currently supported
+ return
+ }
+
+ raw, ok := field.Tag.Lookup(defaultStructTag)
+ if !ok {
+ return
+ }
+ tag.defaultValue = raw
+}
+
func parseApiStructTag(field reflect.StructField, tag *parsedStructTag) {
raw, ok := field.Tag.Lookup(apiStructTag)
if !ok {
diff --git a/internal/requestconfig/requestconfig.go b/internal/requestconfig/requestconfig.go
index 4be744f..6595f2b 100644
--- a/internal/requestconfig/requestconfig.go
+++ b/internal/requestconfig/requestconfig.go
@@ -121,7 +121,13 @@ func NewRequestConfig(ctx context.Context, method string, u string, body any, ds
}
params := q.Encode()
if params != "" {
- u = u + "?" + params
+ parsed, _ := url.Parse(u)
+ if parsed.RawQuery != "" {
+ parsed.RawQuery = parsed.RawQuery + "&" + params
+ u = parsed.String()
+ } else {
+ u = u + "?" + params
+ }
}
}
if body, ok := body.([]byte); ok {
diff --git a/internal/version.go b/internal/version.go
index 27842b2..0f8ee25 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.44.0" // x-release-please-version
+const PackageVersion = "0.45.0" // x-release-please-version
diff --git a/invocation.go b/invocation.go
index 3a75523..775dd29 100644
--- a/invocation.go
+++ b/invocation.go
@@ -150,7 +150,7 @@ func (r *InvocationService) ListBrowsers(ctx context.Context, id string, opts ..
// An event representing the current state of an invocation.
type InvocationStateEvent struct {
// Event type identifier (always "invocation_state").
- Event constant.InvocationState `json:"event" api:"required"`
+ Event constant.InvocationState `json:"event" default:"invocation_state"`
Invocation InvocationStateEventInvocation `json:"invocation" api:"required"`
// Time the state was reported.
Timestamp time.Time `json:"timestamp" api:"required" format:"date-time"`
diff --git a/shared/shared.go b/shared/shared.go
index 10fcf8f..09471ec 100644
--- a/shared/shared.go
+++ b/shared/shared.go
@@ -257,7 +257,7 @@ func (r *ErrorDetail) UnmarshalJSON(data []byte) error {
type ErrorEvent struct {
Error ErrorModel `json:"error" api:"required"`
// Event type identifier (always "error").
- Event constant.Error `json:"event" api:"required"`
+ Event constant.Error `json:"event" default:"error"`
// Time the error occurred.
Timestamp time.Time `json:"timestamp" api:"required" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
@@ -307,7 +307,7 @@ func (r *ErrorModel) UnmarshalJSON(data []byte) error {
// Heartbeat event sent periodically to keep SSE connection alive.
type HeartbeatEvent struct {
// Event type identifier (always "sse_heartbeat").
- Event constant.SseHeartbeat `json:"event" api:"required"`
+ Event constant.SseHeartbeat `json:"event" default:"sse_heartbeat"`
// Time the heartbeat was sent.
Timestamp time.Time `json:"timestamp" api:"required" format:"date-time"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
@@ -331,7 +331,7 @@ func (HeartbeatEvent) ImplAuthConnectionFollowResponseUnion() {}
// A log entry from the application.
type LogEvent struct {
// Event type identifier (always "log").
- Event constant.Log `json:"event" api:"required"`
+ Event constant.Log `json:"event" default:"log"`
// Log message text.
Message string `json:"message" api:"required"`
// Time the log entry was produced.