diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cc9223..864cbca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,10 @@ on: - 'integrated/**' - 'stl-preview-head/**' - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2aca35a..4208b5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.0" + ".": "0.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index d654666..ba1c7c9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 11 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-4502c65bef0843a6ae96d23bba075433af6bab49b55b544b1522f63e7881c00c.yml -openapi_spec_hash: 3e67b77bbc8cd6155b8f66f3271f2643 -config_hash: c6bab7ac8da570a5abbcfb19db119b6b +configured_endpoints: 15 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-5d4e11bc46eeecee7363d56a9dfe946acee997d5b352c2b0a50c20e742c54d2d.yml +openapi_spec_hash: 333e53ad9c706296b9afdb8ff73bec8f +config_hash: 0fdf285ddd8dee229fd84ea57df9080f diff --git a/CHANGELOG.md b/CHANGELOG.md index ce46874..da53df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## 0.6.0 (2025-06-17) + +Full Changelog: [v0.5.0...v0.6.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.5.0...v0.6.0) + +### Features + +* **api:** update via SDK Studio ([ee8e77a](https://github.com/onkernel/kernel-go-sdk/commit/ee8e77a653cc83084eec067e1060b80e8e99fc27)) +* **api:** update via SDK Studio ([1b2efd8](https://github.com/onkernel/kernel-go-sdk/commit/1b2efd8f083758e39ed2bd9bec8d5f6da0642ece)) +* **api:** update via SDK Studio ([3094578](https://github.com/onkernel/kernel-go-sdk/commit/3094578598220a1b837274b20e0dd4cb4f36fd2c)) +* **api:** update via SDK Studio ([0fec1e5](https://github.com/onkernel/kernel-go-sdk/commit/0fec1e5e8d6b426ade8030ec6836142ddd18cca4)) +* **api:** update via SDK Studio ([b44c90e](https://github.com/onkernel/kernel-go-sdk/commit/b44c90ed4698ca9c849bb20aa85579d0fcd36736)) +* **api:** update via SDK Studio ([d6e1cd6](https://github.com/onkernel/kernel-go-sdk/commit/d6e1cd618e324beb797495636a79016aa9cfe7b1)) +* **api:** update via SDK Studio ([0bc5b00](https://github.com/onkernel/kernel-go-sdk/commit/0bc5b008aad753e6b2a5bf2647b30b389e36c190)) +* **api:** update via SDK Studio ([db224f1](https://github.com/onkernel/kernel-go-sdk/commit/db224f133e8935217833037397839b771e901885)) +* **api:** update via SDK Studio ([3be7afb](https://github.com/onkernel/kernel-go-sdk/commit/3be7afb4985902b399ed45192a139b8f2a67bcf2)) +* **api:** update via SDK Studio ([562f248](https://github.com/onkernel/kernel-go-sdk/commit/562f248c183bc6bd908433c2920b63b596572711)) +* **api:** update via SDK Studio ([984cd7f](https://github.com/onkernel/kernel-go-sdk/commit/984cd7f8a9cbbb153e11895e5b8dd5ba79cc5548)) +* **api:** update via SDK Studio ([48d0b3d](https://github.com/onkernel/kernel-go-sdk/commit/48d0b3d6938a8e4e9db9148b7dc35d7440e43ae2)) +* **api:** update via SDK Studio ([8c6285b](https://github.com/onkernel/kernel-go-sdk/commit/8c6285b9dfff61a9f6b58053026ac18fbde1b66e)) +* **client:** add debug log helper ([5c92a71](https://github.com/onkernel/kernel-go-sdk/commit/5c92a71246d10274fa60eb84a0f42121cbca6e7b)) + + +### Chores + +* **ci:** enable for pull requests ([72fd885](https://github.com/onkernel/kernel-go-sdk/commit/72fd885ebc2a949148fe7fbc5bc809b716a783fe)) + ## 0.5.0 (2025-06-04) Full Changelog: [v0.4.0...v0.5.0](https://github.com/onkernel/kernel-go-sdk/compare/v0.4.0...v0.5.0) diff --git a/README.md b/README.md index 0e2dd3d..cf8bfe3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Or to pin the version: ```sh -go get -u 'github.com/onkernel/kernel-go-sdk@v0.5.0' +go get -u 'github.com/onkernel/kernel-go-sdk@v0.6.0' ``` @@ -280,6 +280,8 @@ client.Browsers.New(context.TODO(), ..., ) ``` +The request option `option.WithDebugLog(nil)` may be helpful while debugging. + See the [full list of request options](https://pkg.go.dev/github.com/onkernel/kernel-go-sdk/option). ### Pagination diff --git a/aliases.go b/aliases.go index 11f53c8..3295d1b 100644 --- a/aliases.go +++ b/aliases.go @@ -5,6 +5,7 @@ package kernel import ( "github.com/onkernel/kernel-go-sdk/internal/apierror" "github.com/onkernel/kernel-go-sdk/packages/param" + "github.com/onkernel/kernel-go-sdk/shared" ) // aliased to make [param.APIUnion] private when embedding @@ -14,3 +15,19 @@ type paramUnion = param.APIUnion type paramObj = param.APIObject type Error = apierror.Error + +// This is an alias to an internal type. +type ErrorDetail = shared.ErrorDetail + +// An error event from the application. +// +// This is an alias to an internal type. +type ErrorEvent = shared.ErrorEvent + +// This is an alias to an internal type. +type ErrorModel = shared.ErrorModel + +// A log entry from the application. +// +// This is an alias to an internal type. +type LogEvent = shared.LogEvent diff --git a/api.md b/api.md index 4fa940d..8e1101b 100644 --- a/api.md +++ b/api.md @@ -1,3 +1,25 @@ +# Shared Response Types + +- shared.ErrorDetail +- shared.ErrorEvent +- shared.ErrorModel +- shared.LogEvent + +# Deployments + +Response Types: + +- kernel.DeploymentStateEvent +- kernel.DeploymentNewResponse +- kernel.DeploymentGetResponse +- kernel.DeploymentFollowResponseUnion + +Methods: + +- client.Deployments.New(ctx context.Context, body kernel.DeploymentNewParams) (kernel.DeploymentNewResponse, error) +- client.Deployments.Get(ctx context.Context, id string) (kernel.DeploymentGetResponse, error) +- client.Deployments.Follow(ctx context.Context, id string) (kernel.DeploymentFollowResponseUnion, error) + # Apps Response Types: @@ -20,19 +42,22 @@ Methods: - client.Apps.Deployments.New(ctx context.Context, body kernel.AppDeploymentNewParams) (kernel.AppDeploymentNewResponse, error) - client.Apps.Deployments.Follow(ctx context.Context, id string) (kernel.AppDeploymentFollowResponseUnion, error) -## Invocations +# Invocations Response Types: -- kernel.AppInvocationNewResponse -- kernel.AppInvocationGetResponse -- kernel.AppInvocationUpdateResponse +- kernel.InvocationStateEvent +- kernel.InvocationNewResponse +- kernel.InvocationGetResponse +- kernel.InvocationUpdateResponse +- kernel.InvocationFollowResponseUnion Methods: -- client.Apps.Invocations.New(ctx context.Context, body kernel.AppInvocationNewParams) (kernel.AppInvocationNewResponse, error) -- client.Apps.Invocations.Get(ctx context.Context, id string) (kernel.AppInvocationGetResponse, error) -- client.Apps.Invocations.Update(ctx context.Context, id string, body kernel.AppInvocationUpdateParams) (kernel.AppInvocationUpdateResponse, error) +- client.Invocations.New(ctx context.Context, body kernel.InvocationNewParams) (kernel.InvocationNewResponse, error) +- client.Invocations.Get(ctx context.Context, id string) (kernel.InvocationGetResponse, error) +- client.Invocations.Update(ctx context.Context, id string, body kernel.InvocationUpdateParams) (kernel.InvocationUpdateResponse, error) +- client.Invocations.Follow(ctx context.Context, id string) (kernel.InvocationFollowResponseUnion, error) # Browsers diff --git a/app.go b/app.go index 6e6f185..a38ef15 100644 --- a/app.go +++ b/app.go @@ -13,6 +13,7 @@ import ( "github.com/onkernel/kernel-go-sdk/option" "github.com/onkernel/kernel-go-sdk/packages/param" "github.com/onkernel/kernel-go-sdk/packages/respjson" + "github.com/onkernel/kernel-go-sdk/shared/constant" ) // AppService contains methods and other services that help with interacting with @@ -24,7 +25,6 @@ import ( type AppService struct { Options []option.RequestOption Deployments AppDeploymentService - Invocations AppInvocationService } // NewAppService generates a new service that applies the given options to each @@ -34,7 +34,6 @@ func NewAppService(opts ...option.RequestOption) (r AppService) { r = AppService{} r.Options = opts r.Deployments = NewAppDeploymentService(opts...) - r.Invocations = NewAppInvocationService(opts...) return } @@ -53,7 +52,7 @@ type AppListResponse struct { // Name of the application AppName string `json:"app_name,required"` // Deployment region code - Region string `json:"region,required"` + Region constant.AwsUsEast1a `json:"region,required"` // Version label for the application Version string `json:"version,required"` // Environment variables configured for this app version diff --git a/appdeployment.go b/appdeployment.go index 373e942..0199bd0 100644 --- a/appdeployment.go +++ b/appdeployment.go @@ -20,6 +20,7 @@ import ( "github.com/onkernel/kernel-go-sdk/packages/param" "github.com/onkernel/kernel-go-sdk/packages/respjson" "github.com/onkernel/kernel-go-sdk/packages/ssestream" + "github.com/onkernel/kernel-go-sdk/shared" "github.com/onkernel/kernel-go-sdk/shared/constant" ) @@ -146,7 +147,7 @@ const ( // AppDeploymentFollowResponseUnion contains all possible properties and values // from [AppDeploymentFollowResponseState], -// [AppDeploymentFollowResponseStateUpdate], [AppDeploymentFollowResponseLog]. +// [AppDeploymentFollowResponseStateUpdate], [shared.LogEvent]. // // Use the [AppDeploymentFollowResponseUnion.AsAny] method to switch on the // variant. @@ -157,7 +158,7 @@ type AppDeploymentFollowResponseUnion struct { Event string `json:"event"` State string `json:"state"` Timestamp time.Time `json:"timestamp"` - // This field is from variant [AppDeploymentFollowResponseLog]. + // This field is from variant [shared.LogEvent]. Message string `json:"message"` JSON struct { Event respjson.Field @@ -172,19 +173,18 @@ type AppDeploymentFollowResponseUnion struct { // [AppDeploymentFollowResponseUnion] to add type safety for the return type of // [AppDeploymentFollowResponseUnion.AsAny] type anyAppDeploymentFollowResponse interface { - implAppDeploymentFollowResponseUnion() + ImplAppDeploymentFollowResponseUnion() } -func (AppDeploymentFollowResponseState) implAppDeploymentFollowResponseUnion() {} -func (AppDeploymentFollowResponseStateUpdate) implAppDeploymentFollowResponseUnion() {} -func (AppDeploymentFollowResponseLog) implAppDeploymentFollowResponseUnion() {} +func (AppDeploymentFollowResponseState) ImplAppDeploymentFollowResponseUnion() {} +func (AppDeploymentFollowResponseStateUpdate) ImplAppDeploymentFollowResponseUnion() {} // Use the following switch statement to find the correct variant // // switch variant := AppDeploymentFollowResponseUnion.AsAny().(type) { // case kernel.AppDeploymentFollowResponseState: // case kernel.AppDeploymentFollowResponseStateUpdate: -// case kernel.AppDeploymentFollowResponseLog: +// case shared.LogEvent: // default: // fmt.Errorf("no variant present") // } @@ -210,7 +210,7 @@ func (u AppDeploymentFollowResponseUnion) AsStateUpdate() (v AppDeploymentFollow return } -func (u AppDeploymentFollowResponseUnion) AsLog() (v AppDeploymentFollowResponseLog) { +func (u AppDeploymentFollowResponseUnion) AsLog() (v shared.LogEvent) { apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) return } @@ -270,30 +270,6 @@ func (r *AppDeploymentFollowResponseStateUpdate) UnmarshalJSON(data []byte) erro return apijson.UnmarshalRoot(data, r) } -// A log entry from the application. -type AppDeploymentFollowResponseLog struct { - // Event type identifier (always "log"). - Event constant.Log `json:"event,required"` - // Log message text. - Message string `json:"message,required"` - // Time the log entry was produced. - Timestamp time.Time `json:"timestamp" format:"date-time"` - // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. - JSON struct { - Event respjson.Field - Message respjson.Field - Timestamp respjson.Field - ExtraFields map[string]respjson.Field - raw string - } `json:"-"` -} - -// Returns the unmodified JSON received from the API -func (r AppDeploymentFollowResponseLog) RawJSON() string { return r.JSON.raw } -func (r *AppDeploymentFollowResponseLog) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - type AppDeploymentNewParams struct { // Relative path to the entrypoint of the application EntrypointRelPath string `json:"entrypoint_rel_path,required"` diff --git a/appinvocation.go b/appinvocation.go deleted file mode 100644 index 18663be..0000000 --- a/appinvocation.go +++ /dev/null @@ -1,266 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -package kernel - -import ( - "context" - "errors" - "fmt" - "net/http" - "time" - - "github.com/onkernel/kernel-go-sdk/internal/apijson" - "github.com/onkernel/kernel-go-sdk/internal/requestconfig" - "github.com/onkernel/kernel-go-sdk/option" - "github.com/onkernel/kernel-go-sdk/packages/param" - "github.com/onkernel/kernel-go-sdk/packages/respjson" -) - -// AppInvocationService contains methods and other services that help with -// interacting with the kernel API. -// -// Note, unlike clients, this service does not read variables from the environment -// automatically. You should not instantiate this service directly, and instead use -// the [NewAppInvocationService] method instead. -type AppInvocationService struct { - Options []option.RequestOption -} - -// NewAppInvocationService generates a new service that applies the given options -// to each request. These options are applied after the parent client's options (if -// there is one), and before any request-specific options. -func NewAppInvocationService(opts ...option.RequestOption) (r AppInvocationService) { - r = AppInvocationService{} - r.Options = opts - return -} - -// Invoke an action. -func (r *AppInvocationService) New(ctx context.Context, body AppInvocationNewParams, opts ...option.RequestOption) (res *AppInvocationNewResponse, err error) { - opts = append(r.Options[:], opts...) - path := "invocations" - err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) - return -} - -// Get details about an invocation's status and output. -func (r *AppInvocationService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *AppInvocationGetResponse, err error) { - opts = append(r.Options[:], opts...) - if id == "" { - err = errors.New("missing required id parameter") - return - } - path := fmt.Sprintf("invocations/%s", id) - err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) - return -} - -// Update an invocation's status or output. -func (r *AppInvocationService) Update(ctx context.Context, id string, body AppInvocationUpdateParams, opts ...option.RequestOption) (res *AppInvocationUpdateResponse, err error) { - opts = append(r.Options[:], opts...) - if id == "" { - err = errors.New("missing required id parameter") - return - } - path := fmt.Sprintf("invocations/%s", id) - err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...) - return -} - -type AppInvocationNewResponse struct { - // ID of the invocation - ID string `json:"id,required"` - // Status of the invocation - // - // Any of "queued", "running", "succeeded", "failed". - Status AppInvocationNewResponseStatus `json:"status,required"` - // The return value of the action that was invoked, rendered as a JSON string. This - // could be: string, number, boolean, array, object, or null. - Output string `json:"output"` - // Status reason - StatusReason string `json:"status_reason"` - // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. - JSON struct { - ID respjson.Field - Status respjson.Field - Output respjson.Field - StatusReason respjson.Field - ExtraFields map[string]respjson.Field - raw string - } `json:"-"` -} - -// Returns the unmodified JSON received from the API -func (r AppInvocationNewResponse) RawJSON() string { return r.JSON.raw } -func (r *AppInvocationNewResponse) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// Status of the invocation -type AppInvocationNewResponseStatus string - -const ( - AppInvocationNewResponseStatusQueued AppInvocationNewResponseStatus = "queued" - AppInvocationNewResponseStatusRunning AppInvocationNewResponseStatus = "running" - AppInvocationNewResponseStatusSucceeded AppInvocationNewResponseStatus = "succeeded" - AppInvocationNewResponseStatusFailed AppInvocationNewResponseStatus = "failed" -) - -type AppInvocationGetResponse struct { - // ID of the invocation - ID string `json:"id,required"` - // Name of the action invoked - ActionName string `json:"action_name,required"` - // Name of the application - AppName string `json:"app_name,required"` - // RFC 3339 Nanoseconds timestamp when the invocation started - StartedAt time.Time `json:"started_at,required" format:"date-time"` - // Status of the invocation - // - // Any of "queued", "running", "succeeded", "failed". - Status AppInvocationGetResponseStatus `json:"status,required"` - // RFC 3339 Nanoseconds timestamp when the invocation finished (null if still - // running) - FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"` - // Output produced by the action, rendered as a JSON string. This could be: string, - // number, boolean, array, object, or null. - Output string `json:"output"` - // Payload provided to the invocation. This is a string that can be parsed as JSON. - Payload string `json:"payload"` - // Status reason - StatusReason string `json:"status_reason"` - // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. - JSON struct { - ID respjson.Field - ActionName respjson.Field - AppName respjson.Field - StartedAt respjson.Field - Status respjson.Field - FinishedAt respjson.Field - Output respjson.Field - Payload respjson.Field - StatusReason respjson.Field - ExtraFields map[string]respjson.Field - raw string - } `json:"-"` -} - -// Returns the unmodified JSON received from the API -func (r AppInvocationGetResponse) RawJSON() string { return r.JSON.raw } -func (r *AppInvocationGetResponse) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// Status of the invocation -type AppInvocationGetResponseStatus string - -const ( - AppInvocationGetResponseStatusQueued AppInvocationGetResponseStatus = "queued" - AppInvocationGetResponseStatusRunning AppInvocationGetResponseStatus = "running" - AppInvocationGetResponseStatusSucceeded AppInvocationGetResponseStatus = "succeeded" - AppInvocationGetResponseStatusFailed AppInvocationGetResponseStatus = "failed" -) - -type AppInvocationUpdateResponse struct { - // ID of the invocation - ID string `json:"id,required"` - // Name of the action invoked - ActionName string `json:"action_name,required"` - // Name of the application - AppName string `json:"app_name,required"` - // RFC 3339 Nanoseconds timestamp when the invocation started - StartedAt time.Time `json:"started_at,required" format:"date-time"` - // Status of the invocation - // - // Any of "queued", "running", "succeeded", "failed". - Status AppInvocationUpdateResponseStatus `json:"status,required"` - // RFC 3339 Nanoseconds timestamp when the invocation finished (null if still - // running) - FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"` - // Output produced by the action, rendered as a JSON string. This could be: string, - // number, boolean, array, object, or null. - Output string `json:"output"` - // Payload provided to the invocation. This is a string that can be parsed as JSON. - Payload string `json:"payload"` - // Status reason - StatusReason string `json:"status_reason"` - // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. - JSON struct { - ID respjson.Field - ActionName respjson.Field - AppName respjson.Field - StartedAt respjson.Field - Status respjson.Field - FinishedAt respjson.Field - Output respjson.Field - Payload respjson.Field - StatusReason respjson.Field - ExtraFields map[string]respjson.Field - raw string - } `json:"-"` -} - -// Returns the unmodified JSON received from the API -func (r AppInvocationUpdateResponse) RawJSON() string { return r.JSON.raw } -func (r *AppInvocationUpdateResponse) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// Status of the invocation -type AppInvocationUpdateResponseStatus string - -const ( - AppInvocationUpdateResponseStatusQueued AppInvocationUpdateResponseStatus = "queued" - AppInvocationUpdateResponseStatusRunning AppInvocationUpdateResponseStatus = "running" - AppInvocationUpdateResponseStatusSucceeded AppInvocationUpdateResponseStatus = "succeeded" - AppInvocationUpdateResponseStatusFailed AppInvocationUpdateResponseStatus = "failed" -) - -type AppInvocationNewParams struct { - // Name of the action to invoke - ActionName string `json:"action_name,required"` - // Name of the application - AppName string `json:"app_name,required"` - // Version of the application - Version string `json:"version,required"` - // If true, invoke asynchronously. When set, the API responds 202 Accepted with - // status "queued". - Async param.Opt[bool] `json:"async,omitzero"` - // Input data for the action, sent as a JSON string. - Payload param.Opt[string] `json:"payload,omitzero"` - paramObj -} - -func (r AppInvocationNewParams) MarshalJSON() (data []byte, err error) { - type shadow AppInvocationNewParams - return param.MarshalObject(r, (*shadow)(&r)) -} -func (r *AppInvocationNewParams) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -type AppInvocationUpdateParams struct { - // New status for the invocation. - // - // Any of "succeeded", "failed". - Status AppInvocationUpdateParamsStatus `json:"status,omitzero,required"` - // Updated output of the invocation rendered as JSON string. - Output param.Opt[string] `json:"output,omitzero"` - paramObj -} - -func (r AppInvocationUpdateParams) MarshalJSON() (data []byte, err error) { - type shadow AppInvocationUpdateParams - return param.MarshalObject(r, (*shadow)(&r)) -} -func (r *AppInvocationUpdateParams) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// New status for the invocation. -type AppInvocationUpdateParamsStatus string - -const ( - AppInvocationUpdateParamsStatusSucceeded AppInvocationUpdateParamsStatus = "succeeded" - AppInvocationUpdateParamsStatusFailed AppInvocationUpdateParamsStatus = "failed" -) diff --git a/client.go b/client.go index fe8f57a..526823e 100644 --- a/client.go +++ b/client.go @@ -15,9 +15,11 @@ import ( // interacting with the kernel API. You should not instantiate this client // directly, and instead use the [NewClient] method instead. type Client struct { - Options []option.RequestOption - Apps AppService - Browsers BrowserService + Options []option.RequestOption + Deployments DeploymentService + Apps AppService + Invocations InvocationService + Browsers BrowserService } // DefaultClientOptions read from the environment (KERNEL_API_KEY, @@ -42,7 +44,9 @@ func NewClient(opts ...option.RequestOption) (r Client) { r = Client{Options: opts} + r.Deployments = NewDeploymentService(opts...) r.Apps = NewAppService(opts...) + r.Invocations = NewInvocationService(opts...) r.Browsers = NewBrowserService(opts...) return diff --git a/client_test.go b/client_test.go index 6dd92d2..6abf48c 100644 --- a/client_test.go +++ b/client_test.go @@ -311,7 +311,7 @@ func TestContextDeadlineStreaming(t *testing.T) { }, }), ) - stream := client.Apps.Deployments.FollowStreaming(deadlineCtx, "id") + stream := client.Deployments.FollowStreaming(deadlineCtx, "id") for stream.Next() { _ = stream.Current() } @@ -356,7 +356,7 @@ func TestContextDeadlineStreamingWithRequestTimeout(t *testing.T) { }, }), ) - stream := client.Apps.Deployments.FollowStreaming( + stream := client.Deployments.FollowStreaming( context.Background(), "id", option.WithRequestTimeout((100 * time.Millisecond)), diff --git a/deployment.go b/deployment.go new file mode 100644 index 0000000..70422aa --- /dev/null +++ b/deployment.go @@ -0,0 +1,425 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "time" + + "github.com/onkernel/kernel-go-sdk/internal/apiform" + "github.com/onkernel/kernel-go-sdk/internal/apijson" + "github.com/onkernel/kernel-go-sdk/internal/requestconfig" + "github.com/onkernel/kernel-go-sdk/option" + "github.com/onkernel/kernel-go-sdk/packages/param" + "github.com/onkernel/kernel-go-sdk/packages/respjson" + "github.com/onkernel/kernel-go-sdk/packages/ssestream" + "github.com/onkernel/kernel-go-sdk/shared" + "github.com/onkernel/kernel-go-sdk/shared/constant" +) + +// DeploymentService contains methods and other services that help with interacting +// with the kernel API. +// +// Note, unlike clients, this service does not read variables from the environment +// automatically. You should not instantiate this service directly, and instead use +// the [NewDeploymentService] method instead. +type DeploymentService struct { + Options []option.RequestOption +} + +// NewDeploymentService generates a new service that applies the given options to +// each request. These options are applied after the parent client's options (if +// there is one), and before any request-specific options. +func NewDeploymentService(opts ...option.RequestOption) (r DeploymentService) { + r = DeploymentService{} + r.Options = opts + return +} + +// Create a new deployment. +func (r *DeploymentService) New(ctx context.Context, body DeploymentNewParams, opts ...option.RequestOption) (res *DeploymentNewResponse, err error) { + opts = append(r.Options[:], opts...) + path := "deployments" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Get information about a deployment's status. +func (r *DeploymentService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *DeploymentGetResponse, err error) { + opts = append(r.Options[:], opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("deployments/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return +} + +// Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and +// status updates for a deployment. The stream terminates automatically once the +// deployment reaches a terminal state. +func (r *DeploymentService) FollowStreaming(ctx context.Context, id string, opts ...option.RequestOption) (stream *ssestream.Stream[DeploymentFollowResponseUnion]) { + var ( + raw *http.Response + err error + ) + opts = append(r.Options[:], opts...) + opts = append([]option.RequestOption{option.WithHeader("Accept", "text/event-stream")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("deployments/%s/events", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &raw, opts...) + return ssestream.NewStream[DeploymentFollowResponseUnion](ssestream.NewDecoder(raw), err) +} + +// An event representing the current state of a deployment. +type DeploymentStateEvent struct { + // Deployment record information. + Deployment DeploymentStateEventDeployment `json:"deployment,required"` + // Event type identifier (always "deployment_state"). + Event constant.DeploymentState `json:"event,required"` + // Time the state was reported. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Deployment respjson.Field + Event respjson.Field + Timestamp respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentStateEvent) RawJSON() string { return r.JSON.raw } +func (r *DeploymentStateEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Deployment record information. +type DeploymentStateEventDeployment struct { + // Unique identifier for the deployment + ID string `json:"id,required"` + // Timestamp when the deployment was created + CreatedAt time.Time `json:"created_at,required" format:"date-time"` + // Deployment region code + Region constant.AwsUsEast1a `json:"region,required"` + // Current status of the deployment + // + // Any of "queued", "in_progress", "running", "failed", "stopped". + Status string `json:"status,required"` + // Relative path to the application entrypoint + EntrypointRelPath string `json:"entrypoint_rel_path"` + // Environment variables configured for this deployment + EnvVars map[string]string `json:"env_vars"` + // Status reason + StatusReason string `json:"status_reason"` + // Timestamp when the deployment was last updated + UpdatedAt time.Time `json:"updated_at,nullable" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + CreatedAt respjson.Field + Region respjson.Field + Status respjson.Field + EntrypointRelPath respjson.Field + EnvVars respjson.Field + StatusReason respjson.Field + UpdatedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentStateEventDeployment) RawJSON() string { return r.JSON.raw } +func (r *DeploymentStateEventDeployment) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Deployment record information. +type DeploymentNewResponse struct { + // Unique identifier for the deployment + ID string `json:"id,required"` + // Timestamp when the deployment was created + CreatedAt time.Time `json:"created_at,required" format:"date-time"` + // Deployment region code + Region constant.AwsUsEast1a `json:"region,required"` + // Current status of the deployment + // + // Any of "queued", "in_progress", "running", "failed", "stopped". + Status DeploymentNewResponseStatus `json:"status,required"` + // Relative path to the application entrypoint + EntrypointRelPath string `json:"entrypoint_rel_path"` + // Environment variables configured for this deployment + EnvVars map[string]string `json:"env_vars"` + // Status reason + StatusReason string `json:"status_reason"` + // Timestamp when the deployment was last updated + UpdatedAt time.Time `json:"updated_at,nullable" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + CreatedAt respjson.Field + Region respjson.Field + Status respjson.Field + EntrypointRelPath respjson.Field + EnvVars respjson.Field + StatusReason respjson.Field + UpdatedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentNewResponse) RawJSON() string { return r.JSON.raw } +func (r *DeploymentNewResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current status of the deployment +type DeploymentNewResponseStatus string + +const ( + DeploymentNewResponseStatusQueued DeploymentNewResponseStatus = "queued" + DeploymentNewResponseStatusInProgress DeploymentNewResponseStatus = "in_progress" + DeploymentNewResponseStatusRunning DeploymentNewResponseStatus = "running" + DeploymentNewResponseStatusFailed DeploymentNewResponseStatus = "failed" + DeploymentNewResponseStatusStopped DeploymentNewResponseStatus = "stopped" +) + +// Deployment record information. +type DeploymentGetResponse struct { + // Unique identifier for the deployment + ID string `json:"id,required"` + // Timestamp when the deployment was created + CreatedAt time.Time `json:"created_at,required" format:"date-time"` + // Deployment region code + Region constant.AwsUsEast1a `json:"region,required"` + // Current status of the deployment + // + // Any of "queued", "in_progress", "running", "failed", "stopped". + Status DeploymentGetResponseStatus `json:"status,required"` + // Relative path to the application entrypoint + EntrypointRelPath string `json:"entrypoint_rel_path"` + // Environment variables configured for this deployment + EnvVars map[string]string `json:"env_vars"` + // Status reason + StatusReason string `json:"status_reason"` + // Timestamp when the deployment was last updated + UpdatedAt time.Time `json:"updated_at,nullable" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + CreatedAt respjson.Field + Region respjson.Field + Status respjson.Field + EntrypointRelPath respjson.Field + EnvVars respjson.Field + StatusReason respjson.Field + UpdatedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentGetResponse) RawJSON() string { return r.JSON.raw } +func (r *DeploymentGetResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current status of the deployment +type DeploymentGetResponseStatus string + +const ( + DeploymentGetResponseStatusQueued DeploymentGetResponseStatus = "queued" + DeploymentGetResponseStatusInProgress DeploymentGetResponseStatus = "in_progress" + DeploymentGetResponseStatusRunning DeploymentGetResponseStatus = "running" + DeploymentGetResponseStatusFailed DeploymentGetResponseStatus = "failed" + DeploymentGetResponseStatusStopped DeploymentGetResponseStatus = "stopped" +) + +// DeploymentFollowResponseUnion contains all possible properties and values from +// [shared.LogEvent], [DeploymentStateEvent], +// [DeploymentFollowResponseAppVersionSummaryEvent], [shared.ErrorEvent]. +// +// Use the [DeploymentFollowResponseUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type DeploymentFollowResponseUnion struct { + // Any of "log", "deployment_state", nil, nil. + Event string `json:"event"` + // This field is from variant [shared.LogEvent]. + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + // This field is from variant [DeploymentStateEvent]. + Deployment DeploymentStateEventDeployment `json:"deployment"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + ID string `json:"id"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + Actions []DeploymentFollowResponseAppVersionSummaryEventAction `json:"actions"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + AppName string `json:"app_name"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + Region constant.AwsUsEast1a `json:"region"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + Version string `json:"version"` + // This field is from variant [DeploymentFollowResponseAppVersionSummaryEvent]. + EnvVars map[string]string `json:"env_vars"` + // This field is from variant [shared.ErrorEvent]. + Error shared.ErrorModel `json:"error"` + JSON struct { + Event respjson.Field + Message respjson.Field + Timestamp respjson.Field + Deployment respjson.Field + ID respjson.Field + Actions respjson.Field + AppName respjson.Field + Region respjson.Field + Version respjson.Field + EnvVars respjson.Field + Error respjson.Field + raw string + } `json:"-"` +} + +func (u DeploymentFollowResponseUnion) AsLog() (v shared.LogEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u DeploymentFollowResponseUnion) AsDeploymentState() (v DeploymentStateEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u DeploymentFollowResponseUnion) AsDeploymentFollowResponseAppVersionSummaryEvent() (v DeploymentFollowResponseAppVersionSummaryEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u DeploymentFollowResponseUnion) AsErrorEvent() (v shared.ErrorEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u DeploymentFollowResponseUnion) RawJSON() string { return u.JSON.raw } + +func (r *DeploymentFollowResponseUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Summary of an application version. +type DeploymentFollowResponseAppVersionSummaryEvent struct { + // Unique identifier for the app version + ID string `json:"id,required"` + // List of actions available on the app + Actions []DeploymentFollowResponseAppVersionSummaryEventAction `json:"actions,required"` + // Name of the application + AppName string `json:"app_name,required"` + // Event type identifier (always "app_version_summary"). + Event constant.AppVersionSummary `json:"event,required"` + // Deployment region code + Region constant.AwsUsEast1a `json:"region,required"` + // Time the state was reported. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // Version label for the application + Version string `json:"version,required"` + // Environment variables configured for this app version + EnvVars map[string]string `json:"env_vars"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Actions respjson.Field + AppName respjson.Field + Event respjson.Field + Region respjson.Field + Timestamp respjson.Field + Version respjson.Field + EnvVars respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentFollowResponseAppVersionSummaryEvent) RawJSON() string { return r.JSON.raw } +func (r *DeploymentFollowResponseAppVersionSummaryEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An action available on the app +type DeploymentFollowResponseAppVersionSummaryEventAction struct { + // Name of the action + Name string `json:"name,required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Name respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r DeploymentFollowResponseAppVersionSummaryEventAction) RawJSON() string { return r.JSON.raw } +func (r *DeploymentFollowResponseAppVersionSummaryEventAction) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type DeploymentNewParams struct { + // Relative path to the entrypoint of the application + EntrypointRelPath string `json:"entrypoint_rel_path,required"` + // ZIP file containing the application source directory + File io.Reader `json:"file,omitzero,required" format:"binary"` + // Allow overwriting an existing app version + Force param.Opt[bool] `json:"force,omitzero"` + // Version of the application. Can be any string. + Version param.Opt[string] `json:"version,omitzero"` + // Map of environment variables to set for the deployed application. Each key-value + // pair represents an environment variable. + EnvVars map[string]string `json:"env_vars,omitzero"` + // Region for deployment. Currently we only support "aws.us-east-1a" + // + // Any of "aws.us-east-1a". + Region DeploymentNewParamsRegion `json:"region,omitzero"` + paramObj +} + +func (r DeploymentNewParams) MarshalMultipart() (data []byte, contentType string, err error) { + buf := bytes.NewBuffer(nil) + writer := multipart.NewWriter(buf) + err = apiform.MarshalRoot(r, writer) + if err == nil { + err = apiform.WriteExtras(writer, r.ExtraFields()) + } + if err != nil { + writer.Close() + return nil, "", err + } + err = writer.Close() + if err != nil { + return nil, "", err + } + return buf.Bytes(), writer.FormDataContentType(), nil +} + +// Region for deployment. Currently we only support "aws.us-east-1a" +type DeploymentNewParamsRegion string + +const ( + DeploymentNewParamsRegionAwsUsEast1a DeploymentNewParamsRegion = "aws.us-east-1a" +) diff --git a/deployment_test.go b/deployment_test.go new file mode 100644 index 0000000..e4c49ec --- /dev/null +++ b/deployment_test.go @@ -0,0 +1,71 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel_test + +import ( + "bytes" + "context" + "errors" + "io" + "os" + "testing" + + "github.com/onkernel/kernel-go-sdk" + "github.com/onkernel/kernel-go-sdk/internal/testutil" + "github.com/onkernel/kernel-go-sdk/option" +) + +func TestDeploymentNewWithOptionalParams(t *testing.T) { + t.Skip("skipped: tests are disabled for the time being") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Deployments.New(context.TODO(), kernel.DeploymentNewParams{ + EntrypointRelPath: "src/app.py", + File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + EnvVars: map[string]string{ + "foo": "string", + }, + Force: kernel.Bool(false), + Region: kernel.DeploymentNewParamsRegionAwsUsEast1a, + Version: kernel.String("1.0.0"), + }) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestDeploymentGet(t *testing.T) { + t.Skip("skipped: tests are disabled for the time being") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Deployments.Get(context.TODO(), "id") + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} diff --git a/internal/version.go b/internal/version.go index 67c4d40..577a4dc 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.5.0" // x-release-please-version +const PackageVersion = "0.6.0" // x-release-please-version diff --git a/invocation.go b/invocation.go new file mode 100644 index 0000000..22a5f0a --- /dev/null +++ b/invocation.go @@ -0,0 +1,435 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "time" + + "github.com/onkernel/kernel-go-sdk/internal/apijson" + "github.com/onkernel/kernel-go-sdk/internal/requestconfig" + "github.com/onkernel/kernel-go-sdk/option" + "github.com/onkernel/kernel-go-sdk/packages/param" + "github.com/onkernel/kernel-go-sdk/packages/respjson" + "github.com/onkernel/kernel-go-sdk/packages/ssestream" + "github.com/onkernel/kernel-go-sdk/shared" + "github.com/onkernel/kernel-go-sdk/shared/constant" +) + +// InvocationService contains methods and other services that help with interacting +// with the kernel API. +// +// Note, unlike clients, this service does not read variables from the environment +// automatically. You should not instantiate this service directly, and instead use +// the [NewInvocationService] method instead. +type InvocationService struct { + Options []option.RequestOption +} + +// NewInvocationService generates a new service that applies the given options to +// each request. These options are applied after the parent client's options (if +// there is one), and before any request-specific options. +func NewInvocationService(opts ...option.RequestOption) (r InvocationService) { + r = InvocationService{} + r.Options = opts + return +} + +// Invoke an action. +func (r *InvocationService) New(ctx context.Context, body InvocationNewParams, opts ...option.RequestOption) (res *InvocationNewResponse, err error) { + opts = append(r.Options[:], opts...) + path := "invocations" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Get details about an invocation's status and output. +func (r *InvocationService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *InvocationGetResponse, err error) { + opts = append(r.Options[:], opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("invocations/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return +} + +// Update an invocation's status or output. +func (r *InvocationService) Update(ctx context.Context, id string, body InvocationUpdateParams, opts ...option.RequestOption) (res *InvocationUpdateResponse, err error) { + opts = append(r.Options[:], opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("invocations/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...) + return +} + +// Establishes a Server-Sent Events (SSE) stream that delivers real-time logs and +// status updates for an invocation. The stream terminates automatically once the +// invocation reaches a terminal state. +func (r *InvocationService) FollowStreaming(ctx context.Context, id string, opts ...option.RequestOption) (stream *ssestream.Stream[InvocationFollowResponseUnion]) { + var ( + raw *http.Response + err error + ) + opts = append(r.Options[:], opts...) + opts = append([]option.RequestOption{option.WithHeader("Accept", "text/event-stream")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("invocations/%s/events", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &raw, opts...) + return ssestream.NewStream[InvocationFollowResponseUnion](ssestream.NewDecoder(raw), err) +} + +// An event representing the current state of an invocation. +type InvocationStateEvent struct { + // Event type identifier (always "invocation_state"). + Event constant.InvocationState `json:"event,required"` + Invocation InvocationStateEventInvocation `json:"invocation,required"` + // Time the state was reported. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Event respjson.Field + Invocation respjson.Field + Timestamp respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r InvocationStateEvent) RawJSON() string { return r.JSON.raw } +func (r *InvocationStateEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type InvocationStateEventInvocation struct { + // ID of the invocation + ID string `json:"id,required"` + // Name of the action invoked + ActionName string `json:"action_name,required"` + // Name of the application + AppName string `json:"app_name,required"` + // RFC 3339 Nanoseconds timestamp when the invocation started + StartedAt time.Time `json:"started_at,required" format:"date-time"` + // Status of the invocation + // + // Any of "queued", "running", "succeeded", "failed". + Status string `json:"status,required"` + // RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + // running) + FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"` + // Output produced by the action, rendered as a JSON string. This could be: string, + // number, boolean, array, object, or null. + Output string `json:"output"` + // Payload provided to the invocation. This is a string that can be parsed as JSON. + Payload string `json:"payload"` + // Status reason + StatusReason string `json:"status_reason"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + ActionName respjson.Field + AppName respjson.Field + StartedAt respjson.Field + Status respjson.Field + FinishedAt respjson.Field + Output respjson.Field + Payload respjson.Field + StatusReason respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r InvocationStateEventInvocation) RawJSON() string { return r.JSON.raw } +func (r *InvocationStateEventInvocation) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type InvocationNewResponse struct { + // ID of the invocation + ID string `json:"id,required"` + // Status of the invocation + // + // Any of "queued", "running", "succeeded", "failed". + Status InvocationNewResponseStatus `json:"status,required"` + // The return value of the action that was invoked, rendered as a JSON string. This + // could be: string, number, boolean, array, object, or null. + Output string `json:"output"` + // Status reason + StatusReason string `json:"status_reason"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Status respjson.Field + Output respjson.Field + StatusReason respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r InvocationNewResponse) RawJSON() string { return r.JSON.raw } +func (r *InvocationNewResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Status of the invocation +type InvocationNewResponseStatus string + +const ( + InvocationNewResponseStatusQueued InvocationNewResponseStatus = "queued" + InvocationNewResponseStatusRunning InvocationNewResponseStatus = "running" + InvocationNewResponseStatusSucceeded InvocationNewResponseStatus = "succeeded" + InvocationNewResponseStatusFailed InvocationNewResponseStatus = "failed" +) + +type InvocationGetResponse struct { + // ID of the invocation + ID string `json:"id,required"` + // Name of the action invoked + ActionName string `json:"action_name,required"` + // Name of the application + AppName string `json:"app_name,required"` + // RFC 3339 Nanoseconds timestamp when the invocation started + StartedAt time.Time `json:"started_at,required" format:"date-time"` + // Status of the invocation + // + // Any of "queued", "running", "succeeded", "failed". + Status InvocationGetResponseStatus `json:"status,required"` + // RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + // running) + FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"` + // Output produced by the action, rendered as a JSON string. This could be: string, + // number, boolean, array, object, or null. + Output string `json:"output"` + // Payload provided to the invocation. This is a string that can be parsed as JSON. + Payload string `json:"payload"` + // Status reason + StatusReason string `json:"status_reason"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + ActionName respjson.Field + AppName respjson.Field + StartedAt respjson.Field + Status respjson.Field + FinishedAt respjson.Field + Output respjson.Field + Payload respjson.Field + StatusReason respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r InvocationGetResponse) RawJSON() string { return r.JSON.raw } +func (r *InvocationGetResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Status of the invocation +type InvocationGetResponseStatus string + +const ( + InvocationGetResponseStatusQueued InvocationGetResponseStatus = "queued" + InvocationGetResponseStatusRunning InvocationGetResponseStatus = "running" + InvocationGetResponseStatusSucceeded InvocationGetResponseStatus = "succeeded" + InvocationGetResponseStatusFailed InvocationGetResponseStatus = "failed" +) + +type InvocationUpdateResponse struct { + // ID of the invocation + ID string `json:"id,required"` + // Name of the action invoked + ActionName string `json:"action_name,required"` + // Name of the application + AppName string `json:"app_name,required"` + // RFC 3339 Nanoseconds timestamp when the invocation started + StartedAt time.Time `json:"started_at,required" format:"date-time"` + // Status of the invocation + // + // Any of "queued", "running", "succeeded", "failed". + Status InvocationUpdateResponseStatus `json:"status,required"` + // RFC 3339 Nanoseconds timestamp when the invocation finished (null if still + // running) + FinishedAt time.Time `json:"finished_at,nullable" format:"date-time"` + // Output produced by the action, rendered as a JSON string. This could be: string, + // number, boolean, array, object, or null. + Output string `json:"output"` + // Payload provided to the invocation. This is a string that can be parsed as JSON. + Payload string `json:"payload"` + // Status reason + StatusReason string `json:"status_reason"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + ActionName respjson.Field + AppName respjson.Field + StartedAt respjson.Field + Status respjson.Field + FinishedAt respjson.Field + Output respjson.Field + Payload respjson.Field + StatusReason respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r InvocationUpdateResponse) RawJSON() string { return r.JSON.raw } +func (r *InvocationUpdateResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Status of the invocation +type InvocationUpdateResponseStatus string + +const ( + InvocationUpdateResponseStatusQueued InvocationUpdateResponseStatus = "queued" + InvocationUpdateResponseStatusRunning InvocationUpdateResponseStatus = "running" + InvocationUpdateResponseStatusSucceeded InvocationUpdateResponseStatus = "succeeded" + InvocationUpdateResponseStatusFailed InvocationUpdateResponseStatus = "failed" +) + +// InvocationFollowResponseUnion contains all possible properties and values from +// [shared.LogEvent], [InvocationStateEvent], [shared.ErrorEvent]. +// +// Use the [InvocationFollowResponseUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type InvocationFollowResponseUnion struct { + // Any of "log", "invocation_state", "error". + Event string `json:"event"` + // This field is from variant [shared.LogEvent]. + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + // This field is from variant [InvocationStateEvent]. + Invocation InvocationStateEventInvocation `json:"invocation"` + // This field is from variant [shared.ErrorEvent]. + Error shared.ErrorModel `json:"error"` + JSON struct { + Event respjson.Field + Message respjson.Field + Timestamp respjson.Field + Invocation respjson.Field + Error respjson.Field + raw string + } `json:"-"` +} + +// anyInvocationFollowResponse is implemented by each variant of +// [InvocationFollowResponseUnion] to add type safety for the return type of +// [InvocationFollowResponseUnion.AsAny] +type anyInvocationFollowResponse interface { + ImplInvocationFollowResponseUnion() +} + +func (InvocationStateEvent) ImplInvocationFollowResponseUnion() {} + +// Use the following switch statement to find the correct variant +// +// switch variant := InvocationFollowResponseUnion.AsAny().(type) { +// case shared.LogEvent: +// case kernel.InvocationStateEvent: +// case shared.ErrorEvent: +// default: +// fmt.Errorf("no variant present") +// } +func (u InvocationFollowResponseUnion) AsAny() anyInvocationFollowResponse { + switch u.Event { + case "log": + return u.AsLog() + case "invocation_state": + return u.AsInvocationState() + case "error": + return u.AsError() + } + return nil +} + +func (u InvocationFollowResponseUnion) AsLog() (v shared.LogEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u InvocationFollowResponseUnion) AsInvocationState() (v InvocationStateEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u InvocationFollowResponseUnion) AsError() (v shared.ErrorEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u InvocationFollowResponseUnion) RawJSON() string { return u.JSON.raw } + +func (r *InvocationFollowResponseUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type InvocationNewParams struct { + // Name of the action to invoke + ActionName string `json:"action_name,required"` + // Name of the application + AppName string `json:"app_name,required"` + // Version of the application + Version string `json:"version,required"` + // If true, invoke asynchronously. When set, the API responds 202 Accepted with + // status "queued". + Async param.Opt[bool] `json:"async,omitzero"` + // Input data for the action, sent as a JSON string. + Payload param.Opt[string] `json:"payload,omitzero"` + paramObj +} + +func (r InvocationNewParams) MarshalJSON() (data []byte, err error) { + type shadow InvocationNewParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *InvocationNewParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type InvocationUpdateParams struct { + // New status for the invocation. + // + // Any of "succeeded", "failed". + Status InvocationUpdateParamsStatus `json:"status,omitzero,required"` + // Updated output of the invocation rendered as JSON string. + Output param.Opt[string] `json:"output,omitzero"` + paramObj +} + +func (r InvocationUpdateParams) MarshalJSON() (data []byte, err error) { + type shadow InvocationUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *InvocationUpdateParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// New status for the invocation. +type InvocationUpdateParamsStatus string + +const ( + InvocationUpdateParamsStatusSucceeded InvocationUpdateParamsStatus = "succeeded" + InvocationUpdateParamsStatusFailed InvocationUpdateParamsStatus = "failed" +) diff --git a/appinvocation_test.go b/invocation_test.go similarity index 81% rename from appinvocation_test.go rename to invocation_test.go index 3b7b972..989cd3e 100644 --- a/appinvocation_test.go +++ b/invocation_test.go @@ -13,7 +13,7 @@ import ( "github.com/onkernel/kernel-go-sdk/option" ) -func TestAppInvocationNewWithOptionalParams(t *testing.T) { +func TestInvocationNewWithOptionalParams(t *testing.T) { t.Skip("skipped: tests are disabled for the time being") baseURL := "http://localhost:4010" if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { @@ -26,7 +26,7 @@ func TestAppInvocationNewWithOptionalParams(t *testing.T) { option.WithBaseURL(baseURL), option.WithAPIKey("My API Key"), ) - _, err := client.Apps.Invocations.New(context.TODO(), kernel.AppInvocationNewParams{ + _, err := client.Invocations.New(context.TODO(), kernel.InvocationNewParams{ ActionName: "analyze", AppName: "my-app", Version: "1.0.0", @@ -42,7 +42,7 @@ func TestAppInvocationNewWithOptionalParams(t *testing.T) { } } -func TestAppInvocationGet(t *testing.T) { +func TestInvocationGet(t *testing.T) { t.Skip("skipped: tests are disabled for the time being") baseURL := "http://localhost:4010" if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { @@ -55,7 +55,7 @@ func TestAppInvocationGet(t *testing.T) { option.WithBaseURL(baseURL), option.WithAPIKey("My API Key"), ) - _, err := client.Apps.Invocations.Get(context.TODO(), "rr33xuugxj9h0bkf1rdt2bet") + _, err := client.Invocations.Get(context.TODO(), "rr33xuugxj9h0bkf1rdt2bet") if err != nil { var apierr *kernel.Error if errors.As(err, &apierr) { @@ -65,7 +65,7 @@ func TestAppInvocationGet(t *testing.T) { } } -func TestAppInvocationUpdateWithOptionalParams(t *testing.T) { +func TestInvocationUpdateWithOptionalParams(t *testing.T) { t.Skip("skipped: tests are disabled for the time being") baseURL := "http://localhost:4010" if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { @@ -78,11 +78,11 @@ func TestAppInvocationUpdateWithOptionalParams(t *testing.T) { option.WithBaseURL(baseURL), option.WithAPIKey("My API Key"), ) - _, err := client.Apps.Invocations.Update( + _, err := client.Invocations.Update( context.TODO(), "id", - kernel.AppInvocationUpdateParams{ - Status: kernel.AppInvocationUpdateParamsStatusSucceeded, + kernel.InvocationUpdateParams{ + Status: kernel.InvocationUpdateParamsStatusSucceeded, Output: kernel.String("output"), }, ) diff --git a/option/middleware.go b/option/middleware.go new file mode 100644 index 0000000..8ec9dd6 --- /dev/null +++ b/option/middleware.go @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package option + +import ( + "log" + "net/http" + "net/http/httputil" +) + +// WithDebugLog logs the HTTP request and response content. +// If the logger parameter is nil, it uses the default logger. +// +// WithDebugLog is for debugging and development purposes only. +// It should not be used in production code. The behavior and interface +// of WithDebugLog is not guaranteed to be stable. +func WithDebugLog(logger *log.Logger) RequestOption { + return WithMiddleware(func(req *http.Request, nxt MiddlewareNext) (*http.Response, error) { + if logger == nil { + logger = log.Default() + } + + if reqBytes, err := httputil.DumpRequest(req, true); err == nil { + logger.Printf("Request Content:\n%s\n", reqBytes) + } + + resp, err := nxt(req) + if err != nil { + return resp, err + } + + if respBytes, err := httputil.DumpResponse(resp, true); err == nil { + logger.Printf("Response Content:\n%s\n", respBytes) + } + + return resp, err + }) +} diff --git a/shared/constant/constants.go b/shared/constant/constants.go index b109097..2b9f076 100644 --- a/shared/constant/constants.go +++ b/shared/constant/constants.go @@ -18,17 +18,32 @@ func ValueOf[T Constant[T]]() T { return t.Default() } -type Log string // Always "log" -type State string // Always "state" -type StateUpdate string // Always "state_update" - -func (c Log) Default() Log { return "log" } -func (c State) Default() State { return "state" } -func (c StateUpdate) Default() StateUpdate { return "state_update" } - -func (c Log) MarshalJSON() ([]byte, error) { return marshalString(c) } -func (c State) MarshalJSON() ([]byte, error) { return marshalString(c) } -func (c StateUpdate) MarshalJSON() ([]byte, error) { return marshalString(c) } +type AppVersionSummary string // Always "app_version_summary" +type AwsUsEast1a string // Always "aws.us-east-1a" +type DeploymentState string // Always "deployment_state" +type Error string // Always "error" +type InvocationState string // Always "invocation_state" +type Log string // Always "log" +type State string // Always "state" +type StateUpdate string // Always "state_update" + +func (c AppVersionSummary) Default() AppVersionSummary { return "app_version_summary" } +func (c AwsUsEast1a) Default() AwsUsEast1a { return "aws.us-east-1a" } +func (c DeploymentState) Default() DeploymentState { return "deployment_state" } +func (c Error) Default() Error { return "error" } +func (c InvocationState) Default() InvocationState { return "invocation_state" } +func (c Log) Default() Log { return "log" } +func (c State) Default() State { return "state" } +func (c StateUpdate) Default() StateUpdate { return "state_update" } + +func (c AppVersionSummary) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c AwsUsEast1a) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c DeploymentState) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c Error) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c InvocationState) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c Log) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c State) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c StateUpdate) MarshalJSON() ([]byte, error) { return marshalString(c) } type constant[T any] interface { Constant[T] diff --git a/shared/shared.go b/shared/shared.go new file mode 100644 index 0000000..4b63e7c --- /dev/null +++ b/shared/shared.go @@ -0,0 +1,115 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package shared + +import ( + "time" + + "github.com/onkernel/kernel-go-sdk/internal/apijson" + "github.com/onkernel/kernel-go-sdk/packages/param" + "github.com/onkernel/kernel-go-sdk/packages/respjson" + "github.com/onkernel/kernel-go-sdk/shared/constant" +) + +// aliased to make [param.APIUnion] private when embedding +type paramUnion = param.APIUnion + +// aliased to make [param.APIObject] private when embedding +type paramObj = param.APIObject + +type ErrorDetail struct { + // Lower-level error code providing more specific detail + Code string `json:"code"` + // Further detail about the error + Message string `json:"message"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Message respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ErrorDetail) RawJSON() string { return r.JSON.raw } +func (r *ErrorDetail) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An error event from the application. +type ErrorEvent struct { + Error ErrorModel `json:"error,required"` + // Event type identifier (always "error"). + Event constant.Error `json:"event,required"` + // Time the error occurred. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Error respjson.Field + Event respjson.Field + Timestamp respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ErrorEvent) RawJSON() string { return r.JSON.raw } +func (r *ErrorEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func (ErrorEvent) ImplInvocationFollowResponseUnion() {} + +type ErrorModel struct { + // Application-specific error code (machine-readable) + Code string `json:"code,required"` + // Human-readable error description for debugging + Message string `json:"message,required"` + // Additional error details (for multiple errors) + Details []ErrorDetail `json:"details"` + InnerError ErrorDetail `json:"inner_error"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Message respjson.Field + Details respjson.Field + InnerError respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ErrorModel) RawJSON() string { return r.JSON.raw } +func (r *ErrorModel) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// A log entry from the application. +type LogEvent struct { + // Event type identifier (always "log"). + Event constant.Log `json:"event,required"` + // Log message text. + Message string `json:"message,required"` + // Time the log entry was produced. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Event respjson.Field + Message respjson.Field + Timestamp respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r LogEvent) RawJSON() string { return r.JSON.raw } +func (r *LogEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func (LogEvent) ImplAppDeploymentFollowResponseUnion() {} +func (LogEvent) ImplInvocationFollowResponseUnion() {}