summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/package.json2
-rwxr-xr-xpackages/opencode/script/publish.ts18
-rw-r--r--packages/opencode/src/format/formatter.ts50
-rw-r--r--packages/opencode/src/server/server.ts26
-rw-r--r--packages/sdk/.devcontainer/devcontainer.json15
-rw-r--r--packages/sdk/.prettierignore7
-rw-r--r--packages/sdk/.prettierrc.json7
-rw-r--r--packages/sdk/.release-please-manifest.json3
-rw-r--r--packages/sdk/.stats.yml4
-rw-r--r--packages/sdk/Brewfile1
-rw-r--r--packages/sdk/CHANGELOG.md196
-rw-r--r--packages/sdk/CONTRIBUTING.md107
-rw-r--r--packages/sdk/README.md370
-rw-r--r--packages/sdk/api.md139
-rw-r--r--packages/sdk/bin/check-release-environment22
-rw-r--r--packages/sdk/bin/publish-npm61
-rw-r--r--packages/sdk/eslint.config.mjs42
-rw-r--r--packages/sdk/go/.devcontainer/devcontainer.json7
-rw-r--r--packages/sdk/go/.github/workflows/ci.yml49
-rw-r--r--packages/sdk/go/.gitignore4
-rw-r--r--packages/sdk/go/.release-please-manifest.json3
-rw-r--r--packages/sdk/go/.stats.yml4
-rw-r--r--packages/sdk/go/Brewfile1
-rw-r--r--packages/sdk/go/CHANGELOG.md73
-rw-r--r--packages/sdk/go/CONTRIBUTING.md66
-rw-r--r--packages/sdk/go/LICENSE (renamed from packages/sdk/LICENSE)0
-rw-r--r--packages/sdk/go/README.md354
-rw-r--r--packages/sdk/go/SECURITY.md (renamed from packages/sdk/SECURITY.md)0
-rw-r--r--packages/sdk/go/aliases.go43
-rw-r--r--packages/sdk/go/api.md128
-rw-r--r--packages/sdk/go/app.go368
-rw-r--r--packages/sdk/go/app_test.go131
-rw-r--r--packages/sdk/go/client.go125
-rw-r--r--packages/sdk/go/client_test.go332
-rw-r--r--packages/sdk/go/config.go887
-rw-r--r--packages/sdk/go/config_test.go36
-rw-r--r--packages/sdk/go/event.go1373
-rw-r--r--packages/sdk/go/examples/.keep (renamed from packages/sdk/examples/.keep)2
-rw-r--r--packages/sdk/go/field.go50
-rw-r--r--packages/sdk/go/file.go142
-rw-r--r--packages/sdk/go/file_test.go60
-rw-r--r--packages/sdk/go/find.go326
-rw-r--r--packages/sdk/go/find_test.go86
-rw-r--r--packages/sdk/go/go.mod13
-rw-r--r--packages/sdk/go/go.sum10
-rw-r--r--packages/sdk/go/internal/apierror/apierror.go53
-rw-r--r--packages/sdk/go/internal/apiform/encoder.go383
-rw-r--r--packages/sdk/go/internal/apiform/form.go5
-rw-r--r--packages/sdk/go/internal/apiform/form_test.go440
-rw-r--r--packages/sdk/go/internal/apiform/tag.go48
-rw-r--r--packages/sdk/go/internal/apijson/decoder.go670
-rw-r--r--packages/sdk/go/internal/apijson/encoder.go398
-rw-r--r--packages/sdk/go/internal/apijson/field.go41
-rw-r--r--packages/sdk/go/internal/apijson/field_test.go66
-rw-r--r--packages/sdk/go/internal/apijson/json_test.go617
-rw-r--r--packages/sdk/go/internal/apijson/port.go120
-rw-r--r--packages/sdk/go/internal/apijson/port_test.go257
-rw-r--r--packages/sdk/go/internal/apijson/registry.go41
-rw-r--r--packages/sdk/go/internal/apijson/tag.go47
-rw-r--r--packages/sdk/go/internal/apiquery/encoder.go341
-rw-r--r--packages/sdk/go/internal/apiquery/query.go50
-rw-r--r--packages/sdk/go/internal/apiquery/query_test.go335
-rw-r--r--packages/sdk/go/internal/apiquery/tag.go41
-rw-r--r--packages/sdk/go/internal/param/field.go29
-rw-r--r--packages/sdk/go/internal/requestconfig/requestconfig.go629
-rw-r--r--packages/sdk/go/internal/testutil/testutil.go27
-rw-r--r--packages/sdk/go/internal/version.go5
-rw-r--r--packages/sdk/go/lib/.keep (renamed from packages/sdk/src/lib/.keep)2
-rw-r--r--packages/sdk/go/option/middleware.go38
-rw-r--r--packages/sdk/go/option/requestoption.go267
-rw-r--r--packages/sdk/go/packages/ssestream/ssestream.go181
-rw-r--r--packages/sdk/go/release-please-config.json (renamed from packages/sdk/release-please-config.json)9
-rwxr-xr-xpackages/sdk/go/scripts/bootstrap (renamed from packages/sdk/scripts/bootstrap)6
-rwxr-xr-xpackages/sdk/go/scripts/format8
-rwxr-xr-xpackages/sdk/go/scripts/lint11
-rwxr-xr-xpackages/sdk/go/scripts/mock (renamed from packages/sdk/scripts/mock)0
-rwxr-xr-xpackages/sdk/go/scripts/test (renamed from packages/sdk/scripts/test)2
-rw-r--r--packages/sdk/go/session.go2117
-rw-r--r--packages/sdk/go/session_test.go323
-rw-r--r--packages/sdk/go/shared/shared.go173
-rw-r--r--packages/sdk/go/tui.go56
-rw-r--r--packages/sdk/go/tui_test.go60
-rw-r--r--packages/sdk/go/usage_test.go32
-rw-r--r--packages/sdk/jest.config.ts23
-rw-r--r--packages/sdk/js/package.json17
-rwxr-xr-xpackages/sdk/js/script/generate.ts41
-rw-r--r--packages/sdk/js/script/publish.ts24
-rw-r--r--packages/sdk/js/src/gen/client.gen.ts18
-rw-r--r--packages/sdk/js/src/gen/client/client.ts195
-rw-r--r--packages/sdk/js/src/gen/client/index.ts22
-rw-r--r--packages/sdk/js/src/gen/client/types.ts222
-rw-r--r--packages/sdk/js/src/gen/client/utils.ts417
-rw-r--r--packages/sdk/js/src/gen/core/auth.ts40
-rw-r--r--packages/sdk/js/src/gen/core/bodySerializer.ts88
-rw-r--r--packages/sdk/js/src/gen/core/params.ts151
-rw-r--r--packages/sdk/js/src/gen/core/pathSerializer.ts179
-rw-r--r--packages/sdk/js/src/gen/core/types.ts118
-rw-r--r--packages/sdk/js/src/gen/sdk.gen.ts339
-rw-r--r--packages/sdk/js/src/gen/types.gen.ts1450
-rw-r--r--packages/sdk/js/src/index.ts8
-rw-r--r--packages/sdk/js/tsconfig.json13
-rw-r--r--packages/sdk/package.json69
-rwxr-xr-xpackages/sdk/scripts/build51
-rwxr-xr-xpackages/sdk/scripts/format12
-rwxr-xr-xpackages/sdk/scripts/lint21
-rw-r--r--packages/sdk/scripts/utils/attw-report.cjs24
-rwxr-xr-xpackages/sdk/scripts/utils/check-is-in-git-install.sh9
-rw-r--r--packages/sdk/scripts/utils/check-version.cjs20
-rw-r--r--packages/sdk/scripts/utils/fix-index-exports.cjs17
-rwxr-xr-xpackages/sdk/scripts/utils/git-swap.sh13
-rw-r--r--packages/sdk/scripts/utils/make-dist-package-json.cjs21
-rw-r--r--packages/sdk/scripts/utils/postprocess-files.cjs94
-rwxr-xr-xpackages/sdk/scripts/utils/upload-artifact.sh25
-rw-r--r--packages/sdk/src/api-promise.ts2
-rw-r--r--packages/sdk/src/client.ts862
-rw-r--r--packages/sdk/src/core/README.md3
-rw-r--r--packages/sdk/src/core/api-promise.ts92
-rw-r--r--packages/sdk/src/core/error.ts130
-rw-r--r--packages/sdk/src/core/resource.ts11
-rw-r--r--packages/sdk/src/core/streaming.ts315
-rw-r--r--packages/sdk/src/core/uploads.ts2
-rw-r--r--packages/sdk/src/error.ts2
-rw-r--r--packages/sdk/src/index.ts22
-rw-r--r--packages/sdk/src/internal/README.md3
-rw-r--r--packages/sdk/src/internal/builtin-types.ts93
-rw-r--r--packages/sdk/src/internal/decoders/line.ts135
-rw-r--r--packages/sdk/src/internal/detect-platform.ts196
-rw-r--r--packages/sdk/src/internal/errors.ts33
-rw-r--r--packages/sdk/src/internal/headers.ts97
-rw-r--r--packages/sdk/src/internal/parse.ts64
-rw-r--r--packages/sdk/src/internal/request-options.ts93
-rw-r--r--packages/sdk/src/internal/shim-types.ts26
-rw-r--r--packages/sdk/src/internal/shims.ts107
-rw-r--r--packages/sdk/src/internal/to-file.ts154
-rw-r--r--packages/sdk/src/internal/types.ts95
-rw-r--r--packages/sdk/src/internal/uploads.ts187
-rw-r--r--packages/sdk/src/internal/utils.ts8
-rw-r--r--packages/sdk/src/internal/utils/base64.ts40
-rw-r--r--packages/sdk/src/internal/utils/bytes.ts32
-rw-r--r--packages/sdk/src/internal/utils/env.ts18
-rw-r--r--packages/sdk/src/internal/utils/log.ts126
-rw-r--r--packages/sdk/src/internal/utils/path.ts88
-rw-r--r--packages/sdk/src/internal/utils/sleep.ts3
-rw-r--r--packages/sdk/src/internal/utils/uuid.ts17
-rw-r--r--packages/sdk/src/internal/utils/values.ts105
-rw-r--r--packages/sdk/src/resource.ts2
-rw-r--r--packages/sdk/src/resources.ts1
-rw-r--r--packages/sdk/src/resources/app.ts192
-rw-r--r--packages/sdk/src/resources/config.ts492
-rw-r--r--packages/sdk/src/resources/event.ts267
-rw-r--r--packages/sdk/src/resources/file.ts52
-rw-r--r--packages/sdk/src/resources/find.ts134
-rw-r--r--packages/sdk/src/resources/index.ts81
-rw-r--r--packages/sdk/src/resources/session.ts605
-rw-r--r--packages/sdk/src/resources/shared.ts33
-rw-r--r--packages/sdk/src/resources/tui.ts37
-rw-r--r--packages/sdk/src/streaming.ts2
-rw-r--r--packages/sdk/src/uploads.ts2
-rw-r--r--packages/sdk/src/version.ts1
-rw-r--r--packages/sdk/sst-env.d.ts9
-rwxr-xr-xpackages/sdk/stainless/generate.ts15
-rw-r--r--packages/sdk/stainless/stainless-workspace.json5
-rw-r--r--packages/sdk/stainless/stainless.yml151
-rw-r--r--packages/sdk/tests/api-resources/app.test.ts77
-rw-r--r--packages/sdk/tests/api-resources/config.test.ts19
-rw-r--r--packages/sdk/tests/api-resources/event.test.ts19
-rw-r--r--packages/sdk/tests/api-resources/file.test.ts36
-rw-r--r--packages/sdk/tests/api-resources/find.test.ts58
-rw-r--r--packages/sdk/tests/api-resources/session.test.ts191
-rw-r--r--packages/sdk/tests/api-resources/tui.test.ts36
-rw-r--r--packages/sdk/tests/base64.test.ts80
-rw-r--r--packages/sdk/tests/buildHeaders.test.ts88
-rw-r--r--packages/sdk/tests/form.test.ts85
-rw-r--r--packages/sdk/tests/index.test.ts690
-rw-r--r--packages/sdk/tests/internal/decoders/line.test.ts128
-rw-r--r--packages/sdk/tests/path.test.ts462
-rw-r--r--packages/sdk/tests/streaming.test.ts219
-rw-r--r--packages/sdk/tests/stringifyQuery.test.ts29
-rw-r--r--packages/sdk/tests/uploads.test.ts104
-rw-r--r--packages/sdk/tsc-multi.json15
-rw-r--r--packages/sdk/tsconfig.build.json18
-rw-r--r--packages/sdk/tsconfig.deno.json15
-rw-r--r--packages/sdk/tsconfig.dist-src.json11
-rw-r--r--packages/sdk/tsconfig.json38
-rw-r--r--packages/sdk/yarn.lock3500
185 files changed, 16182 insertions, 12390 deletions
diff --git a/packages/opencode/package.json b/packages/opencode/package.json
index 0ed936774..cc31e83b7 100644
--- a/packages/opencode/package.json
+++ b/packages/opencode/package.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
- "version": "0.0.5",
+ "version": "0.0.0",
"name": "opencode",
"type": "module",
"private": true,
diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts
index 12295be65..f7133da4c 100755
--- a/packages/opencode/script/publish.ts
+++ b/packages/opencode/script/publish.ts
@@ -1,21 +1,13 @@
#!/usr/bin/env bun
-
+const dir = new URL("..", import.meta.url).pathname
+process.chdir(dir)
import { $ } from "bun"
import pkg from "../package.json"
-const dry = process.argv.includes("--dry")
-const snapshot = process.argv.includes("--snapshot")
-
-const version = snapshot
- ? `0.0.0-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}`
- : await $`git describe --tags --abbrev=0`
- .text()
- .then((x) => x.substring(1).trim())
- .catch(() => {
- console.error("tag not found")
- process.exit(1)
- })
+const dry = process.env["OPENCODE_DRY"] === "true"
+const version = process.env["OPENCODE_VERSION"]!
+const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true"
console.log(`publishing ${version}`)
diff --git a/packages/opencode/src/format/formatter.ts b/packages/opencode/src/format/formatter.ts
index 83e359f6f..8cb77df2b 100644
--- a/packages/opencode/src/format/formatter.ts
+++ b/packages/opencode/src/format/formatter.ts
@@ -1,7 +1,6 @@
import { App } from "../app/app"
import { BunProc } from "../bun"
import { Filesystem } from "../util/filesystem"
-import path from "path"
export interface Info {
name: string
@@ -65,14 +64,57 @@ export const prettier: Info = {
],
async enabled() {
const app = App.info()
- const nms = await Filesystem.findUp("node_modules", app.path.cwd, app.path.root)
- for (const item of nms) {
- if (await Bun.file(path.join(item, ".bin", "prettier")).exists()) return true
+ const items = await Filesystem.findUp("package.json", app.path.cwd, app.path.root)
+ for (const item of items) {
+ const json = await Bun.file(item).json()
+ if (json.dependencies?.prettier) return true
+ if (json.devDependencies?.prettier) return true
}
return false
},
}
+export const biome: Info = {
+ name: "biome",
+ command: [BunProc.which(), "x", "biome", "format", "--write", "$FILE"],
+ environment: {
+ BUN_BE_BUN: "1",
+ },
+ extensions: [
+ ".js",
+ ".jsx",
+ ".mjs",
+ ".cjs",
+ ".ts",
+ ".tsx",
+ ".mts",
+ ".cts",
+ ".html",
+ ".htm",
+ ".css",
+ ".scss",
+ ".sass",
+ ".less",
+ ".vue",
+ ".svelte",
+ ".json",
+ ".jsonc",
+ ".yaml",
+ ".yml",
+ ".toml",
+ ".xml",
+ ".md",
+ ".mdx",
+ ".graphql",
+ ".gql",
+ ],
+ async enabled() {
+ const app = App.info()
+ const items = await Filesystem.findUp("biome.json", app.path.cwd, app.path.root)
+ return items.length > 0
+ },
+}
+
export const zig: Info = {
name: "zig",
command: ["zig", "fmt", "$FILE"],
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index 1c4f19b67..c3e42c4f6 100644
--- a/packages/opencode/src/server/server.ts
+++ b/packages/opencode/src/server/server.ts
@@ -94,6 +94,7 @@ export namespace Server {
"/event",
describeRoute({
description: "Get events",
+ operationId: "event.subscribe",
responses: {
200: {
description: "Event stream",
@@ -137,6 +138,7 @@ export namespace Server {
"/app",
describeRoute({
description: "Get app info",
+ operationId: "app.get",
responses: {
200: {
description: "200",
@@ -156,6 +158,7 @@ export namespace Server {
"/app/init",
describeRoute({
description: "Initialize the app",
+ operationId: "app.init",
responses: {
200: {
description: "Initialize the app",
@@ -176,6 +179,7 @@ export namespace Server {
"/config",
describeRoute({
description: "Get config info",
+ operationId: "config.get",
responses: {
200: {
description: "Get config info",
@@ -195,6 +199,7 @@ export namespace Server {
"/session",
describeRoute({
description: "List all sessions",
+ operationId: "session.list",
responses: {
200: {
description: "List of sessions",
@@ -216,6 +221,7 @@ export namespace Server {
"/session",
describeRoute({
description: "Create a new session",
+ operationId: "session.create",
responses: {
...ERRORS,
200: {
@@ -237,6 +243,7 @@ export namespace Server {
"/session/:id",
describeRoute({
description: "Delete a session and all its data",
+ operationId: "session.delete",
responses: {
200: {
description: "Successfully deleted session",
@@ -263,6 +270,7 @@ export namespace Server {
"/session/:id/init",
describeRoute({
description: "Analyze the app and create an AGENTS.md file",
+ operationId: "session.init",
responses: {
200: {
description: "200",
@@ -299,6 +307,7 @@ export namespace Server {
"/session/:id/abort",
describeRoute({
description: "Abort a session",
+ operationId: "session.abort",
responses: {
200: {
description: "Aborted session",
@@ -324,6 +333,7 @@ export namespace Server {
"/session/:id/share",
describeRoute({
description: "Share a session",
+ operationId: "session.share",
responses: {
200: {
description: "Successfully shared session",
@@ -352,6 +362,7 @@ export namespace Server {
"/session/:id/share",
describeRoute({
description: "Unshare the session",
+ operationId: "session.unshare",
responses: {
200: {
description: "Successfully unshared session",
@@ -380,6 +391,7 @@ export namespace Server {
"/session/:id/summarize",
describeRoute({
description: "Summarize the session",
+ operationId: "session.summarize",
responses: {
200: {
description: "Summarized session",
@@ -415,6 +427,7 @@ export namespace Server {
"/session/:id/message",
describeRoute({
description: "List messages for a session",
+ operationId: "session.messages",
responses: {
200: {
description: "List of messages",
@@ -448,6 +461,7 @@ export namespace Server {
"/session/:id/message",
describeRoute({
description: "Create and send a new message to a session",
+ operationId: "session.chat",
responses: {
200: {
description: "Created message",
@@ -477,6 +491,7 @@ export namespace Server {
"/session/:id/revert",
describeRoute({
description: "Revert a message",
+ operationId: "session.revert",
responses: {
200: {
description: "Updated session",
@@ -506,6 +521,7 @@ export namespace Server {
"/session/:id/unrevert",
describeRoute({
description: "Restore all reverted messages",
+ operationId: "session.unrevert",
responses: {
200: {
description: "Updated session",
@@ -533,6 +549,7 @@ export namespace Server {
"/config/providers",
describeRoute({
description: "List all providers",
+ operationId: "config.providers",
responses: {
200: {
description: "List of providers",
@@ -561,6 +578,7 @@ export namespace Server {
"/find",
describeRoute({
description: "Find text in files",
+ operationId: "find.text",
responses: {
200: {
description: "Matches",
@@ -593,6 +611,7 @@ export namespace Server {
"/find/file",
describeRoute({
description: "Find files",
+ operationId: "find.files",
responses: {
200: {
description: "File paths",
@@ -625,6 +644,7 @@ export namespace Server {
"/find/symbol",
describeRoute({
description: "Find workspace symbols",
+ operationId: "find.symbols",
responses: {
200: {
description: "Symbols",
@@ -652,6 +672,7 @@ export namespace Server {
"/file",
describeRoute({
description: "Read a file",
+ operationId: "file.read",
responses: {
200: {
description: "File content",
@@ -688,6 +709,7 @@ export namespace Server {
"/file/status",
describeRoute({
description: "Get file status",
+ operationId: "file.status",
responses: {
200: {
description: "File status",
@@ -708,6 +730,7 @@ export namespace Server {
"/log",
describeRoute({
description: "Write a log entry to the server logs",
+ operationId: "app.log",
responses: {
200: {
description: "Log entry written successfully",
@@ -757,6 +780,7 @@ export namespace Server {
"/mode",
describeRoute({
description: "List all modes",
+ operationId: "app.modes",
responses: {
200: {
description: "List of modes",
@@ -777,6 +801,7 @@ export namespace Server {
"/tui/append-prompt",
describeRoute({
description: "Append prompt to the TUI",
+ operationId: "tui.appendPrompt",
responses: {
200: {
description: "Prompt processed successfully",
@@ -800,6 +825,7 @@ export namespace Server {
"/tui/open-help",
describeRoute({
description: "Open the help dialog",
+ operationId: "tui.openHelp",
responses: {
200: {
description: "Help dialog opened successfully",
diff --git a/packages/sdk/.devcontainer/devcontainer.json b/packages/sdk/.devcontainer/devcontainer.json
deleted file mode 100644
index 43fd5a73f..000000000
--- a/packages/sdk/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,15 +0,0 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the
-// README at: https://github.com/devcontainers/templates/tree/main/src/debian
-{
- "name": "Development",
- "image": "mcr.microsoft.com/devcontainers/typescript-node:latest",
- "features": {
- "ghcr.io/devcontainers/features/node:1": {}
- },
- "postCreateCommand": "yarn install",
- "customizations": {
- "vscode": {
- "extensions": ["esbenp.prettier-vscode"]
- }
- }
-}
diff --git a/packages/sdk/.prettierignore b/packages/sdk/.prettierignore
deleted file mode 100644
index 3548c5af9..000000000
--- a/packages/sdk/.prettierignore
+++ /dev/null
@@ -1,7 +0,0 @@
-CHANGELOG.md
-/ecosystem-tests/*/**
-/node_modules
-/deno
-
-# don't format tsc output, will break source maps
-/dist
diff --git a/packages/sdk/.prettierrc.json b/packages/sdk/.prettierrc.json
deleted file mode 100644
index af75adaf6..000000000
--- a/packages/sdk/.prettierrc.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "arrowParens": "always",
- "experimentalTernaries": true,
- "printWidth": 110,
- "singleQuote": true,
- "trailingComma": "all"
-}
diff --git a/packages/sdk/.release-please-manifest.json b/packages/sdk/.release-please-manifest.json
deleted file mode 100644
index de4ea38f0..000000000
--- a/packages/sdk/.release-please-manifest.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- ".": "0.1.0-alpha.20"
-}
diff --git a/packages/sdk/.stats.yml b/packages/sdk/.stats.yml
deleted file mode 100644
index 3f719fabf..000000000
--- a/packages/sdk/.stats.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-configured_endpoints: 26
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-62d8fccba4eb8dc3a80434e0849eab3352e49fb96a718bb7b6d17ed8e582b716.yml
-openapi_spec_hash: 4ff9376cf9634e91731e63fe482ea532
-config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/packages/sdk/Brewfile b/packages/sdk/Brewfile
deleted file mode 100644
index e4feee601..000000000
--- a/packages/sdk/Brewfile
+++ /dev/null
@@ -1 +0,0 @@
-brew "node"
diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md
deleted file mode 100644
index c51e0a038..000000000
--- a/packages/sdk/CHANGELOG.md
+++ /dev/null
@@ -1,196 +0,0 @@
-# Changelog
-
-## 0.1.0-alpha.20 (2025-07-16)
-
-Full Changelog: [v0.1.0-alpha.19...v0.1.0-alpha.20](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.19...v0.1.0-alpha.20)
-
-### Features
-
-* **api:** api update ([d296473](https://github.com/sst/opencode-sdk-js/commit/d296473db58378932b85d1afaa60942ac5599c49))
-* **api:** api update ([af2b587](https://github.com/sst/opencode-sdk-js/commit/af2b5875534a4782fac186542ecb9b04393c9b0a))
-
-## 0.1.0-alpha.19 (2025-07-16)
-
-Full Changelog: [v0.1.0-alpha.18...v0.1.0-alpha.19](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.18...v0.1.0-alpha.19)
-
-### Features
-
-* **api:** api update ([2e505ef](https://github.com/sst/opencode-sdk-js/commit/2e505ef451fdcf49358189c5f76bdc42fb821352))
-
-## 0.1.0-alpha.18 (2025-07-15)
-
-Full Changelog: [v0.1.0-alpha.17...v0.1.0-alpha.18](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.17...v0.1.0-alpha.18)
-
-### Features
-
-* **api:** api update ([25a23e5](https://github.com/sst/opencode-sdk-js/commit/25a23e599f1180754910961df65f0cc044aa2935))
-
-## 0.1.0-alpha.17 (2025-07-15)
-
-Full Changelog: [v0.1.0-alpha.16...v0.1.0-alpha.17](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.16...v0.1.0-alpha.17)
-
-### Features
-
-* **api:** api update ([8b5d592](https://github.com/sst/opencode-sdk-js/commit/8b5d59243a0212f98269412f4483e729e2367a77))
-* **api:** api update ([ebd8986](https://github.com/sst/opencode-sdk-js/commit/ebd89862c48be2742eda727c83c01430413e00c0))
-
-## 0.1.0-alpha.16 (2025-07-15)
-
-Full Changelog: [v0.1.0-alpha.15...v0.1.0-alpha.16](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.15...v0.1.0-alpha.16)
-
-### Features
-
-* **api:** api update ([f26379d](https://github.com/sst/opencode-sdk-js/commit/f26379d83ae7094d6ba91c6705a97a3fbd88a55a))
-
-
-### Chores
-
-* make some internal functions async ([36b1db9](https://github.com/sst/opencode-sdk-js/commit/36b1db9ca9d47d9199e2eab5f0b454b7cd31f58f))
-
-## 0.1.0-alpha.15 (2025-07-05)
-
-Full Changelog: [v0.1.0-alpha.14...v0.1.0-alpha.15](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.14...v0.1.0-alpha.15)
-
-### Features
-
-* **api:** manual updates ([f6ee467](https://github.com/sst/opencode-sdk-js/commit/f6ee46752d0c174c8b934894cf2b140864864208))
-
-
-### Chores
-
-* **internal:** codegen related update ([47a1a97](https://github.com/sst/opencode-sdk-js/commit/47a1a972e755735d6b5472c61f726ab2face9e62))
-
-## 0.1.0-alpha.14 (2025-07-03)
-
-Full Changelog: [v0.1.0-alpha.13...v0.1.0-alpha.14](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.13...v0.1.0-alpha.14)
-
-### Features
-
-* **api:** api update ([a1d7cf9](https://github.com/sst/opencode-sdk-js/commit/a1d7cf948a2ff47ce4e98b4a52d0e4d213b87bf6))
-
-
-### Chores
-
-* **internal:** version bump ([f8ad145](https://github.com/sst/opencode-sdk-js/commit/f8ad145b9af0c4a465642630043e59236d5f4e8d))
-
-## 0.1.0-alpha.13 (2025-07-03)
-
-Full Changelog: [v0.1.0-alpha.12...v0.1.0-alpha.13](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.12...v0.1.0-alpha.13)
-
-### Bug Fixes
-
-* avoid console usage ([f96ac97](https://github.com/sst/opencode-sdk-js/commit/f96ac97fbaf7417efda306d8727654d1a4138386))
-
-
-### Chores
-
-* add docs to RequestOptions type ([1ca6677](https://github.com/sst/opencode-sdk-js/commit/1ca667765c22b706732c61ea3d9d2823aeda0a8e))
-
-## 0.1.0-alpha.12 (2025-07-02)
-
-Full Changelog: [v0.1.0-alpha.11...v0.1.0-alpha.12](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.11...v0.1.0-alpha.12)
-
-### Features
-
-* **api:** update via SDK Studio ([7739340](https://github.com/sst/opencode-sdk-js/commit/77393403648067fe937637c39e80067c347a8c5b))
-
-## 0.1.0-alpha.11 (2025-06-30)
-
-Full Changelog: [v0.1.0-alpha.10...v0.1.0-alpha.11](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.10...v0.1.0-alpha.11)
-
-### Features
-
-* **api:** update via SDK Studio ([2ce98e5](https://github.com/sst/opencode-sdk-js/commit/2ce98e55bf330cca0c38f60f011ffd9063b34ea0))
-
-## 0.1.0-alpha.10 (2025-06-30)
-
-Full Changelog: [v0.1.0-alpha.9...v0.1.0-alpha.10](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.9...v0.1.0-alpha.10)
-
-### Features
-
-* **api:** update via SDK Studio ([fa7c91c](https://github.com/sst/opencode-sdk-js/commit/fa7c91cc2fe52d42be7365ca2c4ce3e48c2e76ac))
-
-
-### Chores
-
-* **ci:** only run for pushes and fork pull requests ([0e850e5](https://github.com/sst/opencode-sdk-js/commit/0e850e51daac413dcf2d5e30c0ea7a1cd5346c4b))
-* **client:** improve path param validation ([bc3ff0e](https://github.com/sst/opencode-sdk-js/commit/bc3ff0ee2de9af8be42deae87d12f003fb5f7aa5))
-
-## 0.1.0-alpha.9 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.8...v0.1.0-alpha.9](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.8...v0.1.0-alpha.9)
-
-### Features
-
-* **api:** update via SDK Studio ([7009d10](https://github.com/sst/opencode-sdk-js/commit/7009d10aab99be7102371cee49013ab3edae4450))
-* **api:** update via SDK Studio ([e60aa00](https://github.com/sst/opencode-sdk-js/commit/e60aa0024079671e3725ee6f6bfbf8c2dad78da2))
-
-## 0.1.0-alpha.8 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.7...v0.1.0-alpha.8](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.7...v0.1.0-alpha.8)
-
-### Features
-
-* **api:** update via SDK Studio ([171e3d5](https://github.com/sst/opencode-sdk-js/commit/171e3d5f3ba69ff9ba8547dac90d85b1a0a137c1))
-
-## 0.1.0-alpha.7 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.6...v0.1.0-alpha.7](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.6...v0.1.0-alpha.7)
-
-### Features
-
-* **api:** update via SDK Studio ([14d2d04](https://github.com/sst/opencode-sdk-js/commit/14d2d04d80c1d5880940c9c70a5c1ea200df2ebc))
-
-## 0.1.0-alpha.6 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.5...v0.1.0-alpha.6](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.5...v0.1.0-alpha.6)
-
-### Features
-
-* **api:** update via SDK Studio ([45e78b2](https://github.com/sst/opencode-sdk-js/commit/45e78b2f0fca18f537de9986e358aa876fb0b686))
-
-## 0.1.0-alpha.5 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.4...v0.1.0-alpha.5)
-
-### Features
-
-* **api:** update via SDK Studio ([10a5be9](https://github.com/sst/opencode-sdk-js/commit/10a5be9261c4ba8aeece7bb6921752f5fa6d9f28))
-
-## 0.1.0-alpha.4 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
-
-### Features
-
-* **api:** update via SDK Studio ([20dcd17](https://github.com/sst/opencode-sdk-js/commit/20dcd171405b05801e5a56f1b40fd635259b6a94))
-
-## 0.1.0-alpha.3 (2025-06-27)
-
-Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)
-
-### Bug Fixes
-
-* **ci:** release-doctor — report correct token name ([128884f](https://github.com/sst/opencode-sdk-js/commit/128884f4bc64e618177a0b090cd6d52b122a059a))
-
-## 0.1.0-alpha.2 (2025-06-24)
-
-Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/sst/opencode-sdk-js/compare/v0.1.0-alpha.1...v0.1.0-alpha.2)
-
-### Features
-
-* **api:** update via SDK Studio ([2320f32](https://github.com/sst/opencode-sdk-js/commit/2320f32190ab58d15d00d7c3328f9fba2421536c))
-
-## 0.1.0-alpha.1 (2025-06-24)
-
-Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/sst/opencode-sdk-js/compare/v0.0.1-alpha.0...v0.1.0-alpha.1)
-
-### Features
-
-* **api:** update via SDK Studio ([e448306](https://github.com/sst/opencode-sdk-js/commit/e4483068738cbb10233fca5a9d9d44a9c9815c8b))
-* **api:** update via SDK Studio ([b222c96](https://github.com/sst/opencode-sdk-js/commit/b222c96a679a8aeecb60bcf92c247fef90c75b3d))
-
-
-### Chores
-
-* update SDK settings ([c1481ea](https://github.com/sst/opencode-sdk-js/commit/c1481ea7949c1422bedaeac278600b4ec3f58038))
diff --git a/packages/sdk/CONTRIBUTING.md b/packages/sdk/CONTRIBUTING.md
deleted file mode 100644
index e582e41a7..000000000
--- a/packages/sdk/CONTRIBUTING.md
+++ /dev/null
@@ -1,107 +0,0 @@
-## Setting up the environment
-
-This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install).
-Other package managers may work but are not officially supported for development.
-
-To set up the repository, run:
-
-```sh
-$ yarn
-$ yarn build
-```
-
-This will install all the required dependencies and build output files to `dist/`.
-
-## Modifying/Adding code
-
-Most of the SDK is generated code. Modifications to code will be persisted between generations, but may
-result in merge conflicts between manual patches and changes from the generator. The generator will never
-modify the contents of the `src/lib/` and `examples/` directories.
-
-## Adding and running examples
-
-All files in the `examples/` directory are not modified by the generator and can be freely edited or added to.
-
-```ts
-// add an example to examples/<your-example>.ts
-
-#!/usr/bin/env -S npm run tsn -T
-…
-```
-
-```sh
-$ chmod +x examples/<your-example>.ts
-# run the example against your api
-$ yarn tsn -T examples/<your-example>.ts
-```
-
-## Using the repository from source
-
-If you’d like to use the repository from source, you can either install from git or link to a cloned repository:
-
-To install via git:
-
-```sh
-$ npm install git+ssh://[email protected]:sst/opencode-sdk-js.git
-```
-
-Alternatively, to link a local copy of the repo:
-
-```sh
-# Clone
-$ git clone https://www.github.com/sst/opencode-sdk-js
-$ cd opencode-sdk-js
-
-# With yarn
-$ yarn link
-$ cd ../my-package
-$ yarn link @opencode-ai/sdk
-
-# With pnpm
-$ pnpm link --global
-$ cd ../my-package
-$ pnpm link -—global @opencode-ai/sdk
-```
-
-## Running tests
-
-Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
-
-```sh
-$ npx prism mock path/to/your/openapi.yml
-```
-
-```sh
-$ yarn run test
-```
-
-## Linting and formatting
-
-This repository uses [prettier](https://www.npmjs.com/package/prettier) and
-[eslint](https://www.npmjs.com/package/eslint) to format the code in the repository.
-
-To lint:
-
-```sh
-$ yarn lint
-```
-
-To format and fix all lint issues automatically:
-
-```sh
-$ yarn fix
-```
-
-## Publishing and releases
-
-Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If
-the changes aren't made through the automated pipeline, you may want to make releases manually.
-
-### Publish with a GitHub workflow
-
-You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/sst/opencode-sdk-js/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up.
-
-### Publish manually
-
-If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on
-the environment.
diff --git a/packages/sdk/README.md b/packages/sdk/README.md
deleted file mode 100644
index a06009b37..000000000
--- a/packages/sdk/README.md
+++ /dev/null
@@ -1,370 +0,0 @@
-# Opencode TypeScript API Library
-
-[![NPM version](<https://img.shields.io/npm/v/@opencode-ai/sdk.svg?label=npm%20(stable)>)](https://npmjs.org/package/@opencode-ai/sdk) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@opencode-ai/sdk)
-
-This library provides convenient access to the Opencode REST API from server-side TypeScript or JavaScript.
-
-The REST API documentation can be found on [opencode.ai](https://opencode.ai/docs). The full API of this library can be found in [api.md](api.md).
-
-It is generated with [Stainless](https://www.stainless.com/).
-
-## Installation
-
-```sh
-npm install @opencode-ai/sdk
-```
-
-## Usage
-
-The full API of this library can be found in [api.md](api.md).
-
-<!-- prettier-ignore -->
-```js
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode();
-
-const sessions = await client.session.list();
-```
-
-## Streaming responses
-
-We provide support for streaming responses using Server Sent Events (SSE).
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode();
-
-const stream = await client.event.list();
-for await (const eventListResponse of stream) {
- console.log(eventListResponse);
-}
-```
-
-If you need to cancel a stream, you can `break` from the loop
-or call `stream.controller.abort()`.
-
-### Request & Response types
-
-This library includes TypeScript definitions for all request params and response fields. You may import and use them like so:
-
-<!-- prettier-ignore -->
-```ts
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode();
-
-const sessions: Opencode.SessionListResponse = await client.session.list();
-```
-
-Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.
-
-## Handling errors
-
-When the library is unable to connect to the API,
-or if the API returns a non-success status code (i.e., 4xx or 5xx response),
-a subclass of `APIError` will be thrown:
-
-<!-- prettier-ignore -->
-```ts
-const sessions = await client.session.list().catch(async (err) => {
- if (err instanceof Opencode.APIError) {
- console.log(err.status); // 400
- console.log(err.name); // BadRequestError
- console.log(err.headers); // {server: 'nginx', ...}
- } else {
- throw err;
- }
-});
-```
-
-Error codes are as follows:
-
-| Status Code | Error Type |
-| ----------- | -------------------------- |
-| 400 | `BadRequestError` |
-| 401 | `AuthenticationError` |
-| 403 | `PermissionDeniedError` |
-| 404 | `NotFoundError` |
-| 422 | `UnprocessableEntityError` |
-| 429 | `RateLimitError` |
-| >=500 | `InternalServerError` |
-| N/A | `APIConnectionError` |
-
-### Retries
-
-Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
-Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,
-429 Rate Limit, and >=500 Internal errors will all be retried by default.
-
-You can use the `maxRetries` option to configure or disable this:
-
-<!-- prettier-ignore -->
-```js
-// Configure the default for all requests:
-const client = new Opencode({
- maxRetries: 0, // default is 2
-});
-
-// Or, configure per-request:
-await client.session.list({
- maxRetries: 5,
-});
-```
-
-### Timeouts
-
-Requests time out after 1 minute by default. You can configure this with a `timeout` option:
-
-<!-- prettier-ignore -->
-```ts
-// Configure the default for all requests:
-const client = new Opencode({
- timeout: 20 * 1000, // 20 seconds (default is 1 minute)
-});
-
-// Override per-request:
-await client.session.list({
- timeout: 5 * 1000,
-});
-```
-
-On timeout, an `APIConnectionTimeoutError` is thrown.
-
-Note that requests which time out will be [retried twice by default](#retries).
-
-## Advanced Usage
-
-### Accessing raw Response data (e.g., headers)
-
-The "raw" `Response` returned by `fetch()` can be accessed through the `.asResponse()` method on the `APIPromise` type that all methods return.
-This method returns as soon as the headers for a successful response are received and does not consume the response body, so you are free to write custom parsing or streaming logic.
-
-You can also use the `.withResponse()` method to get the raw `Response` along with the parsed data.
-Unlike `.asResponse()` this method consumes the body, returning once it is parsed.
-
-<!-- prettier-ignore -->
-```ts
-const client = new Opencode();
-
-const response = await client.session.list().asResponse();
-console.log(response.headers.get('X-My-Header'));
-console.log(response.statusText); // access the underlying Response object
-
-const { data: sessions, response: raw } = await client.session.list().withResponse();
-console.log(raw.headers.get('X-My-Header'));
-console.log(sessions);
-```
-
-### Logging
-
-> [!IMPORTANT]
-> All log messages are intended for debugging only. The format and content of log messages
-> may change between releases.
-
-#### Log levels
-
-The log level can be configured in two ways:
-
-1. Via the `OPENCODE_LOG` environment variable
-2. Using the `logLevel` client option (overrides the environment variable if set)
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({
- logLevel: 'debug', // Show all log messages
-});
-```
-
-Available log levels, from most to least verbose:
-
-- `'debug'` - Show debug messages, info, warnings, and errors
-- `'info'` - Show info messages, warnings, and errors
-- `'warn'` - Show warnings and errors (default)
-- `'error'` - Show only errors
-- `'off'` - Disable all logging
-
-At the `'debug'` level, all HTTP requests and responses are logged, including headers and bodies.
-Some authentication-related headers are redacted, but sensitive data in request and response bodies
-may still be visible.
-
-#### Custom logger
-
-By default, this library logs to `globalThis.console`. You can also provide a custom logger.
-Most logging libraries are supported, including [pino](https://www.npmjs.com/package/pino), [winston](https://www.npmjs.com/package/winston), [bunyan](https://www.npmjs.com/package/bunyan), [consola](https://www.npmjs.com/package/consola), [signale](https://www.npmjs.com/package/signale), and [@std/log](https://jsr.io/@std/log). If your logger doesn't work, please open an issue.
-
-When providing a custom logger, the `logLevel` option still controls which messages are emitted, messages
-below the configured level will not be sent to your logger.
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-import pino from 'pino';
-
-const logger = pino();
-
-const client = new Opencode({
- logger: logger.child({ name: 'Opencode' }),
- logLevel: 'debug', // Send all messages to pino, allowing it to filter
-});
-```
-
-### Making custom/undocumented requests
-
-This library is typed for convenient access to the documented API. If you need to access undocumented
-endpoints, params, or response properties, the library can still be used.
-
-#### Undocumented endpoints
-
-To make requests to undocumented endpoints, you can use `client.get`, `client.post`, and other HTTP verbs.
-Options on the client, such as retries, will be respected when making these requests.
-
-```ts
-await client.post('/some/path', {
- body: { some_prop: 'foo' },
- query: { some_query_arg: 'bar' },
-});
-```
-
-#### Undocumented request params
-
-To make requests using undocumented parameters, you may use `// @ts-expect-error` on the undocumented
-parameter. This library doesn't validate at runtime that the request matches the type, so any extra values you
-send will be sent as-is.
-
-```ts
-client.session.list({
- // ...
- // @ts-expect-error baz is not yet public
- baz: 'undocumented option',
-});
-```
-
-For requests with the `GET` verb, any extra params will be in the query, all other requests will send the
-extra param in the body.
-
-If you want to explicitly send an extra argument, you can do so with the `query`, `body`, and `headers` request
-options.
-
-#### Undocumented response properties
-
-To access undocumented response properties, you may access the response object with `// @ts-expect-error` on
-the response object, or cast the response object to the requisite type. Like the request params, we do not
-validate or strip extra properties from the response from the API.
-
-### Customizing the fetch client
-
-By default, this library expects a global `fetch` function is defined.
-
-If you want to use a different `fetch` function, you can either polyfill the global:
-
-```ts
-import fetch from 'my-fetch';
-
-globalThis.fetch = fetch;
-```
-
-Or pass it to the client:
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-import fetch from 'my-fetch';
-
-const client = new Opencode({ fetch });
-```
-
-### Fetch options
-
-If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.)
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({
- fetchOptions: {
- // `RequestInit` options
- },
-});
-```
-
-#### Configuring proxies
-
-To modify proxy behavior, you can provide custom `fetchOptions` that add runtime-specific proxy
-options to requests:
-
-<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/node.svg" align="top" width="18" height="21"> **Node** <sup>[[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)]</sup>
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-import * as undici from 'undici';
-
-const proxyAgent = new undici.ProxyAgent('http://localhost:8888');
-const client = new Opencode({
- fetchOptions: {
- dispatcher: proxyAgent,
- },
-});
-```
-
-<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/bun.svg" align="top" width="18" height="21"> **Bun** <sup>[[docs](https://bun.sh/guides/http/proxy)]</sup>
-
-```ts
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({
- fetchOptions: {
- proxy: 'http://localhost:8888',
- },
-});
-```
-
-<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/deno.svg" align="top" width="18" height="21"> **Deno** <sup>[[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)]</sup>
-
-```ts
-import Opencode from 'npm:@opencode-ai/sdk';
-
-const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });
-const client = new Opencode({
- fetchOptions: {
- client: httpClient,
- },
-});
-```
-
-## Frequently Asked Questions
-
-## Semantic versioning
-
-This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
-
-1. Changes that only affect static types, without breaking runtime behavior.
-2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
-3. Changes that we do not expect to impact the vast majority of users in practice.
-
-We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
-
-We are keen for your feedback; please open an [issue](https://www.github.com/sst/opencode-sdk-js/issues) with questions, bugs, or suggestions.
-
-## Requirements
-
-TypeScript >= 4.9 is supported.
-
-The following runtimes are supported:
-
-- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more)
-- Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions.
-- Deno v1.28.0 or higher.
-- Bun 1.0 or later.
-- Cloudflare Workers.
-- Vercel Edge Runtime.
-- Jest 28 or greater with the `"node"` environment (`"jsdom"` is not supported at this time).
-- Nitro v2.6 or greater.
-
-Note that React Native is not supported at this time.
-
-If you are interested in other runtime environments, please open or upvote an issue on GitHub.
-
-## Contributing
-
-See [the contributing documentation](./CONTRIBUTING.md).
diff --git a/packages/sdk/api.md b/packages/sdk/api.md
deleted file mode 100644
index c0526f063..000000000
--- a/packages/sdk/api.md
+++ /dev/null
@@ -1,139 +0,0 @@
-# Shared
-
-Types:
-
-- <code><a href="./src/resources/shared.ts">MessageAbortedError</a></code>
-- <code><a href="./src/resources/shared.ts">ProviderAuthError</a></code>
-- <code><a href="./src/resources/shared.ts">UnknownError</a></code>
-
-# Event
-
-Types:
-
-- <code><a href="./src/resources/event.ts">EventListResponse</a></code>
-
-Methods:
-
-- <code title="get /event">client.event.<a href="./src/resources/event.ts">list</a>() -> EventListResponse</code>
-
-# App
-
-Types:
-
-- <code><a href="./src/resources/app.ts">App</a></code>
-- <code><a href="./src/resources/app.ts">Mode</a></code>
-- <code><a href="./src/resources/app.ts">Model</a></code>
-- <code><a href="./src/resources/app.ts">Provider</a></code>
-- <code><a href="./src/resources/app.ts">AppInitResponse</a></code>
-- <code><a href="./src/resources/app.ts">AppLogResponse</a></code>
-- <code><a href="./src/resources/app.ts">AppModesResponse</a></code>
-- <code><a href="./src/resources/app.ts">AppProvidersResponse</a></code>
-
-Methods:
-
-- <code title="get /app">client.app.<a href="./src/resources/app.ts">get</a>() -> App</code>
-- <code title="post /app/init">client.app.<a href="./src/resources/app.ts">init</a>() -> AppInitResponse</code>
-- <code title="post /log">client.app.<a href="./src/resources/app.ts">log</a>({ ...params }) -> AppLogResponse</code>
-- <code title="get /mode">client.app.<a href="./src/resources/app.ts">modes</a>() -> AppModesResponse</code>
-- <code title="get /config/providers">client.app.<a href="./src/resources/app.ts">providers</a>() -> AppProvidersResponse</code>
-
-# Find
-
-Types:
-
-- <code><a href="./src/resources/find.ts">Symbol</a></code>
-- <code><a href="./src/resources/find.ts">FindFilesResponse</a></code>
-- <code><a href="./src/resources/find.ts">FindSymbolsResponse</a></code>
-- <code><a href="./src/resources/find.ts">FindTextResponse</a></code>
-
-Methods:
-
-- <code title="get /find/file">client.find.<a href="./src/resources/find.ts">files</a>({ ...params }) -> FindFilesResponse</code>
-- <code title="get /find/symbol">client.find.<a href="./src/resources/find.ts">symbols</a>({ ...params }) -> FindSymbolsResponse</code>
-- <code title="get /find">client.find.<a href="./src/resources/find.ts">text</a>({ ...params }) -> FindTextResponse</code>
-
-# File
-
-Types:
-
-- <code><a href="./src/resources/file.ts">File</a></code>
-- <code><a href="./src/resources/file.ts">FileReadResponse</a></code>
-- <code><a href="./src/resources/file.ts">FileStatusResponse</a></code>
-
-Methods:
-
-- <code title="get /file">client.file.<a href="./src/resources/file.ts">read</a>({ ...params }) -> FileReadResponse</code>
-- <code title="get /file/status">client.file.<a href="./src/resources/file.ts">status</a>() -> FileStatusResponse</code>
-
-# Config
-
-Types:
-
-- <code><a href="./src/resources/config.ts">Config</a></code>
-- <code><a href="./src/resources/config.ts">KeybindsConfig</a></code>
-- <code><a href="./src/resources/config.ts">McpLocalConfig</a></code>
-- <code><a href="./src/resources/config.ts">McpRemoteConfig</a></code>
-- <code><a href="./src/resources/config.ts">ModeConfig</a></code>
-
-Methods:
-
-- <code title="get /config">client.config.<a href="./src/resources/config.ts">get</a>() -> Config</code>
-
-# Session
-
-Types:
-
-- <code><a href="./src/resources/session.ts">AssistantMessage</a></code>
-- <code><a href="./src/resources/session.ts">FilePart</a></code>
-- <code><a href="./src/resources/session.ts">FilePartInput</a></code>
-- <code><a href="./src/resources/session.ts">FilePartSource</a></code>
-- <code><a href="./src/resources/session.ts">FilePartSourceText</a></code>
-- <code><a href="./src/resources/session.ts">FileSource</a></code>
-- <code><a href="./src/resources/session.ts">Message</a></code>
-- <code><a href="./src/resources/session.ts">Part</a></code>
-- <code><a href="./src/resources/session.ts">Session</a></code>
-- <code><a href="./src/resources/session.ts">SnapshotPart</a></code>
-- <code><a href="./src/resources/session.ts">StepFinishPart</a></code>
-- <code><a href="./src/resources/session.ts">StepStartPart</a></code>
-- <code><a href="./src/resources/session.ts">SymbolSource</a></code>
-- <code><a href="./src/resources/session.ts">TextPart</a></code>
-- <code><a href="./src/resources/session.ts">TextPartInput</a></code>
-- <code><a href="./src/resources/session.ts">ToolPart</a></code>
-- <code><a href="./src/resources/session.ts">ToolStateCompleted</a></code>
-- <code><a href="./src/resources/session.ts">ToolStateError</a></code>
-- <code><a href="./src/resources/session.ts">ToolStatePending</a></code>
-- <code><a href="./src/resources/session.ts">ToolStateRunning</a></code>
-- <code><a href="./src/resources/session.ts">UserMessage</a></code>
-- <code><a href="./src/resources/session.ts">SessionListResponse</a></code>
-- <code><a href="./src/resources/session.ts">SessionDeleteResponse</a></code>
-- <code><a href="./src/resources/session.ts">SessionAbortResponse</a></code>
-- <code><a href="./src/resources/session.ts">SessionInitResponse</a></code>
-- <code><a href="./src/resources/session.ts">SessionMessagesResponse</a></code>
-- <code><a href="./src/resources/session.ts">SessionSummarizeResponse</a></code>
-
-Methods:
-
-- <code title="post /session">client.session.<a href="./src/resources/session.ts">create</a>() -> Session</code>
-- <code title="get /session">client.session.<a href="./src/resources/session.ts">list</a>() -> SessionListResponse</code>
-- <code title="delete /session/{id}">client.session.<a href="./src/resources/session.ts">delete</a>(id) -> SessionDeleteResponse</code>
-- <code title="post /session/{id}/abort">client.session.<a href="./src/resources/session.ts">abort</a>(id) -> SessionAbortResponse</code>
-- <code title="post /session/{id}/message">client.session.<a href="./src/resources/session.ts">chat</a>(id, { ...params }) -> AssistantMessage</code>
-- <code title="post /session/{id}/init">client.session.<a href="./src/resources/session.ts">init</a>(id, { ...params }) -> SessionInitResponse</code>
-- <code title="get /session/{id}/message">client.session.<a href="./src/resources/session.ts">messages</a>(id) -> SessionMessagesResponse</code>
-- <code title="post /session/{id}/revert">client.session.<a href="./src/resources/session.ts">revert</a>(id, { ...params }) -> Session</code>
-- <code title="post /session/{id}/share">client.session.<a href="./src/resources/session.ts">share</a>(id) -> Session</code>
-- <code title="post /session/{id}/summarize">client.session.<a href="./src/resources/session.ts">summarize</a>(id, { ...params }) -> SessionSummarizeResponse</code>
-- <code title="post /session/{id}/unrevert">client.session.<a href="./src/resources/session.ts">unrevert</a>(id) -> Session</code>
-- <code title="delete /session/{id}/share">client.session.<a href="./src/resources/session.ts">unshare</a>(id) -> Session</code>
-
-# Tui
-
-Types:
-
-- <code><a href="./src/resources/tui.ts">TuiAppendPromptResponse</a></code>
-- <code><a href="./src/resources/tui.ts">TuiOpenHelpResponse</a></code>
-
-Methods:
-
-- <code title="post /tui/append-prompt">client.tui.<a href="./src/resources/tui.ts">appendPrompt</a>({ ...params }) -> TuiAppendPromptResponse</code>
-- <code title="post /tui/open-help">client.tui.<a href="./src/resources/tui.ts">openHelp</a>() -> TuiOpenHelpResponse</code>
diff --git a/packages/sdk/bin/check-release-environment b/packages/sdk/bin/check-release-environment
deleted file mode 100644
index e4b6d58ea..000000000
--- a/packages/sdk/bin/check-release-environment
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-
-errors=()
-
-if [ -z "${NPM_TOKEN}" ]; then
- errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets")
-fi
-
-lenErrors=${#errors[@]}
-
-if [[ lenErrors -gt 0 ]]; then
- echo -e "Found the following errors in the release environment:\n"
-
- for error in "${errors[@]}"; do
- echo -e "- $error\n"
- done
-
- exit 1
-fi
-
-echo "The environment is ready to push releases!"
-
diff --git a/packages/sdk/bin/publish-npm b/packages/sdk/bin/publish-npm
deleted file mode 100644
index fa2243d24..000000000
--- a/packages/sdk/bin/publish-npm
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env bash
-
-set -eux
-
-npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN"
-
-yarn build
-cd dist
-
-# Get package name and version from package.json
-PACKAGE_NAME="$(jq -r -e '.name' ./package.json)"
-VERSION="$(jq -r -e '.version' ./package.json)"
-
-# Get latest version from npm
-#
-# If the package doesn't exist, npm will return:
-# {
-# "error": {
-# "code": "E404",
-# "summary": "Unpublished on 2025-06-05T09:54:53.528Z",
-# "detail": "'the_package' is not in this registry..."
-# }
-# }
-NPM_INFO="$(npm view "$PACKAGE_NAME" version --json 2>/dev/null || true)"
-
-# Check if we got an E404 error
-if echo "$NPM_INFO" | jq -e '.error.code == "E404"' > /dev/null 2>&1; then
- # Package doesn't exist yet, no last version
- LAST_VERSION=""
-elif echo "$NPM_INFO" | jq -e '.error' > /dev/null 2>&1; then
- # Report other errors
- echo "ERROR: npm returned unexpected data:"
- echo "$NPM_INFO"
- exit 1
-else
- # Success - get the version
- LAST_VERSION=$(echo "$NPM_INFO" | jq -r '.') # strip quotes
-fi
-
-# Check if current version is pre-release (e.g. alpha / beta / rc)
-CURRENT_IS_PRERELEASE=false
-if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then
- CURRENT_IS_PRERELEASE=true
- CURRENT_TAG="${BASH_REMATCH[1]}"
-fi
-
-# Check if last version is a stable release
-LAST_IS_STABLE_RELEASE=true
-if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then
- LAST_IS_STABLE_RELEASE=false
-fi
-
-# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease.
-if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then
- TAG="$CURRENT_TAG"
-else
- TAG="latest"
-fi
-
-# Publish with the appropriate tag
-yarn publish --access public --tag "$TAG"
diff --git a/packages/sdk/eslint.config.mjs b/packages/sdk/eslint.config.mjs
deleted file mode 100644
index 818092eda..000000000
--- a/packages/sdk/eslint.config.mjs
+++ /dev/null
@@ -1,42 +0,0 @@
-// @ts-check
-import tseslint from 'typescript-eslint';
-import unusedImports from 'eslint-plugin-unused-imports';
-import prettier from 'eslint-plugin-prettier';
-
-export default tseslint.config(
- {
- languageOptions: {
- parser: tseslint.parser,
- parserOptions: { sourceType: 'module' },
- },
- files: ['**/*.ts', '**/*.mts', '**/*.cts', '**/*.js', '**/*.mjs', '**/*.cjs'],
- ignores: ['dist/'],
- plugins: {
- '@typescript-eslint': tseslint.plugin,
- 'unused-imports': unusedImports,
- prettier,
- },
- rules: {
- 'no-unused-vars': 'off',
- 'prettier/prettier': 'error',
- 'unused-imports/no-unused-imports': 'error',
- 'no-restricted-imports': [
- 'error',
- {
- patterns: [
- {
- regex: '^@opencode-ai/sdk(/.*)?',
- message: 'Use a relative import, not a package import.',
- },
- ],
- },
- ],
- },
- },
- {
- files: ['tests/**', 'examples/**'],
- rules: {
- 'no-restricted-imports': 'off',
- },
- },
-);
diff --git a/packages/sdk/go/.devcontainer/devcontainer.json b/packages/sdk/go/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..889ae3472
--- /dev/null
+++ b/packages/sdk/go/.devcontainer/devcontainer.json
@@ -0,0 +1,7 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/debian
+{
+ "name": "Development",
+ "image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
+ "postCreateCommand": "go mod tidy"
+}
diff --git a/packages/sdk/go/.github/workflows/ci.yml b/packages/sdk/go/.github/workflows/ci.yml
new file mode 100644
index 000000000..4bf1e907c
--- /dev/null
+++ b/packages/sdk/go/.github/workflows/ci.yml
@@ -0,0 +1,49 @@
+name: CI
+on:
+ push:
+ branches-ignore:
+ - 'generated'
+ - 'codegen/**'
+ - 'integrated/**'
+ - 'stl-preview-head/**'
+ - 'stl-preview-base/**'
+ pull_request:
+ branches-ignore:
+ - 'stl-preview-head/**'
+ - 'stl-preview-base/**'
+
+jobs:
+ lint:
+ timeout-minutes: 10
+ name: lint
+ runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: ./go.mod
+
+ - name: Run lints
+ run: ./scripts/lint
+ test:
+ timeout-minutes: 10
+ name: test
+ runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: ./go.mod
+
+ - name: Bootstrap
+ run: ./scripts/bootstrap
+
+ - name: Run tests
+ run: ./scripts/test
diff --git a/packages/sdk/go/.gitignore b/packages/sdk/go/.gitignore
new file mode 100644
index 000000000..c6d050151
--- /dev/null
+++ b/packages/sdk/go/.gitignore
@@ -0,0 +1,4 @@
+.prism.log
+codegen.log
+Brewfile.lock.json
+.idea/
diff --git a/packages/sdk/go/.release-please-manifest.json b/packages/sdk/go/.release-please-manifest.json
new file mode 100644
index 000000000..c373724dc
--- /dev/null
+++ b/packages/sdk/go/.release-please-manifest.json
@@ -0,0 +1,3 @@
+{
+ ".": "0.1.0-alpha.8"
+} \ No newline at end of file
diff --git a/packages/sdk/go/.stats.yml b/packages/sdk/go/.stats.yml
new file mode 100644
index 000000000..a42ec8ee2
--- /dev/null
+++ b/packages/sdk/go/.stats.yml
@@ -0,0 +1,4 @@
+configured_endpoints: 26
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-5bf6a39123d248d306490c1dee61b46ba113ea2c415a4de1a631c76462769c49.yml
+openapi_spec_hash: 3c5b25f121429281275ffd70c9d5cfe4
+config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3
diff --git a/packages/sdk/go/Brewfile b/packages/sdk/go/Brewfile
new file mode 100644
index 000000000..577e34a4b
--- /dev/null
+++ b/packages/sdk/go/Brewfile
@@ -0,0 +1 @@
+brew "go"
diff --git a/packages/sdk/go/CHANGELOG.md b/packages/sdk/go/CHANGELOG.md
new file mode 100644
index 000000000..bc407fad9
--- /dev/null
+++ b/packages/sdk/go/CHANGELOG.md
@@ -0,0 +1,73 @@
+# Changelog
+
+## 0.1.0-alpha.8 (2025-07-02)
+
+Full Changelog: [v0.1.0-alpha.7...v0.1.0-alpha.8](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.7...v0.1.0-alpha.8)
+
+### Features
+
+* **api:** update via SDK Studio ([651e937](https://github.com/sst/opencode-sdk-go/commit/651e937c334e1caba3b968e6cac865c219879519))
+
+## 0.1.0-alpha.7 (2025-06-30)
+
+Full Changelog: [v0.1.0-alpha.6...v0.1.0-alpha.7](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.6...v0.1.0-alpha.7)
+
+### Features
+
+* **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775))
+* **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf))
+
+
+### Chores
+
+* **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d))
+
+## 0.1.0-alpha.6 (2025-06-28)
+
+Full Changelog: [v0.1.0-alpha.5...v0.1.0-alpha.6](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.5...v0.1.0-alpha.6)
+
+### Bug Fixes
+
+* don't try to deserialize as json when ResponseBodyInto is []byte ([5988d04](https://github.com/sst/opencode-sdk-go/commit/5988d04839cb78b6613057280b91b72a60fef33d))
+
+## 0.1.0-alpha.5 (2025-06-27)
+
+Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.4...v0.1.0-alpha.5)
+
+### Features
+
+* **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e))
+
+## 0.1.0-alpha.4 (2025-06-27)
+
+Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
+
+### Features
+
+* **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52))
+
+## 0.1.0-alpha.3 (2025-06-27)
+
+Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.2...v0.1.0-alpha.3)
+
+### Features
+
+* **api:** update via SDK Studio ([57f3230](https://github.com/sst/opencode-sdk-go/commit/57f32309023cc1f0f20c20d02a3907e390a71f61))
+
+## 0.1.0-alpha.2 (2025-06-27)
+
+Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/sst/opencode-sdk-go/compare/v0.1.0-alpha.1...v0.1.0-alpha.2)
+
+### Features
+
+* **api:** update via SDK Studio ([a766f1c](https://github.com/sst/opencode-sdk-go/commit/a766f1c54f02bbc1380151b0e22d97cc2c5892e6))
+
+## 0.1.0-alpha.1 (2025-06-27)
+
+Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/sst/opencode-sdk-go/compare/v0.0.1-alpha.0...v0.1.0-alpha.1)
+
+### Features
+
+* **api:** update via SDK Studio ([27b7376](https://github.com/sst/opencode-sdk-go/commit/27b7376310466ee17a63f2104f546b53a2b8361a))
+* **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397))
+* **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844))
diff --git a/packages/sdk/go/CONTRIBUTING.md b/packages/sdk/go/CONTRIBUTING.md
new file mode 100644
index 000000000..34620a3c1
--- /dev/null
+++ b/packages/sdk/go/CONTRIBUTING.md
@@ -0,0 +1,66 @@
+## Setting up the environment
+
+To set up the repository, run:
+
+```sh
+$ ./scripts/bootstrap
+$ ./scripts/build
+```
+
+This will install all the required dependencies and build the SDK.
+
+You can also [install go 1.18+ manually](https://go.dev/doc/install).
+
+## Modifying/Adding code
+
+Most of the SDK is generated code. Modifications to code will be persisted between generations, but may
+result in merge conflicts between manual patches and changes from the generator. The generator will never
+modify the contents of the `lib/` and `examples/` directories.
+
+## Adding and running examples
+
+All files in the `examples/` directory are not modified by the generator and can be freely edited or added to.
+
+```go
+# add an example to examples/<your-example>/main.go
+
+package main
+
+func main() {
+ // ...
+}
+```
+
+```sh
+$ go run ./examples/<your-example>
+```
+
+## Using the repository from source
+
+To use a local version of this library from source in another project, edit the `go.mod` with a replace
+directive. This can be done through the CLI with the following:
+
+```sh
+$ go mod edit -replace github.com/sst/opencode-sdk-go=/path/to/opencode-sdk-go
+```
+
+## Running tests
+
+Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
+
+```sh
+# you will need npm installed
+$ npx prism mock path/to/your/openapi.yml
+```
+
+```sh
+$ ./scripts/test
+```
+
+## Formatting
+
+This library uses the standard gofmt code formatter:
+
+```sh
+$ ./scripts/format
+```
diff --git a/packages/sdk/LICENSE b/packages/sdk/go/LICENSE
index 821edebd5..821edebd5 100644
--- a/packages/sdk/LICENSE
+++ b/packages/sdk/go/LICENSE
diff --git a/packages/sdk/go/README.md b/packages/sdk/go/README.md
new file mode 100644
index 000000000..2588b6147
--- /dev/null
+++ b/packages/sdk/go/README.md
@@ -0,0 +1,354 @@
+# Opencode Go API Library
+
+<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go"><img src="https://pkg.go.dev/badge/github.com/sst/opencode-sdk-go.svg" alt="Go Reference"></a>
+
+The Opencode Go library provides convenient access to the [Opencode REST API](https://opencode.ai/docs)
+from applications written in Go.
+
+It is generated with [Stainless](https://www.stainless.com/).
+
+## Installation
+
+<!-- x-release-please-start-version -->
+
+```go
+import (
+ "github.com/sst/opencode-sdk-go" // imported as opencode
+)
+```
+
+<!-- x-release-please-end -->
+
+Or to pin the version:
+
+<!-- x-release-please-start-version -->
+
+```sh
+go get -u 'github.com/sst/[email protected]'
+```
+
+<!-- x-release-please-end -->
+
+## Requirements
+
+This library requires Go 1.18+.
+
+## Usage
+
+The full API of this library can be found in [api.md](api.md).
+
+```go
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/sst/opencode-sdk-go"
+)
+
+func main() {
+ client := opencode.NewClient()
+ sessions, err := client.Session.List(context.TODO())
+ if err != nil {
+ panic(err.Error())
+ }
+ fmt.Printf("%+v\n", sessions)
+}
+
+```
+
+### Request fields
+
+All request parameters are wrapped in a generic `Field` type,
+which we use to distinguish zero values from null or omitted fields.
+
+This prevents accidentally sending a zero value if you forget a required parameter,
+and enables explicitly sending `null`, `false`, `''`, or `0` on optional parameters.
+Any field not specified is not sent.
+
+To construct fields with values, use the helpers `String()`, `Int()`, `Float()`, or most commonly, the generic `F[T]()`.
+To send a null, use `Null[T]()`, and to send a nonconforming value, use `Raw[T](any)`. For example:
+
+```go
+params := FooParams{
+ Name: opencode.F("hello"),
+
+ // Explicitly send `"description": null`
+ Description: opencode.Null[string](),
+
+ Point: opencode.F(opencode.Point{
+ X: opencode.Int(0),
+ Y: opencode.Int(1),
+
+ // In cases where the API specifies a given type,
+ // but you want to send something else, use `Raw`:
+ Z: opencode.Raw[int64](0.01), // sends a float
+ }),
+}
+```
+
+### Response objects
+
+All fields in response structs are value types (not pointers or wrappers).
+
+If a given field is `null`, not present, or invalid, the corresponding field
+will simply be its zero value.
+
+All response structs also include a special `JSON` field, containing more detailed
+information about each property, which you can use like so:
+
+```go
+if res.Name == "" {
+ // true if `"name"` is either not present or explicitly null
+ res.JSON.Name.IsNull()
+
+ // true if the `"name"` key was not present in the response JSON at all
+ res.JSON.Name.IsMissing()
+
+ // When the API returns data that cannot be coerced to the expected type:
+ if res.JSON.Name.IsInvalid() {
+ raw := res.JSON.Name.Raw()
+
+ legacyName := struct{
+ First string `json:"first"`
+ Last string `json:"last"`
+ }{}
+ json.Unmarshal([]byte(raw), &legacyName)
+ name = legacyName.First + " " + legacyName.Last
+ }
+}
+```
+
+These `.JSON` structs also include an `Extras` map containing
+any properties in the json response that were not specified
+in the struct. This can be useful for API features not yet
+present in the SDK.
+
+```go
+body := res.JSON.ExtraFields["my_unexpected_field"].Raw()
+```
+
+### RequestOptions
+
+This library uses the functional options pattern. Functions defined in the
+`option` package return a `RequestOption`, which is a closure that mutates a
+`RequestConfig`. These options can be supplied to the client or at individual
+requests. For example:
+
+```go
+client := opencode.NewClient(
+ // Adds a header to every request made by the client
+ option.WithHeader("X-Some-Header", "custom_header_info"),
+)
+
+client.Session.List(context.TODO(), ...,
+ // Override the header
+ option.WithHeader("X-Some-Header", "some_other_custom_header_info"),
+ // Add an undocumented field to the request body, using sjson syntax
+ option.WithJSONSet("some.json.path", map[string]string{"my": "object"}),
+)
+```
+
+See the [full list of request options](https://pkg.go.dev/github.com/sst/opencode-sdk-go/option).
+
+### Pagination
+
+This library provides some conveniences for working with paginated list endpoints.
+
+You can use `.ListAutoPaging()` methods to iterate through items across all pages:
+
+Or you can use simple `.List()` methods to fetch a single page and receive a standard response object
+with additional helper methods like `.GetNextPage()`, e.g.:
+
+### Errors
+
+When the API returns a non-success status code, we return an error with type
+`*opencode.Error`. This contains the `StatusCode`, `*http.Request`, and
+`*http.Response` values of the request, as well as the JSON of the error body
+(much like other response objects in the SDK).
+
+To handle errors, we recommend that you use the `errors.As` pattern:
+
+```go
+_, err := client.Session.List(context.TODO())
+if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ println(string(apierr.DumpRequest(true))) // Prints the serialized HTTP request
+ println(string(apierr.DumpResponse(true))) // Prints the serialized HTTP response
+ }
+ panic(err.Error()) // GET "/session": 400 Bad Request { ... }
+}
+```
+
+When other errors occur, they are returned unwrapped; for example,
+if HTTP transport fails, you might receive `*url.Error` wrapping `*net.OpError`.
+
+### Timeouts
+
+Requests do not time out by default; use context to configure a timeout for a request lifecycle.
+
+Note that if a request is [retried](#retries), the context timeout does not start over.
+To set a per-retry timeout, use `option.WithRequestTimeout()`.
+
+```go
+// This sets the timeout for the request, including all the retries.
+ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
+defer cancel()
+client.Session.List(
+ ctx,
+ // This sets the per-retry timeout
+ option.WithRequestTimeout(20*time.Second),
+)
+```
+
+### File uploads
+
+Request parameters that correspond to file uploads in multipart requests are typed as
+`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form
+part with the file name of "anonymous_file" and content-type of "application/octet-stream".
+
+The file name and content-type can be customized by implementing `Name() string` or `ContentType()
+string` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a
+file returned by `os.Open` will be sent with the file name on disk.
+
+We also provide a helper `opencode.FileParam(reader io.Reader, filename string, contentType string)`
+which can be used to wrap any `io.Reader` with the appropriate file name and content type.
+
+### Retries
+
+Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
+We retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit,
+and >=500 Internal errors.
+
+You can use the `WithMaxRetries` option to configure or disable this:
+
+```go
+// Configure the default for all requests:
+client := opencode.NewClient(
+ option.WithMaxRetries(0), // default is 2
+)
+
+// Override per-request:
+client.Session.List(context.TODO(), option.WithMaxRetries(5))
+```
+
+### Accessing raw response data (e.g. response headers)
+
+You can access the raw HTTP response data by using the `option.WithResponseInto()` request option. This is useful when
+you need to examine response headers, status codes, or other details.
+
+```go
+// Create a variable to store the HTTP response
+var response *http.Response
+sessions, err := client.Session.List(context.TODO(), option.WithResponseInto(&response))
+if err != nil {
+ // handle error
+}
+fmt.Printf("%+v\n", sessions)
+
+fmt.Printf("Status Code: %d\n", response.StatusCode)
+fmt.Printf("Headers: %+#v\n", response.Header)
+```
+
+### Making custom/undocumented requests
+
+This library is typed for convenient access to the documented API. If you need to access undocumented
+endpoints, params, or response properties, the library can still be used.
+
+#### Undocumented endpoints
+
+To make requests to undocumented endpoints, you can use `client.Get`, `client.Post`, and other HTTP verbs.
+`RequestOptions` on the client, such as retries, will be respected when making these requests.
+
+```go
+var (
+ // params can be an io.Reader, a []byte, an encoding/json serializable object,
+ // or a "…Params" struct defined in this library.
+ params map[string]interface{}
+
+ // result can be an []byte, *http.Response, a encoding/json deserializable object,
+ // or a model defined in this library.
+ result *http.Response
+)
+err := client.Post(context.Background(), "/unspecified", params, &result)
+if err != nil {
+ …
+}
+```
+
+#### Undocumented request params
+
+To make requests using undocumented parameters, you may use either the `option.WithQuerySet()`
+or the `option.WithJSONSet()` methods.
+
+```go
+params := FooNewParams{
+ ID: opencode.F("id_xxxx"),
+ Data: opencode.F(FooNewParamsData{
+ FirstName: opencode.F("John"),
+ }),
+}
+client.Foo.New(context.Background(), params, option.WithJSONSet("data.last_name", "Doe"))
+```
+
+#### Undocumented response properties
+
+To access undocumented response properties, you may either access the raw JSON of the response as a string
+with `result.JSON.RawJSON()`, or get the raw JSON of a particular field on the result with
+`result.JSON.Foo.Raw()`.
+
+Any fields that are not present on the response struct will be saved and can be accessed by `result.JSON.ExtraFields()` which returns the extra fields as a `map[string]Field`.
+
+### Middleware
+
+We provide `option.WithMiddleware` which applies the given
+middleware to requests.
+
+```go
+func Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response, err error) {
+ // Before the request
+ start := time.Now()
+ LogReq(req)
+
+ // Forward the request to the next handler
+ res, err = next(req)
+
+ // Handle stuff after the request
+ end := time.Now()
+ LogRes(res, err, start - end)
+
+ return res, err
+}
+
+client := opencode.NewClient(
+ option.WithMiddleware(Logger),
+)
+```
+
+When multiple middlewares are provided as variadic arguments, the middlewares
+are applied left to right. If `option.WithMiddleware` is given
+multiple times, for example first in the client then the method, the
+middleware in the client will run first and the middleware given in the method
+will run next.
+
+You may also replace the default `http.Client` with
+`option.WithHTTPClient(client)`. Only one http client is
+accepted (this overwrites any previous client) and receives requests after any
+middleware has been applied.
+
+## Semantic versioning
+
+This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
+
+1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
+2. Changes that we do not expect to impact the vast majority of users in practice.
+
+We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
+
+We are keen for your feedback; please open an [issue](https://www.github.com/sst/opencode-sdk-go/issues) with questions, bugs, or suggestions.
+
+## Contributing
+
+See [the contributing documentation](./CONTRIBUTING.md).
diff --git a/packages/sdk/SECURITY.md b/packages/sdk/go/SECURITY.md
index 6912e12bc..6912e12bc 100644
--- a/packages/sdk/SECURITY.md
+++ b/packages/sdk/go/SECURITY.md
diff --git a/packages/sdk/go/aliases.go b/packages/sdk/go/aliases.go
new file mode 100644
index 000000000..6ab36d04c
--- /dev/null
+++ b/packages/sdk/go/aliases.go
@@ -0,0 +1,43 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "github.com/sst/opencode-sdk-go/internal/apierror"
+ "github.com/sst/opencode-sdk-go/shared"
+)
+
+type Error = apierror.Error
+
+// This is an alias to an internal type.
+type MessageAbortedError = shared.MessageAbortedError
+
+// This is an alias to an internal type.
+type MessageAbortedErrorName = shared.MessageAbortedErrorName
+
+// This is an alias to an internal value.
+const MessageAbortedErrorNameMessageAbortedError = shared.MessageAbortedErrorNameMessageAbortedError
+
+// This is an alias to an internal type.
+type ProviderAuthError = shared.ProviderAuthError
+
+// This is an alias to an internal type.
+type ProviderAuthErrorData = shared.ProviderAuthErrorData
+
+// This is an alias to an internal type.
+type ProviderAuthErrorName = shared.ProviderAuthErrorName
+
+// This is an alias to an internal value.
+const ProviderAuthErrorNameProviderAuthError = shared.ProviderAuthErrorNameProviderAuthError
+
+// This is an alias to an internal type.
+type UnknownError = shared.UnknownError
+
+// This is an alias to an internal type.
+type UnknownErrorData = shared.UnknownErrorData
+
+// This is an alias to an internal type.
+type UnknownErrorName = shared.UnknownErrorName
+
+// This is an alias to an internal value.
+const UnknownErrorNameUnknownError = shared.UnknownErrorNameUnknownError
diff --git a/packages/sdk/go/api.md b/packages/sdk/go/api.md
new file mode 100644
index 000000000..fb3db9c53
--- /dev/null
+++ b/packages/sdk/go/api.md
@@ -0,0 +1,128 @@
+# Shared Response Types
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared#MessageAbortedError">MessageAbortedError</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared#ProviderAuthError">ProviderAuthError</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go/shared#UnknownError">UnknownError</a>
+
+# Event
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#EventListResponse">EventListResponse</a>
+
+Methods:
+
+- <code title="get /event">client.Event.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#EventService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#EventListResponse">EventListResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# App
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#App">App</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Mode">Mode</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Model">Model</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Provider">Provider</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppProvidersResponse">AppProvidersResponse</a>
+
+Methods:
+
+- <code title="get /app">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#App">App</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /app/init">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /log">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Log">Log</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppLogParams">AppLogParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /mode">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Modes">Modes</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Mode">Mode</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /config/providers">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Providers">Providers</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppProvidersResponse">AppProvidersResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# Find
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Symbol">Symbol</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindTextResponse">FindTextResponse</a>
+
+Methods:
+
+- <code title="get /find/file">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Files">Files</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindFilesParams">FindFilesParams</a>) ([]<a href="https://pkg.go.dev/builtin#string">string</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /find/symbol">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Symbols">Symbols</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindSymbolsParams">FindSymbolsParams</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Symbol">Symbol</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /find">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Text">Text</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindTextParams">FindTextParams</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindTextResponse">FindTextResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# File
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#File">File</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileReadResponse">FileReadResponse</a>
+
+Methods:
+
+- <code title="get /file">client.File.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileService.Read">Read</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileReadParams">FileReadParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileReadResponse">FileReadResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /file/status">client.File.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileService.Status">Status</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#File">File</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# Config
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Config">Config</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#KeybindsConfig">KeybindsConfig</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#McpLocalConfig">McpLocalConfig</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#McpRemoteConfig">McpRemoteConfig</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ModeConfig">ModeConfig</a>
+
+Methods:
+
+- <code title="get /config">client.Config.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ConfigService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Config">Config</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# Session
+
+Params Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartInputParam">FilePartInputParam</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSourceUnionParam">FilePartSourceUnionParam</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSourceTextParam">FilePartSourceTextParam</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileSourceParam">FileSourceParam</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SymbolSourceParam">SymbolSourceParam</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TextPartInputParam">TextPartInputParam</a>
+
+Response Types:
+
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePart">FilePart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSource">FilePartSource</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartSourceText">FilePartSourceText</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileSource">FileSource</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Message">Message</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Part">Part</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SnapshotPart">SnapshotPart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#StepFinishPart">StepFinishPart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#StepStartPart">StepStartPart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SymbolSource">SymbolSource</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TextPart">TextPart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolPart">ToolPart</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateCompleted">ToolStateCompleted</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateError">ToolStateError</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStatePending">ToolStatePending</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateRunning">ToolStateRunning</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#UserMessage">UserMessage</a>
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessagesResponse">SessionMessagesResponse</a>
+
+Methods:
+
+- <code title="post /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="delete /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/abort">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Abort">Abort</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Chat">Chat</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatParams">SessionChatParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/init">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionInitParams">SessionInitParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Messages">Messages</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessagesResponse">SessionMessagesResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/revert">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Revert">Revert</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionRevertParams">SessionRevertParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/share">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Share">Share</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/summarize">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Summarize">Summarize</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionSummarizeParams">SessionSummarizeParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /session/{id}/unrevert">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Unrevert">Unrevert</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="delete /session/{id}/share">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Unshare">Unshare</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+
+# Tui
+
+Methods:
+
+- <code title="post /tui/append-prompt">client.Tui.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiService.AppendPrompt">AppendPrompt</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiAppendPromptParams">TuiAppendPromptParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="post /tui/open-help">client.Tui.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiService.OpenHelp">OpenHelp</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
diff --git a/packages/sdk/go/app.go b/packages/sdk/go/app.go
new file mode 100644
index 000000000..479011a23
--- /dev/null
+++ b/packages/sdk/go/app.go
@@ -0,0 +1,368 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+// AppService contains methods and other services that help with interacting with
+// the opencode 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 [NewAppService] method instead.
+type AppService struct {
+ Options []option.RequestOption
+}
+
+// NewAppService 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 NewAppService(opts ...option.RequestOption) (r *AppService) {
+ r = &AppService{}
+ r.Options = opts
+ return
+}
+
+// Get app info
+func (r *AppService) Get(ctx context.Context, opts ...option.RequestOption) (res *App, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "app"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Initialize the app
+func (r *AppService) Init(ctx context.Context, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "app/init"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+// Write a log entry to the server logs
+func (r *AppService) Log(ctx context.Context, body AppLogParams, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "log"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// List all modes
+func (r *AppService) Modes(ctx context.Context, opts ...option.RequestOption) (res *[]Mode, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "mode"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// List all providers
+func (r *AppService) Providers(ctx context.Context, opts ...option.RequestOption) (res *AppProvidersResponse, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "config/providers"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+type App struct {
+ Git bool `json:"git,required"`
+ Hostname string `json:"hostname,required"`
+ Path AppPath `json:"path,required"`
+ Time AppTime `json:"time,required"`
+ JSON appJSON `json:"-"`
+}
+
+// appJSON contains the JSON metadata for the struct [App]
+type appJSON struct {
+ Git apijson.Field
+ Hostname apijson.Field
+ Path apijson.Field
+ Time apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *App) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r appJSON) RawJSON() string {
+ return r.raw
+}
+
+type AppPath struct {
+ Config string `json:"config,required"`
+ Cwd string `json:"cwd,required"`
+ Data string `json:"data,required"`
+ Root string `json:"root,required"`
+ State string `json:"state,required"`
+ JSON appPathJSON `json:"-"`
+}
+
+// appPathJSON contains the JSON metadata for the struct [AppPath]
+type appPathJSON struct {
+ Config apijson.Field
+ Cwd apijson.Field
+ Data apijson.Field
+ Root apijson.Field
+ State apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AppPath) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r appPathJSON) RawJSON() string {
+ return r.raw
+}
+
+type AppTime struct {
+ Initialized float64 `json:"initialized"`
+ JSON appTimeJSON `json:"-"`
+}
+
+// appTimeJSON contains the JSON metadata for the struct [AppTime]
+type appTimeJSON struct {
+ Initialized apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AppTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r appTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type Mode struct {
+ Name string `json:"name,required"`
+ Tools map[string]bool `json:"tools,required"`
+ Model ModeModel `json:"model"`
+ Prompt string `json:"prompt"`
+ Temperature float64 `json:"temperature"`
+ JSON modeJSON `json:"-"`
+}
+
+// modeJSON contains the JSON metadata for the struct [Mode]
+type modeJSON struct {
+ Name apijson.Field
+ Tools apijson.Field
+ Model apijson.Field
+ Prompt apijson.Field
+ Temperature apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Mode) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modeJSON) RawJSON() string {
+ return r.raw
+}
+
+type ModeModel struct {
+ ModelID string `json:"modelID,required"`
+ ProviderID string `json:"providerID,required"`
+ JSON modeModelJSON `json:"-"`
+}
+
+// modeModelJSON contains the JSON metadata for the struct [ModeModel]
+type modeModelJSON struct {
+ ModelID apijson.Field
+ ProviderID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ModeModel) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modeModelJSON) RawJSON() string {
+ return r.raw
+}
+
+type Model struct {
+ ID string `json:"id,required"`
+ Attachment bool `json:"attachment,required"`
+ Cost ModelCost `json:"cost,required"`
+ Limit ModelLimit `json:"limit,required"`
+ Name string `json:"name,required"`
+ Options map[string]interface{} `json:"options,required"`
+ Reasoning bool `json:"reasoning,required"`
+ ReleaseDate string `json:"release_date,required"`
+ Temperature bool `json:"temperature,required"`
+ ToolCall bool `json:"tool_call,required"`
+ JSON modelJSON `json:"-"`
+}
+
+// modelJSON contains the JSON metadata for the struct [Model]
+type modelJSON struct {
+ ID apijson.Field
+ Attachment apijson.Field
+ Cost apijson.Field
+ Limit apijson.Field
+ Name apijson.Field
+ Options apijson.Field
+ Reasoning apijson.Field
+ ReleaseDate apijson.Field
+ Temperature apijson.Field
+ ToolCall apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Model) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modelJSON) RawJSON() string {
+ return r.raw
+}
+
+type ModelCost struct {
+ Input float64 `json:"input,required"`
+ Output float64 `json:"output,required"`
+ CacheRead float64 `json:"cache_read"`
+ CacheWrite float64 `json:"cache_write"`
+ JSON modelCostJSON `json:"-"`
+}
+
+// modelCostJSON contains the JSON metadata for the struct [ModelCost]
+type modelCostJSON struct {
+ Input apijson.Field
+ Output apijson.Field
+ CacheRead apijson.Field
+ CacheWrite apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ModelCost) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modelCostJSON) RawJSON() string {
+ return r.raw
+}
+
+type ModelLimit struct {
+ Context float64 `json:"context,required"`
+ Output float64 `json:"output,required"`
+ JSON modelLimitJSON `json:"-"`
+}
+
+// modelLimitJSON contains the JSON metadata for the struct [ModelLimit]
+type modelLimitJSON struct {
+ Context apijson.Field
+ Output apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ModelLimit) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modelLimitJSON) RawJSON() string {
+ return r.raw
+}
+
+type Provider struct {
+ ID string `json:"id,required"`
+ Env []string `json:"env,required"`
+ Models map[string]Model `json:"models,required"`
+ Name string `json:"name,required"`
+ API string `json:"api"`
+ Npm string `json:"npm"`
+ JSON providerJSON `json:"-"`
+}
+
+// providerJSON contains the JSON metadata for the struct [Provider]
+type providerJSON struct {
+ ID apijson.Field
+ Env apijson.Field
+ Models apijson.Field
+ Name apijson.Field
+ API apijson.Field
+ Npm apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Provider) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r providerJSON) RawJSON() string {
+ return r.raw
+}
+
+type AppProvidersResponse struct {
+ Default map[string]string `json:"default,required"`
+ Providers []Provider `json:"providers,required"`
+ JSON appProvidersResponseJSON `json:"-"`
+}
+
+// appProvidersResponseJSON contains the JSON metadata for the struct
+// [AppProvidersResponse]
+type appProvidersResponseJSON struct {
+ Default apijson.Field
+ Providers apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AppProvidersResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r appProvidersResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type AppLogParams struct {
+ // Log level
+ Level param.Field[AppLogParamsLevel] `json:"level,required"`
+ // Log message
+ Message param.Field[string] `json:"message,required"`
+ // Service name for the log entry
+ Service param.Field[string] `json:"service,required"`
+ // Additional metadata for the log entry
+ Extra param.Field[map[string]interface{}] `json:"extra"`
+}
+
+func (r AppLogParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+// Log level
+type AppLogParamsLevel string
+
+const (
+ AppLogParamsLevelDebug AppLogParamsLevel = "debug"
+ AppLogParamsLevelInfo AppLogParamsLevel = "info"
+ AppLogParamsLevelError AppLogParamsLevel = "error"
+ AppLogParamsLevelWarn AppLogParamsLevel = "warn"
+)
+
+func (r AppLogParamsLevel) IsKnown() bool {
+ switch r {
+ case AppLogParamsLevelDebug, AppLogParamsLevelInfo, AppLogParamsLevelError, AppLogParamsLevelWarn:
+ return true
+ }
+ return false
+}
diff --git a/packages/sdk/go/app_test.go b/packages/sdk/go/app_test.go
new file mode 100644
index 000000000..16bb8ff88
--- /dev/null
+++ b/packages/sdk/go/app_test.go
@@ -0,0 +1,131 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestAppGet(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Get(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestAppInit(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Init(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestAppLogWithOptionalParams(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Log(context.TODO(), opencode.AppLogParams{
+ Level: opencode.F(opencode.AppLogParamsLevelDebug),
+ Message: opencode.F("message"),
+ Service: opencode.F("service"),
+ Extra: opencode.F(map[string]interface{}{
+ "foo": "bar",
+ }),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestAppModes(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Modes(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestAppProviders(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Providers(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/client.go b/packages/sdk/go/client.go
new file mode 100644
index 000000000..6baf21a8f
--- /dev/null
+++ b/packages/sdk/go/client.go
@@ -0,0 +1,125 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+ "os"
+
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+// Client creates a struct with services and top level methods that help with
+// interacting with the opencode API. You should not instantiate this client
+// directly, and instead use the [NewClient] method instead.
+type Client struct {
+ Options []option.RequestOption
+ Event *EventService
+ App *AppService
+ Find *FindService
+ File *FileService
+ Config *ConfigService
+ Session *SessionService
+ Tui *TuiService
+}
+
+// DefaultClientOptions read from the environment (OPENCODE_BASE_URL). This should
+// be used to initialize new clients.
+func DefaultClientOptions() []option.RequestOption {
+ defaults := []option.RequestOption{option.WithEnvironmentProduction()}
+ if o, ok := os.LookupEnv("OPENCODE_BASE_URL"); ok {
+ defaults = append(defaults, option.WithBaseURL(o))
+ }
+ return defaults
+}
+
+// NewClient generates a new client with the default option read from the
+// environment (OPENCODE_BASE_URL). The option passed in as arguments are applied
+// after these default arguments, and all option will be passed down to the
+// services and requests that this client makes.
+func NewClient(opts ...option.RequestOption) (r *Client) {
+ opts = append(DefaultClientOptions(), opts...)
+
+ r = &Client{Options: opts}
+
+ r.Event = NewEventService(opts...)
+ r.App = NewAppService(opts...)
+ r.Find = NewFindService(opts...)
+ r.File = NewFileService(opts...)
+ r.Config = NewConfigService(opts...)
+ r.Session = NewSessionService(opts...)
+ r.Tui = NewTuiService(opts...)
+
+ return
+}
+
+// Execute makes a request with the given context, method, URL, request params,
+// response, and request options. This is useful for hitting undocumented endpoints
+// while retaining the base URL, auth, retries, and other options from the client.
+//
+// If a byte slice or an [io.Reader] is supplied to params, it will be used as-is
+// for the request body.
+//
+// The params is by default serialized into the body using [encoding/json]. If your
+// type implements a MarshalJSON function, it will be used instead to serialize the
+// request. If a URLQuery method is implemented, the returned [url.Values] will be
+// used as query strings to the url.
+//
+// If your params struct uses [param.Field], you must provide either [MarshalJSON],
+// [URLQuery], and/or [MarshalForm] functions. It is undefined behavior to use a
+// struct uses [param.Field] without specifying how it is serialized.
+//
+// Any "…Params" object defined in this library can be used as the request
+// argument. Note that 'path' arguments will not be forwarded into the url.
+//
+// The response body will be deserialized into the res variable, depending on its
+// type:
+//
+// - A pointer to a [*http.Response] is populated by the raw response.
+// - A pointer to a byte array will be populated with the contents of the request
+// body.
+// - A pointer to any other type uses this library's default JSON decoding, which
+// respects UnmarshalJSON if it is defined on the type.
+// - A nil value will not read the response body.
+//
+// For even greater flexibility, see [option.WithResponseInto] and
+// [option.WithResponseBodyInto].
+func (r *Client) Execute(ctx context.Context, method string, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ opts = append(r.Options, opts...)
+ return requestconfig.ExecuteNewRequest(ctx, method, path, params, res, opts...)
+}
+
+// Get makes a GET request with the given URL, params, and optionally deserializes
+// to a response. See [Execute] documentation on the params and response.
+func (r *Client) Get(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ return r.Execute(ctx, http.MethodGet, path, params, res, opts...)
+}
+
+// Post makes a POST request with the given URL, params, and optionally
+// deserializes to a response. See [Execute] documentation on the params and
+// response.
+func (r *Client) Post(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ return r.Execute(ctx, http.MethodPost, path, params, res, opts...)
+}
+
+// Put makes a PUT request with the given URL, params, and optionally deserializes
+// to a response. See [Execute] documentation on the params and response.
+func (r *Client) Put(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ return r.Execute(ctx, http.MethodPut, path, params, res, opts...)
+}
+
+// Patch makes a PATCH request with the given URL, params, and optionally
+// deserializes to a response. See [Execute] documentation on the params and
+// response.
+func (r *Client) Patch(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ return r.Execute(ctx, http.MethodPatch, path, params, res, opts...)
+}
+
+// Delete makes a DELETE request with the given URL, params, and optionally
+// deserializes to a response. See [Execute] documentation on the params and
+// response.
+func (r *Client) Delete(ctx context.Context, path string, params interface{}, res interface{}, opts ...option.RequestOption) error {
+ return r.Execute(ctx, http.MethodDelete, path, params, res, opts...)
+}
diff --git a/packages/sdk/go/client_test.go b/packages/sdk/go/client_test.go
new file mode 100644
index 000000000..0f5b8205d
--- /dev/null
+++ b/packages/sdk/go/client_test.go
@@ -0,0 +1,332 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "net/http"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+type closureTransport struct {
+ fn func(req *http.Request) (*http.Response, error)
+}
+
+func (t *closureTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ return t.fn(req)
+}
+
+func TestUserAgentHeader(t *testing.T) {
+ var userAgent string
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ userAgent = req.Header.Get("User-Agent")
+ return &http.Response{
+ StatusCode: http.StatusOK,
+ }, nil
+ },
+ },
+ }),
+ )
+ client.Session.List(context.Background())
+ if userAgent != fmt.Sprintf("Opencode/Go %s", internal.PackageVersion) {
+ t.Errorf("Expected User-Agent to be correct, but got: %#v", userAgent)
+ }
+}
+
+func TestRetryAfter(t *testing.T) {
+ retryCountHeaders := make([]string, 0)
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ retryCountHeaders = append(retryCountHeaders, req.Header.Get("X-Stainless-Retry-Count"))
+ return &http.Response{
+ StatusCode: http.StatusTooManyRequests,
+ Header: http.Header{
+ http.CanonicalHeaderKey("Retry-After"): []string{"0.1"},
+ },
+ }, nil
+ },
+ },
+ }),
+ )
+ _, err := client.Session.List(context.Background())
+ if err == nil {
+ t.Error("Expected there to be a cancel error")
+ }
+
+ attempts := len(retryCountHeaders)
+ if attempts != 3 {
+ t.Errorf("Expected %d attempts, got %d", 3, attempts)
+ }
+
+ expectedRetryCountHeaders := []string{"0", "1", "2"}
+ if !reflect.DeepEqual(retryCountHeaders, expectedRetryCountHeaders) {
+ t.Errorf("Expected %v retry count headers, got %v", expectedRetryCountHeaders, retryCountHeaders)
+ }
+}
+
+func TestDeleteRetryCountHeader(t *testing.T) {
+ retryCountHeaders := make([]string, 0)
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ retryCountHeaders = append(retryCountHeaders, req.Header.Get("X-Stainless-Retry-Count"))
+ return &http.Response{
+ StatusCode: http.StatusTooManyRequests,
+ Header: http.Header{
+ http.CanonicalHeaderKey("Retry-After"): []string{"0.1"},
+ },
+ }, nil
+ },
+ },
+ }),
+ option.WithHeaderDel("X-Stainless-Retry-Count"),
+ )
+ _, err := client.Session.List(context.Background())
+ if err == nil {
+ t.Error("Expected there to be a cancel error")
+ }
+
+ expectedRetryCountHeaders := []string{"", "", ""}
+ if !reflect.DeepEqual(retryCountHeaders, expectedRetryCountHeaders) {
+ t.Errorf("Expected %v retry count headers, got %v", expectedRetryCountHeaders, retryCountHeaders)
+ }
+}
+
+func TestOverwriteRetryCountHeader(t *testing.T) {
+ retryCountHeaders := make([]string, 0)
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ retryCountHeaders = append(retryCountHeaders, req.Header.Get("X-Stainless-Retry-Count"))
+ return &http.Response{
+ StatusCode: http.StatusTooManyRequests,
+ Header: http.Header{
+ http.CanonicalHeaderKey("Retry-After"): []string{"0.1"},
+ },
+ }, nil
+ },
+ },
+ }),
+ option.WithHeader("X-Stainless-Retry-Count", "42"),
+ )
+ _, err := client.Session.List(context.Background())
+ if err == nil {
+ t.Error("Expected there to be a cancel error")
+ }
+
+ expectedRetryCountHeaders := []string{"42", "42", "42"}
+ if !reflect.DeepEqual(retryCountHeaders, expectedRetryCountHeaders) {
+ t.Errorf("Expected %v retry count headers, got %v", expectedRetryCountHeaders, retryCountHeaders)
+ }
+}
+
+func TestRetryAfterMs(t *testing.T) {
+ attempts := 0
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ attempts++
+ return &http.Response{
+ StatusCode: http.StatusTooManyRequests,
+ Header: http.Header{
+ http.CanonicalHeaderKey("Retry-After-Ms"): []string{"100"},
+ },
+ }, nil
+ },
+ },
+ }),
+ )
+ _, err := client.Session.List(context.Background())
+ if err == nil {
+ t.Error("Expected there to be a cancel error")
+ }
+ if want := 3; attempts != want {
+ t.Errorf("Expected %d attempts, got %d", want, attempts)
+ }
+}
+
+func TestContextCancel(t *testing.T) {
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ <-req.Context().Done()
+ return nil, req.Context().Err()
+ },
+ },
+ }),
+ )
+ cancelCtx, cancel := context.WithCancel(context.Background())
+ cancel()
+ _, err := client.Session.List(cancelCtx)
+ if err == nil {
+ t.Error("Expected there to be a cancel error")
+ }
+}
+
+func TestContextCancelDelay(t *testing.T) {
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ <-req.Context().Done()
+ return nil, req.Context().Err()
+ },
+ },
+ }),
+ )
+ cancelCtx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond)
+ defer cancel()
+ _, err := client.Session.List(cancelCtx)
+ if err == nil {
+ t.Error("expected there to be a cancel error")
+ }
+}
+
+func TestContextDeadline(t *testing.T) {
+ testTimeout := time.After(3 * time.Second)
+ testDone := make(chan struct{})
+
+ deadline := time.Now().Add(100 * time.Millisecond)
+ deadlineCtx, cancel := context.WithDeadline(context.Background(), deadline)
+ defer cancel()
+
+ go func() {
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ <-req.Context().Done()
+ return nil, req.Context().Err()
+ },
+ },
+ }),
+ )
+ _, err := client.Session.List(deadlineCtx)
+ if err == nil {
+ t.Error("expected there to be a deadline error")
+ }
+ close(testDone)
+ }()
+
+ select {
+ case <-testTimeout:
+ t.Fatal("client didn't finish in time")
+ case <-testDone:
+ if diff := time.Since(deadline); diff < -30*time.Millisecond || 30*time.Millisecond < diff {
+ t.Fatalf("client did not return within 30ms of context deadline, got %s", diff)
+ }
+ }
+}
+
+func TestContextDeadlineStreaming(t *testing.T) {
+ testTimeout := time.After(3 * time.Second)
+ testDone := make(chan struct{})
+
+ deadline := time.Now().Add(100 * time.Millisecond)
+ deadlineCtx, cancel := context.WithDeadline(context.Background(), deadline)
+ defer cancel()
+
+ go func() {
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ return &http.Response{
+ StatusCode: 200,
+ Status: "200 OK",
+ Body: io.NopCloser(
+ io.Reader(readerFunc(func([]byte) (int, error) {
+ <-req.Context().Done()
+ return 0, req.Context().Err()
+ })),
+ ),
+ }, nil
+ },
+ },
+ }),
+ )
+ stream := client.Event.ListStreaming(deadlineCtx)
+ for stream.Next() {
+ _ = stream.Current()
+ }
+ if stream.Err() == nil {
+ t.Error("expected there to be a deadline error")
+ }
+ close(testDone)
+ }()
+
+ select {
+ case <-testTimeout:
+ t.Fatal("client didn't finish in time")
+ case <-testDone:
+ if diff := time.Since(deadline); diff < -30*time.Millisecond || 30*time.Millisecond < diff {
+ t.Fatalf("client did not return within 30ms of context deadline, got %s", diff)
+ }
+ }
+}
+
+func TestContextDeadlineStreamingWithRequestTimeout(t *testing.T) {
+ testTimeout := time.After(3 * time.Second)
+ testDone := make(chan struct{})
+ deadline := time.Now().Add(100 * time.Millisecond)
+
+ go func() {
+ client := opencode.NewClient(
+ option.WithHTTPClient(&http.Client{
+ Transport: &closureTransport{
+ fn: func(req *http.Request) (*http.Response, error) {
+ return &http.Response{
+ StatusCode: 200,
+ Status: "200 OK",
+ Body: io.NopCloser(
+ io.Reader(readerFunc(func([]byte) (int, error) {
+ <-req.Context().Done()
+ return 0, req.Context().Err()
+ })),
+ ),
+ }, nil
+ },
+ },
+ }),
+ )
+ stream := client.Event.ListStreaming(context.Background(), option.WithRequestTimeout((100 * time.Millisecond)))
+ for stream.Next() {
+ _ = stream.Current()
+ }
+ if stream.Err() == nil {
+ t.Error("expected there to be a deadline error")
+ }
+ close(testDone)
+ }()
+
+ select {
+ case <-testTimeout:
+ t.Fatal("client didn't finish in time")
+ case <-testDone:
+ if diff := time.Since(deadline); diff < -30*time.Millisecond || 30*time.Millisecond < diff {
+ t.Fatalf("client did not return within 30ms of context deadline, got %s", diff)
+ }
+ }
+}
+
+type readerFunc func([]byte) (int, error)
+
+func (f readerFunc) Read(p []byte) (int, error) { return f(p) }
+func (f readerFunc) Close() error { return nil }
diff --git a/packages/sdk/go/config.go b/packages/sdk/go/config.go
new file mode 100644
index 000000000..5fcfd1edc
--- /dev/null
+++ b/packages/sdk/go/config.go
@@ -0,0 +1,887 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+ "github.com/tidwall/gjson"
+)
+
+// ConfigService contains methods and other services that help with interacting
+// with the opencode 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 [NewConfigService] method instead.
+type ConfigService struct {
+ Options []option.RequestOption
+}
+
+// NewConfigService 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 NewConfigService(opts ...option.RequestOption) (r *ConfigService) {
+ r = &ConfigService{}
+ r.Options = opts
+ return
+}
+
+// Get config info
+func (r *ConfigService) Get(ctx context.Context, opts ...option.RequestOption) (res *Config, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "config"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+type Config struct {
+ // JSON schema reference for configuration validation
+ Schema string `json:"$schema"`
+ // Modes configuration, see https://opencode.ai/docs/modes
+ Agent ConfigAgent `json:"agent"`
+ // @deprecated Use 'share' field instead. Share newly created sessions
+ // automatically
+ Autoshare bool `json:"autoshare"`
+ // Automatically update to the latest version
+ Autoupdate bool `json:"autoupdate"`
+ // Disable providers that are loaded automatically
+ DisabledProviders []string `json:"disabled_providers"`
+ Experimental ConfigExperimental `json:"experimental"`
+ // Additional instruction files or patterns to include
+ Instructions []string `json:"instructions"`
+ // Custom keybind configurations
+ Keybinds KeybindsConfig `json:"keybinds"`
+ // @deprecated Always uses stretch layout.
+ Layout ConfigLayout `json:"layout"`
+ // MCP (Model Context Protocol) server configurations
+ Mcp map[string]ConfigMcp `json:"mcp"`
+ // Modes configuration, see https://opencode.ai/docs/modes
+ Mode ConfigMode `json:"mode"`
+ // Model to use in the format of provider/model, eg anthropic/claude-2
+ Model string `json:"model"`
+ Permission ConfigPermission `json:"permission"`
+ // Custom provider configurations and model overrides
+ Provider map[string]ConfigProvider `json:"provider"`
+ // Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
+ // enables automatic sharing, 'disabled' disables all sharing
+ Share ConfigShare `json:"share"`
+ // Small model to use for tasks like summarization and title generation in the
+ // format of provider/model
+ SmallModel string `json:"small_model"`
+ // Theme name to use for the interface
+ Theme string `json:"theme"`
+ // Custom username to display in conversations instead of system username
+ Username string `json:"username"`
+ JSON configJSON `json:"-"`
+}
+
+// configJSON contains the JSON metadata for the struct [Config]
+type configJSON struct {
+ Schema apijson.Field
+ Agent apijson.Field
+ Autoshare apijson.Field
+ Autoupdate apijson.Field
+ DisabledProviders apijson.Field
+ Experimental apijson.Field
+ Instructions apijson.Field
+ Keybinds apijson.Field
+ Layout apijson.Field
+ Mcp apijson.Field
+ Mode apijson.Field
+ Model apijson.Field
+ Permission apijson.Field
+ Provider apijson.Field
+ Share apijson.Field
+ SmallModel apijson.Field
+ Theme apijson.Field
+ Username apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Config) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configJSON) RawJSON() string {
+ return r.raw
+}
+
+// Modes configuration, see https://opencode.ai/docs/modes
+type ConfigAgent struct {
+ General ConfigAgentGeneral `json:"general"`
+ ExtraFields map[string]ConfigAgent `json:"-,extras"`
+ JSON configAgentJSON `json:"-"`
+}
+
+// configAgentJSON contains the JSON metadata for the struct [ConfigAgent]
+type configAgentJSON struct {
+ General apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigAgent) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configAgentJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigAgentGeneral struct {
+ Description string `json:"description,required"`
+ JSON configAgentGeneralJSON `json:"-"`
+ ModeConfig
+}
+
+// configAgentGeneralJSON contains the JSON metadata for the struct
+// [ConfigAgentGeneral]
+type configAgentGeneralJSON struct {
+ Description apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigAgentGeneral) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configAgentGeneralJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigExperimental struct {
+ Hook ConfigExperimentalHook `json:"hook"`
+ JSON configExperimentalJSON `json:"-"`
+}
+
+// configExperimentalJSON contains the JSON metadata for the struct
+// [ConfigExperimental]
+type configExperimentalJSON struct {
+ Hook apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigExperimental) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configExperimentalJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigExperimentalHook struct {
+ FileEdited map[string][]ConfigExperimentalHookFileEdited `json:"file_edited"`
+ SessionCompleted []ConfigExperimentalHookSessionCompleted `json:"session_completed"`
+ JSON configExperimentalHookJSON `json:"-"`
+}
+
+// configExperimentalHookJSON contains the JSON metadata for the struct
+// [ConfigExperimentalHook]
+type configExperimentalHookJSON struct {
+ FileEdited apijson.Field
+ SessionCompleted apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigExperimentalHook) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configExperimentalHookJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigExperimentalHookFileEdited struct {
+ Command []string `json:"command,required"`
+ Environment map[string]string `json:"environment"`
+ JSON configExperimentalHookFileEditedJSON `json:"-"`
+}
+
+// configExperimentalHookFileEditedJSON contains the JSON metadata for the struct
+// [ConfigExperimentalHookFileEdited]
+type configExperimentalHookFileEditedJSON struct {
+ Command apijson.Field
+ Environment apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigExperimentalHookFileEdited) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configExperimentalHookFileEditedJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigExperimentalHookSessionCompleted struct {
+ Command []string `json:"command,required"`
+ Environment map[string]string `json:"environment"`
+ JSON configExperimentalHookSessionCompletedJSON `json:"-"`
+}
+
+// configExperimentalHookSessionCompletedJSON contains the JSON metadata for the
+// struct [ConfigExperimentalHookSessionCompleted]
+type configExperimentalHookSessionCompletedJSON struct {
+ Command apijson.Field
+ Environment apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigExperimentalHookSessionCompleted) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configExperimentalHookSessionCompletedJSON) RawJSON() string {
+ return r.raw
+}
+
+// @deprecated Always uses stretch layout.
+type ConfigLayout string
+
+const (
+ ConfigLayoutAuto ConfigLayout = "auto"
+ ConfigLayoutStretch ConfigLayout = "stretch"
+)
+
+func (r ConfigLayout) IsKnown() bool {
+ switch r {
+ case ConfigLayoutAuto, ConfigLayoutStretch:
+ return true
+ }
+ return false
+}
+
+type ConfigMcp struct {
+ // Type of MCP server connection
+ Type ConfigMcpType `json:"type,required"`
+ // This field can have the runtime type of [[]string].
+ Command interface{} `json:"command"`
+ // Enable or disable the MCP server on startup
+ Enabled bool `json:"enabled"`
+ // This field can have the runtime type of [map[string]string].
+ Environment interface{} `json:"environment"`
+ // This field can have the runtime type of [map[string]string].
+ Headers interface{} `json:"headers"`
+ // URL of the remote MCP server
+ URL string `json:"url"`
+ JSON configMcpJSON `json:"-"`
+ union ConfigMcpUnion
+}
+
+// configMcpJSON contains the JSON metadata for the struct [ConfigMcp]
+type configMcpJSON struct {
+ Type apijson.Field
+ Command apijson.Field
+ Enabled apijson.Field
+ Environment apijson.Field
+ Headers apijson.Field
+ URL apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r configMcpJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *ConfigMcp) UnmarshalJSON(data []byte) (err error) {
+ *r = ConfigMcp{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [ConfigMcpUnion] interface which you can cast to the specific
+// types for more type safety.
+//
+// Possible runtime types of the union are [McpLocalConfig], [McpRemoteConfig].
+func (r ConfigMcp) AsUnion() ConfigMcpUnion {
+ return r.union
+}
+
+// Union satisfied by [McpLocalConfig] or [McpRemoteConfig].
+type ConfigMcpUnion interface {
+ implementsConfigMcp()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*ConfigMcpUnion)(nil)).Elem(),
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(McpLocalConfig{}),
+ DiscriminatorValue: "local",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(McpRemoteConfig{}),
+ DiscriminatorValue: "remote",
+ },
+ )
+}
+
+// Type of MCP server connection
+type ConfigMcpType string
+
+const (
+ ConfigMcpTypeLocal ConfigMcpType = "local"
+ ConfigMcpTypeRemote ConfigMcpType = "remote"
+)
+
+func (r ConfigMcpType) IsKnown() bool {
+ switch r {
+ case ConfigMcpTypeLocal, ConfigMcpTypeRemote:
+ return true
+ }
+ return false
+}
+
+// Modes configuration, see https://opencode.ai/docs/modes
+type ConfigMode struct {
+ Build ModeConfig `json:"build"`
+ Plan ModeConfig `json:"plan"`
+ ExtraFields map[string]ModeConfig `json:"-,extras"`
+ JSON configModeJSON `json:"-"`
+}
+
+// configModeJSON contains the JSON metadata for the struct [ConfigMode]
+type configModeJSON struct {
+ Build apijson.Field
+ Plan apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigMode) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configModeJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigPermission struct {
+ Bash ConfigPermissionBashUnion `json:"bash"`
+ Edit ConfigPermissionEdit `json:"edit"`
+ JSON configPermissionJSON `json:"-"`
+}
+
+// configPermissionJSON contains the JSON metadata for the struct
+// [ConfigPermission]
+type configPermissionJSON struct {
+ Bash apijson.Field
+ Edit apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigPermission) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configPermissionJSON) RawJSON() string {
+ return r.raw
+}
+
+// Union satisfied by [ConfigPermissionBashString] or [ConfigPermissionBashMap].
+type ConfigPermissionBashUnion interface {
+ implementsConfigPermissionBashUnion()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*ConfigPermissionBashUnion)(nil)).Elem(),
+ "",
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(ConfigPermissionBashString("")),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ConfigPermissionBashMap{}),
+ },
+ )
+}
+
+type ConfigPermissionBashString string
+
+const (
+ ConfigPermissionBashStringAsk ConfigPermissionBashString = "ask"
+ ConfigPermissionBashStringAllow ConfigPermissionBashString = "allow"
+)
+
+func (r ConfigPermissionBashString) IsKnown() bool {
+ switch r {
+ case ConfigPermissionBashStringAsk, ConfigPermissionBashStringAllow:
+ return true
+ }
+ return false
+}
+
+func (r ConfigPermissionBashString) implementsConfigPermissionBashUnion() {}
+
+type ConfigPermissionBashMap map[string]ConfigPermissionBashMapItem
+
+func (r ConfigPermissionBashMap) implementsConfigPermissionBashUnion() {}
+
+type ConfigPermissionBashMapItem string
+
+const (
+ ConfigPermissionBashMapAsk ConfigPermissionBashMapItem = "ask"
+ ConfigPermissionBashMapAllow ConfigPermissionBashMapItem = "allow"
+)
+
+func (r ConfigPermissionBashMapItem) IsKnown() bool {
+ switch r {
+ case ConfigPermissionBashMapAsk, ConfigPermissionBashMapAllow:
+ return true
+ }
+ return false
+}
+
+type ConfigPermissionEdit string
+
+const (
+ ConfigPermissionEditAsk ConfigPermissionEdit = "ask"
+ ConfigPermissionEditAllow ConfigPermissionEdit = "allow"
+)
+
+func (r ConfigPermissionEdit) IsKnown() bool {
+ switch r {
+ case ConfigPermissionEditAsk, ConfigPermissionEditAllow:
+ return true
+ }
+ return false
+}
+
+type ConfigProvider struct {
+ Models map[string]ConfigProviderModel `json:"models,required"`
+ ID string `json:"id"`
+ API string `json:"api"`
+ Env []string `json:"env"`
+ Name string `json:"name"`
+ Npm string `json:"npm"`
+ Options ConfigProviderOptions `json:"options"`
+ JSON configProviderJSON `json:"-"`
+}
+
+// configProviderJSON contains the JSON metadata for the struct [ConfigProvider]
+type configProviderJSON struct {
+ Models apijson.Field
+ ID apijson.Field
+ API apijson.Field
+ Env apijson.Field
+ Name apijson.Field
+ Npm apijson.Field
+ Options apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigProvider) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configProviderJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigProviderModel struct {
+ ID string `json:"id"`
+ Attachment bool `json:"attachment"`
+ Cost ConfigProviderModelsCost `json:"cost"`
+ Limit ConfigProviderModelsLimit `json:"limit"`
+ Name string `json:"name"`
+ Options map[string]interface{} `json:"options"`
+ Reasoning bool `json:"reasoning"`
+ ReleaseDate string `json:"release_date"`
+ Temperature bool `json:"temperature"`
+ ToolCall bool `json:"tool_call"`
+ JSON configProviderModelJSON `json:"-"`
+}
+
+// configProviderModelJSON contains the JSON metadata for the struct
+// [ConfigProviderModel]
+type configProviderModelJSON struct {
+ ID apijson.Field
+ Attachment apijson.Field
+ Cost apijson.Field
+ Limit apijson.Field
+ Name apijson.Field
+ Options apijson.Field
+ Reasoning apijson.Field
+ ReleaseDate apijson.Field
+ Temperature apijson.Field
+ ToolCall apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigProviderModel) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configProviderModelJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigProviderModelsCost struct {
+ Input float64 `json:"input,required"`
+ Output float64 `json:"output,required"`
+ CacheRead float64 `json:"cache_read"`
+ CacheWrite float64 `json:"cache_write"`
+ JSON configProviderModelsCostJSON `json:"-"`
+}
+
+// configProviderModelsCostJSON contains the JSON metadata for the struct
+// [ConfigProviderModelsCost]
+type configProviderModelsCostJSON struct {
+ Input apijson.Field
+ Output apijson.Field
+ CacheRead apijson.Field
+ CacheWrite apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigProviderModelsCost) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configProviderModelsCostJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigProviderModelsLimit struct {
+ Context float64 `json:"context,required"`
+ Output float64 `json:"output,required"`
+ JSON configProviderModelsLimitJSON `json:"-"`
+}
+
+// configProviderModelsLimitJSON contains the JSON metadata for the struct
+// [ConfigProviderModelsLimit]
+type configProviderModelsLimitJSON struct {
+ Context apijson.Field
+ Output apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigProviderModelsLimit) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configProviderModelsLimitJSON) RawJSON() string {
+ return r.raw
+}
+
+type ConfigProviderOptions struct {
+ APIKey string `json:"apiKey"`
+ BaseURL string `json:"baseURL"`
+ ExtraFields map[string]interface{} `json:"-,extras"`
+ JSON configProviderOptionsJSON `json:"-"`
+}
+
+// configProviderOptionsJSON contains the JSON metadata for the struct
+// [ConfigProviderOptions]
+type configProviderOptionsJSON struct {
+ APIKey apijson.Field
+ BaseURL apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ConfigProviderOptions) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r configProviderOptionsJSON) RawJSON() string {
+ return r.raw
+}
+
+// Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
+// enables automatic sharing, 'disabled' disables all sharing
+type ConfigShare string
+
+const (
+ ConfigShareManual ConfigShare = "manual"
+ ConfigShareAuto ConfigShare = "auto"
+ ConfigShareDisabled ConfigShare = "disabled"
+)
+
+func (r ConfigShare) IsKnown() bool {
+ switch r {
+ case ConfigShareManual, ConfigShareAuto, ConfigShareDisabled:
+ return true
+ }
+ return false
+}
+
+type KeybindsConfig struct {
+ // Exit the application
+ AppExit string `json:"app_exit,required"`
+ // Show help dialog
+ AppHelp string `json:"app_help,required"`
+ // Open external editor
+ EditorOpen string `json:"editor_open,required"`
+ // Close file
+ FileClose string `json:"file_close,required"`
+ // Split/unified diff
+ FileDiffToggle string `json:"file_diff_toggle,required"`
+ // List files
+ FileList string `json:"file_list,required"`
+ // Search file
+ FileSearch string `json:"file_search,required"`
+ // Clear input field
+ InputClear string `json:"input_clear,required"`
+ // Insert newline in input
+ InputNewline string `json:"input_newline,required"`
+ // Paste from clipboard
+ InputPaste string `json:"input_paste,required"`
+ // Submit input
+ InputSubmit string `json:"input_submit,required"`
+ // Leader key for keybind combinations
+ Leader string `json:"leader,required"`
+ // Copy message
+ MessagesCopy string `json:"messages_copy,required"`
+ // Navigate to first message
+ MessagesFirst string `json:"messages_first,required"`
+ // Scroll messages down by half page
+ MessagesHalfPageDown string `json:"messages_half_page_down,required"`
+ // Scroll messages up by half page
+ MessagesHalfPageUp string `json:"messages_half_page_up,required"`
+ // Navigate to last message
+ MessagesLast string `json:"messages_last,required"`
+ // Toggle layout
+ MessagesLayoutToggle string `json:"messages_layout_toggle,required"`
+ // Navigate to next message
+ MessagesNext string `json:"messages_next,required"`
+ // Scroll messages down by one page
+ MessagesPageDown string `json:"messages_page_down,required"`
+ // Scroll messages up by one page
+ MessagesPageUp string `json:"messages_page_up,required"`
+ // Navigate to previous message
+ MessagesPrevious string `json:"messages_previous,required"`
+ // Redo message
+ MessagesRedo string `json:"messages_redo,required"`
+ // @deprecated use messages_undo. Revert message
+ MessagesRevert string `json:"messages_revert,required"`
+ // Undo message
+ MessagesUndo string `json:"messages_undo,required"`
+ // List available models
+ ModelList string `json:"model_list,required"`
+ // Create/update AGENTS.md
+ ProjectInit string `json:"project_init,required"`
+ // Compact the session
+ SessionCompact string `json:"session_compact,required"`
+ // Export session to editor
+ SessionExport string `json:"session_export,required"`
+ // Interrupt current session
+ SessionInterrupt string `json:"session_interrupt,required"`
+ // List all sessions
+ SessionList string `json:"session_list,required"`
+ // Create a new session
+ SessionNew string `json:"session_new,required"`
+ // Share current session
+ SessionShare string `json:"session_share,required"`
+ // Unshare current session
+ SessionUnshare string `json:"session_unshare,required"`
+ // Next mode
+ SwitchMode string `json:"switch_mode,required"`
+ // Previous Mode
+ SwitchModeReverse string `json:"switch_mode_reverse,required"`
+ // List available themes
+ ThemeList string `json:"theme_list,required"`
+ // Toggle tool details
+ ToolDetails string `json:"tool_details,required"`
+ JSON keybindsConfigJSON `json:"-"`
+}
+
+// keybindsConfigJSON contains the JSON metadata for the struct [KeybindsConfig]
+type keybindsConfigJSON struct {
+ AppExit apijson.Field
+ AppHelp apijson.Field
+ EditorOpen apijson.Field
+ FileClose apijson.Field
+ FileDiffToggle apijson.Field
+ FileList apijson.Field
+ FileSearch apijson.Field
+ InputClear apijson.Field
+ InputNewline apijson.Field
+ InputPaste apijson.Field
+ InputSubmit apijson.Field
+ Leader apijson.Field
+ MessagesCopy apijson.Field
+ MessagesFirst apijson.Field
+ MessagesHalfPageDown apijson.Field
+ MessagesHalfPageUp apijson.Field
+ MessagesLast apijson.Field
+ MessagesLayoutToggle apijson.Field
+ MessagesNext apijson.Field
+ MessagesPageDown apijson.Field
+ MessagesPageUp apijson.Field
+ MessagesPrevious apijson.Field
+ MessagesRedo apijson.Field
+ MessagesRevert apijson.Field
+ MessagesUndo apijson.Field
+ ModelList apijson.Field
+ ProjectInit apijson.Field
+ SessionCompact apijson.Field
+ SessionExport apijson.Field
+ SessionInterrupt apijson.Field
+ SessionList apijson.Field
+ SessionNew apijson.Field
+ SessionShare apijson.Field
+ SessionUnshare apijson.Field
+ SwitchMode apijson.Field
+ SwitchModeReverse apijson.Field
+ ThemeList apijson.Field
+ ToolDetails apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *KeybindsConfig) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r keybindsConfigJSON) RawJSON() string {
+ return r.raw
+}
+
+type McpLocalConfig struct {
+ // Command and arguments to run the MCP server
+ Command []string `json:"command,required"`
+ // Type of MCP server connection
+ Type McpLocalConfigType `json:"type,required"`
+ // Enable or disable the MCP server on startup
+ Enabled bool `json:"enabled"`
+ // Environment variables to set when running the MCP server
+ Environment map[string]string `json:"environment"`
+ JSON mcpLocalConfigJSON `json:"-"`
+}
+
+// mcpLocalConfigJSON contains the JSON metadata for the struct [McpLocalConfig]
+type mcpLocalConfigJSON struct {
+ Command apijson.Field
+ Type apijson.Field
+ Enabled apijson.Field
+ Environment apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *McpLocalConfig) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r mcpLocalConfigJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r McpLocalConfig) implementsConfigMcp() {}
+
+// Type of MCP server connection
+type McpLocalConfigType string
+
+const (
+ McpLocalConfigTypeLocal McpLocalConfigType = "local"
+)
+
+func (r McpLocalConfigType) IsKnown() bool {
+ switch r {
+ case McpLocalConfigTypeLocal:
+ return true
+ }
+ return false
+}
+
+type McpRemoteConfig struct {
+ // Type of MCP server connection
+ Type McpRemoteConfigType `json:"type,required"`
+ // URL of the remote MCP server
+ URL string `json:"url,required"`
+ // Enable or disable the MCP server on startup
+ Enabled bool `json:"enabled"`
+ // Headers to send with the request
+ Headers map[string]string `json:"headers"`
+ JSON mcpRemoteConfigJSON `json:"-"`
+}
+
+// mcpRemoteConfigJSON contains the JSON metadata for the struct [McpRemoteConfig]
+type mcpRemoteConfigJSON struct {
+ Type apijson.Field
+ URL apijson.Field
+ Enabled apijson.Field
+ Headers apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *McpRemoteConfig) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r mcpRemoteConfigJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r McpRemoteConfig) implementsConfigMcp() {}
+
+// Type of MCP server connection
+type McpRemoteConfigType string
+
+const (
+ McpRemoteConfigTypeRemote McpRemoteConfigType = "remote"
+)
+
+func (r McpRemoteConfigType) IsKnown() bool {
+ switch r {
+ case McpRemoteConfigTypeRemote:
+ return true
+ }
+ return false
+}
+
+type ModeConfig struct {
+ Disable bool `json:"disable"`
+ Model string `json:"model"`
+ Prompt string `json:"prompt"`
+ Temperature float64 `json:"temperature"`
+ Tools map[string]bool `json:"tools"`
+ JSON modeConfigJSON `json:"-"`
+}
+
+// modeConfigJSON contains the JSON metadata for the struct [ModeConfig]
+type modeConfigJSON struct {
+ Disable apijson.Field
+ Model apijson.Field
+ Prompt apijson.Field
+ Temperature apijson.Field
+ Tools apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ModeConfig) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r modeConfigJSON) RawJSON() string {
+ return r.raw
+}
diff --git a/packages/sdk/go/config_test.go b/packages/sdk/go/config_test.go
new file mode 100644
index 000000000..86e058a9a
--- /dev/null
+++ b/packages/sdk/go/config_test.go
@@ -0,0 +1,36 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestConfigGet(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Config.Get(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/event.go b/packages/sdk/go/event.go
new file mode 100644
index 000000000..5203ab23a
--- /dev/null
+++ b/packages/sdk/go/event.go
@@ -0,0 +1,1373 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+ "github.com/sst/opencode-sdk-go/packages/ssestream"
+ "github.com/sst/opencode-sdk-go/shared"
+ "github.com/tidwall/gjson"
+)
+
+// EventService contains methods and other services that help with interacting with
+// the opencode 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 [NewEventService] method instead.
+type EventService struct {
+ Options []option.RequestOption
+}
+
+// NewEventService 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 NewEventService(opts ...option.RequestOption) (r *EventService) {
+ r = &EventService{}
+ r.Options = opts
+ return
+}
+
+// Get events
+func (r *EventService) ListStreaming(ctx context.Context, opts ...option.RequestOption) (stream *ssestream.Stream[EventListResponse]) {
+ var (
+ raw *http.Response
+ err error
+ )
+ opts = append(r.Options[:], opts...)
+ path := "event"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &raw, opts...)
+ return ssestream.NewStream[EventListResponse](ssestream.NewDecoder(raw), err)
+}
+
+type EventListResponse struct {
+ // This field can have the runtime type of
+ // [EventListResponseEventInstallationUpdatedProperties],
+ // [EventListResponseEventLspClientDiagnosticsProperties],
+ // [EventListResponseEventMessageUpdatedProperties],
+ // [EventListResponseEventMessageRemovedProperties],
+ // [EventListResponseEventMessagePartUpdatedProperties],
+ // [EventListResponseEventMessagePartRemovedProperties],
+ // [EventListResponseEventStorageWriteProperties],
+ // [EventListResponseEventPermissionUpdatedProperties],
+ // [EventListResponseEventFileEditedProperties],
+ // [EventListResponseEventSessionUpdatedProperties],
+ // [EventListResponseEventSessionDeletedProperties],
+ // [EventListResponseEventSessionIdleProperties],
+ // [EventListResponseEventSessionErrorProperties], [interface{}],
+ // [EventListResponseEventFileWatcherUpdatedProperties],
+ // [EventListResponseEventIdeInstalledProperties].
+ Properties interface{} `json:"properties,required"`
+ Type EventListResponseType `json:"type,required"`
+ JSON eventListResponseJSON `json:"-"`
+ union EventListResponseUnion
+}
+
+// eventListResponseJSON contains the JSON metadata for the struct
+// [EventListResponse]
+type eventListResponseJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r eventListResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) {
+ *r = EventListResponse{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [EventListResponseUnion] interface which you can cast to the
+// specific types for more type safety.
+//
+// Possible runtime types of the union are
+// [EventListResponseEventInstallationUpdated],
+// [EventListResponseEventLspClientDiagnostics],
+// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
+// [EventListResponseEventMessagePartUpdated],
+// [EventListResponseEventMessagePartRemoved],
+// [EventListResponseEventStorageWrite], [EventListResponseEventPermissionUpdated],
+// [EventListResponseEventFileEdited], [EventListResponseEventSessionUpdated],
+// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionIdle],
+// [EventListResponseEventSessionError], [EventListResponseEventServerConnected],
+// [EventListResponseEventFileWatcherUpdated],
+// [EventListResponseEventIdeInstalled].
+func (r EventListResponse) AsUnion() EventListResponseUnion {
+ return r.union
+}
+
+// Union satisfied by [EventListResponseEventInstallationUpdated],
+// [EventListResponseEventLspClientDiagnostics],
+// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
+// [EventListResponseEventMessagePartUpdated],
+// [EventListResponseEventMessagePartRemoved],
+// [EventListResponseEventStorageWrite], [EventListResponseEventPermissionUpdated],
+// [EventListResponseEventFileEdited], [EventListResponseEventSessionUpdated],
+// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionIdle],
+// [EventListResponseEventSessionError], [EventListResponseEventServerConnected],
+// [EventListResponseEventFileWatcherUpdated] or
+// [EventListResponseEventIdeInstalled].
+type EventListResponseUnion interface {
+ implementsEventListResponse()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*EventListResponseUnion)(nil)).Elem(),
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventInstallationUpdated{}),
+ DiscriminatorValue: "installation.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventLspClientDiagnostics{}),
+ DiscriminatorValue: "lsp.client.diagnostics",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventMessageUpdated{}),
+ DiscriminatorValue: "message.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventMessageRemoved{}),
+ DiscriminatorValue: "message.removed",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventMessagePartUpdated{}),
+ DiscriminatorValue: "message.part.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventMessagePartRemoved{}),
+ DiscriminatorValue: "message.part.removed",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventStorageWrite{}),
+ DiscriminatorValue: "storage.write",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventPermissionUpdated{}),
+ DiscriminatorValue: "permission.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventFileEdited{}),
+ DiscriminatorValue: "file.edited",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventSessionUpdated{}),
+ DiscriminatorValue: "session.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventSessionDeleted{}),
+ DiscriminatorValue: "session.deleted",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventSessionIdle{}),
+ DiscriminatorValue: "session.idle",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventSessionError{}),
+ DiscriminatorValue: "session.error",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventServerConnected{}),
+ DiscriminatorValue: "server.connected",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}),
+ DiscriminatorValue: "file.watcher.updated",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventIdeInstalled{}),
+ DiscriminatorValue: "ide.installed",
+ },
+ )
+}
+
+type EventListResponseEventInstallationUpdated struct {
+ Properties EventListResponseEventInstallationUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventInstallationUpdatedType `json:"type,required"`
+ JSON eventListResponseEventInstallationUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventInstallationUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventInstallationUpdated]
+type eventListResponseEventInstallationUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventInstallationUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventInstallationUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventInstallationUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventInstallationUpdatedProperties struct {
+ Version string `json:"version,required"`
+ JSON eventListResponseEventInstallationUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventInstallationUpdatedPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventInstallationUpdatedProperties]
+type eventListResponseEventInstallationUpdatedPropertiesJSON struct {
+ Version apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventInstallationUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventInstallationUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventInstallationUpdatedType string
+
+const (
+ EventListResponseEventInstallationUpdatedTypeInstallationUpdated EventListResponseEventInstallationUpdatedType = "installation.updated"
+)
+
+func (r EventListResponseEventInstallationUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventInstallationUpdatedTypeInstallationUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventLspClientDiagnostics struct {
+ Properties EventListResponseEventLspClientDiagnosticsProperties `json:"properties,required"`
+ Type EventListResponseEventLspClientDiagnosticsType `json:"type,required"`
+ JSON eventListResponseEventLspClientDiagnosticsJSON `json:"-"`
+}
+
+// eventListResponseEventLspClientDiagnosticsJSON contains the JSON metadata for
+// the struct [EventListResponseEventLspClientDiagnostics]
+type eventListResponseEventLspClientDiagnosticsJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventLspClientDiagnostics) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventLspClientDiagnosticsJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventLspClientDiagnostics) implementsEventListResponse() {}
+
+type EventListResponseEventLspClientDiagnosticsProperties struct {
+ Path string `json:"path,required"`
+ ServerID string `json:"serverID,required"`
+ JSON eventListResponseEventLspClientDiagnosticsPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventLspClientDiagnosticsPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventLspClientDiagnosticsProperties]
+type eventListResponseEventLspClientDiagnosticsPropertiesJSON struct {
+ Path apijson.Field
+ ServerID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventLspClientDiagnosticsProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventLspClientDiagnosticsPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventLspClientDiagnosticsType string
+
+const (
+ EventListResponseEventLspClientDiagnosticsTypeLspClientDiagnostics EventListResponseEventLspClientDiagnosticsType = "lsp.client.diagnostics"
+)
+
+func (r EventListResponseEventLspClientDiagnosticsType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventLspClientDiagnosticsTypeLspClientDiagnostics:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventMessageUpdated struct {
+ Properties EventListResponseEventMessageUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventMessageUpdatedType `json:"type,required"`
+ JSON eventListResponseEventMessageUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventMessageUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventMessageUpdated]
+type eventListResponseEventMessageUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessageUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessageUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventMessageUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventMessageUpdatedProperties struct {
+ Info Message `json:"info,required"`
+ JSON eventListResponseEventMessageUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventMessageUpdatedPropertiesJSON contains the JSON metadata
+// for the struct [EventListResponseEventMessageUpdatedProperties]
+type eventListResponseEventMessageUpdatedPropertiesJSON struct {
+ Info apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessageUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessageUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventMessageUpdatedType string
+
+const (
+ EventListResponseEventMessageUpdatedTypeMessageUpdated EventListResponseEventMessageUpdatedType = "message.updated"
+)
+
+func (r EventListResponseEventMessageUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventMessageUpdatedTypeMessageUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventMessageRemoved struct {
+ Properties EventListResponseEventMessageRemovedProperties `json:"properties,required"`
+ Type EventListResponseEventMessageRemovedType `json:"type,required"`
+ JSON eventListResponseEventMessageRemovedJSON `json:"-"`
+}
+
+// eventListResponseEventMessageRemovedJSON contains the JSON metadata for the
+// struct [EventListResponseEventMessageRemoved]
+type eventListResponseEventMessageRemovedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessageRemoved) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessageRemovedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventMessageRemoved) implementsEventListResponse() {}
+
+type EventListResponseEventMessageRemovedProperties struct {
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ JSON eventListResponseEventMessageRemovedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventMessageRemovedPropertiesJSON contains the JSON metadata
+// for the struct [EventListResponseEventMessageRemovedProperties]
+type eventListResponseEventMessageRemovedPropertiesJSON struct {
+ MessageID apijson.Field
+ SessionID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessageRemovedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessageRemovedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventMessageRemovedType string
+
+const (
+ EventListResponseEventMessageRemovedTypeMessageRemoved EventListResponseEventMessageRemovedType = "message.removed"
+)
+
+func (r EventListResponseEventMessageRemovedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventMessageRemovedTypeMessageRemoved:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventMessagePartUpdated struct {
+ Properties EventListResponseEventMessagePartUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventMessagePartUpdatedType `json:"type,required"`
+ JSON eventListResponseEventMessagePartUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventMessagePartUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventMessagePartUpdated]
+type eventListResponseEventMessagePartUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessagePartUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessagePartUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventMessagePartUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventMessagePartUpdatedProperties struct {
+ Part Part `json:"part,required"`
+ JSON eventListResponseEventMessagePartUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventMessagePartUpdatedPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventMessagePartUpdatedProperties]
+type eventListResponseEventMessagePartUpdatedPropertiesJSON struct {
+ Part apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessagePartUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessagePartUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventMessagePartUpdatedType string
+
+const (
+ EventListResponseEventMessagePartUpdatedTypeMessagePartUpdated EventListResponseEventMessagePartUpdatedType = "message.part.updated"
+)
+
+func (r EventListResponseEventMessagePartUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventMessagePartUpdatedTypeMessagePartUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventMessagePartRemoved struct {
+ Properties EventListResponseEventMessagePartRemovedProperties `json:"properties,required"`
+ Type EventListResponseEventMessagePartRemovedType `json:"type,required"`
+ JSON eventListResponseEventMessagePartRemovedJSON `json:"-"`
+}
+
+// eventListResponseEventMessagePartRemovedJSON contains the JSON metadata for the
+// struct [EventListResponseEventMessagePartRemoved]
+type eventListResponseEventMessagePartRemovedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessagePartRemoved) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessagePartRemovedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventMessagePartRemoved) implementsEventListResponse() {}
+
+type EventListResponseEventMessagePartRemovedProperties struct {
+ MessageID string `json:"messageID,required"`
+ PartID string `json:"partID,required"`
+ SessionID string `json:"sessionID,required"`
+ JSON eventListResponseEventMessagePartRemovedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventMessagePartRemovedPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventMessagePartRemovedProperties]
+type eventListResponseEventMessagePartRemovedPropertiesJSON struct {
+ MessageID apijson.Field
+ PartID apijson.Field
+ SessionID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventMessagePartRemovedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventMessagePartRemovedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventMessagePartRemovedType string
+
+const (
+ EventListResponseEventMessagePartRemovedTypeMessagePartRemoved EventListResponseEventMessagePartRemovedType = "message.part.removed"
+)
+
+func (r EventListResponseEventMessagePartRemovedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventMessagePartRemovedTypeMessagePartRemoved:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventStorageWrite struct {
+ Properties EventListResponseEventStorageWriteProperties `json:"properties,required"`
+ Type EventListResponseEventStorageWriteType `json:"type,required"`
+ JSON eventListResponseEventStorageWriteJSON `json:"-"`
+}
+
+// eventListResponseEventStorageWriteJSON contains the JSON metadata for the struct
+// [EventListResponseEventStorageWrite]
+type eventListResponseEventStorageWriteJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventStorageWrite) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventStorageWriteJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventStorageWrite) implementsEventListResponse() {}
+
+type EventListResponseEventStorageWriteProperties struct {
+ Key string `json:"key,required"`
+ Content interface{} `json:"content"`
+ JSON eventListResponseEventStorageWritePropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventStorageWritePropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventStorageWriteProperties]
+type eventListResponseEventStorageWritePropertiesJSON struct {
+ Key apijson.Field
+ Content apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventStorageWriteProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventStorageWritePropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventStorageWriteType string
+
+const (
+ EventListResponseEventStorageWriteTypeStorageWrite EventListResponseEventStorageWriteType = "storage.write"
+)
+
+func (r EventListResponseEventStorageWriteType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventStorageWriteTypeStorageWrite:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventPermissionUpdated struct {
+ Properties EventListResponseEventPermissionUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventPermissionUpdatedType `json:"type,required"`
+ JSON eventListResponseEventPermissionUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventPermissionUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventPermissionUpdated]
+type eventListResponseEventPermissionUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventPermissionUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventPermissionUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventPermissionUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventPermissionUpdatedProperties struct {
+ ID string `json:"id,required"`
+ Metadata map[string]interface{} `json:"metadata,required"`
+ SessionID string `json:"sessionID,required"`
+ Time EventListResponseEventPermissionUpdatedPropertiesTime `json:"time,required"`
+ Title string `json:"title,required"`
+ JSON eventListResponseEventPermissionUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventPermissionUpdatedPropertiesJSON contains the JSON metadata
+// for the struct [EventListResponseEventPermissionUpdatedProperties]
+type eventListResponseEventPermissionUpdatedPropertiesJSON struct {
+ ID apijson.Field
+ Metadata apijson.Field
+ SessionID apijson.Field
+ Time apijson.Field
+ Title apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventPermissionUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventPermissionUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventPermissionUpdatedPropertiesTime struct {
+ Created float64 `json:"created,required"`
+ JSON eventListResponseEventPermissionUpdatedPropertiesTimeJSON `json:"-"`
+}
+
+// eventListResponseEventPermissionUpdatedPropertiesTimeJSON contains the JSON
+// metadata for the struct [EventListResponseEventPermissionUpdatedPropertiesTime]
+type eventListResponseEventPermissionUpdatedPropertiesTimeJSON struct {
+ Created apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventPermissionUpdatedPropertiesTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventPermissionUpdatedPropertiesTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventPermissionUpdatedType string
+
+const (
+ EventListResponseEventPermissionUpdatedTypePermissionUpdated EventListResponseEventPermissionUpdatedType = "permission.updated"
+)
+
+func (r EventListResponseEventPermissionUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventPermissionUpdatedTypePermissionUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventFileEdited struct {
+ Properties EventListResponseEventFileEditedProperties `json:"properties,required"`
+ Type EventListResponseEventFileEditedType `json:"type,required"`
+ JSON eventListResponseEventFileEditedJSON `json:"-"`
+}
+
+// eventListResponseEventFileEditedJSON contains the JSON metadata for the struct
+// [EventListResponseEventFileEdited]
+type eventListResponseEventFileEditedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileEdited) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileEditedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventFileEdited) implementsEventListResponse() {}
+
+type EventListResponseEventFileEditedProperties struct {
+ File string `json:"file,required"`
+ JSON eventListResponseEventFileEditedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventFileEditedPropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventFileEditedProperties]
+type eventListResponseEventFileEditedPropertiesJSON struct {
+ File apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileEditedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileEditedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventFileEditedType string
+
+const (
+ EventListResponseEventFileEditedTypeFileEdited EventListResponseEventFileEditedType = "file.edited"
+)
+
+func (r EventListResponseEventFileEditedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventFileEditedTypeFileEdited:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionUpdated struct {
+ Properties EventListResponseEventSessionUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventSessionUpdatedType `json:"type,required"`
+ JSON eventListResponseEventSessionUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventSessionUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventSessionUpdated]
+type eventListResponseEventSessionUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventSessionUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventSessionUpdatedProperties struct {
+ Info Session `json:"info,required"`
+ JSON eventListResponseEventSessionUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventSessionUpdatedPropertiesJSON contains the JSON metadata
+// for the struct [EventListResponseEventSessionUpdatedProperties]
+type eventListResponseEventSessionUpdatedPropertiesJSON struct {
+ Info apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventSessionUpdatedType string
+
+const (
+ EventListResponseEventSessionUpdatedTypeSessionUpdated EventListResponseEventSessionUpdatedType = "session.updated"
+)
+
+func (r EventListResponseEventSessionUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionUpdatedTypeSessionUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionDeleted struct {
+ Properties EventListResponseEventSessionDeletedProperties `json:"properties,required"`
+ Type EventListResponseEventSessionDeletedType `json:"type,required"`
+ JSON eventListResponseEventSessionDeletedJSON `json:"-"`
+}
+
+// eventListResponseEventSessionDeletedJSON contains the JSON metadata for the
+// struct [EventListResponseEventSessionDeleted]
+type eventListResponseEventSessionDeletedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionDeleted) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionDeletedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventSessionDeleted) implementsEventListResponse() {}
+
+type EventListResponseEventSessionDeletedProperties struct {
+ Info Session `json:"info,required"`
+ JSON eventListResponseEventSessionDeletedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventSessionDeletedPropertiesJSON contains the JSON metadata
+// for the struct [EventListResponseEventSessionDeletedProperties]
+type eventListResponseEventSessionDeletedPropertiesJSON struct {
+ Info apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionDeletedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionDeletedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventSessionDeletedType string
+
+const (
+ EventListResponseEventSessionDeletedTypeSessionDeleted EventListResponseEventSessionDeletedType = "session.deleted"
+)
+
+func (r EventListResponseEventSessionDeletedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionDeletedTypeSessionDeleted:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionIdle struct {
+ Properties EventListResponseEventSessionIdleProperties `json:"properties,required"`
+ Type EventListResponseEventSessionIdleType `json:"type,required"`
+ JSON eventListResponseEventSessionIdleJSON `json:"-"`
+}
+
+// eventListResponseEventSessionIdleJSON contains the JSON metadata for the struct
+// [EventListResponseEventSessionIdle]
+type eventListResponseEventSessionIdleJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionIdle) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionIdleJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventSessionIdle) implementsEventListResponse() {}
+
+type EventListResponseEventSessionIdleProperties struct {
+ SessionID string `json:"sessionID,required"`
+ JSON eventListResponseEventSessionIdlePropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventSessionIdlePropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventSessionIdleProperties]
+type eventListResponseEventSessionIdlePropertiesJSON struct {
+ SessionID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionIdleProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionIdlePropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventSessionIdleType string
+
+const (
+ EventListResponseEventSessionIdleTypeSessionIdle EventListResponseEventSessionIdleType = "session.idle"
+)
+
+func (r EventListResponseEventSessionIdleType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionIdleTypeSessionIdle:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionError struct {
+ Properties EventListResponseEventSessionErrorProperties `json:"properties,required"`
+ Type EventListResponseEventSessionErrorType `json:"type,required"`
+ JSON eventListResponseEventSessionErrorJSON `json:"-"`
+}
+
+// eventListResponseEventSessionErrorJSON contains the JSON metadata for the struct
+// [EventListResponseEventSessionError]
+type eventListResponseEventSessionErrorJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventSessionError) implementsEventListResponse() {}
+
+type EventListResponseEventSessionErrorProperties struct {
+ Error EventListResponseEventSessionErrorPropertiesError `json:"error"`
+ SessionID string `json:"sessionID"`
+ JSON eventListResponseEventSessionErrorPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventSessionErrorPropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventSessionErrorProperties]
+type eventListResponseEventSessionErrorPropertiesJSON struct {
+ Error apijson.Field
+ SessionID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionErrorProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionErrorPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventSessionErrorPropertiesError struct {
+ // This field can have the runtime type of [shared.ProviderAuthErrorData],
+ // [shared.UnknownErrorData], [interface{}].
+ Data interface{} `json:"data,required"`
+ Name EventListResponseEventSessionErrorPropertiesErrorName `json:"name,required"`
+ JSON eventListResponseEventSessionErrorPropertiesErrorJSON `json:"-"`
+ union EventListResponseEventSessionErrorPropertiesErrorUnion
+}
+
+// eventListResponseEventSessionErrorPropertiesErrorJSON contains the JSON metadata
+// for the struct [EventListResponseEventSessionErrorPropertiesError]
+type eventListResponseEventSessionErrorPropertiesErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r eventListResponseEventSessionErrorPropertiesErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *EventListResponseEventSessionErrorPropertiesError) UnmarshalJSON(data []byte) (err error) {
+ *r = EventListResponseEventSessionErrorPropertiesError{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [EventListResponseEventSessionErrorPropertiesErrorUnion]
+// interface which you can cast to the specific types for more type safety.
+//
+// Possible runtime types of the union are [shared.ProviderAuthError],
+// [shared.UnknownError],
+// [EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError],
+// [shared.MessageAbortedError].
+func (r EventListResponseEventSessionErrorPropertiesError) AsUnion() EventListResponseEventSessionErrorPropertiesErrorUnion {
+ return r.union
+}
+
+// Union satisfied by [shared.ProviderAuthError], [shared.UnknownError],
+// [EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError] or
+// [shared.MessageAbortedError].
+type EventListResponseEventSessionErrorPropertiesErrorUnion interface {
+ ImplementsEventListResponseEventSessionErrorPropertiesError()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*EventListResponseEventSessionErrorPropertiesErrorUnion)(nil)).Elem(),
+ "name",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.ProviderAuthError{}),
+ DiscriminatorValue: "ProviderAuthError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.UnknownError{}),
+ DiscriminatorValue: "UnknownError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError{}),
+ DiscriminatorValue: "MessageOutputLengthError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.MessageAbortedError{}),
+ DiscriminatorValue: "MessageAbortedError",
+ },
+ )
+}
+
+type EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError struct {
+ Data interface{} `json:"data,required"`
+ Name EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorName `json:"name,required"`
+ JSON eventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorJSON `json:"-"`
+}
+
+// eventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorJSON
+// contains the JSON metadata for the struct
+// [EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError]
+type eventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthError) ImplementsEventListResponseEventSessionErrorPropertiesError() {
+}
+
+type EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorName string
+
+const (
+ EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorNameMessageOutputLengthError EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorName = "MessageOutputLengthError"
+)
+
+func (r EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorName) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionErrorPropertiesErrorMessageOutputLengthErrorNameMessageOutputLengthError:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionErrorPropertiesErrorName string
+
+const (
+ EventListResponseEventSessionErrorPropertiesErrorNameProviderAuthError EventListResponseEventSessionErrorPropertiesErrorName = "ProviderAuthError"
+ EventListResponseEventSessionErrorPropertiesErrorNameUnknownError EventListResponseEventSessionErrorPropertiesErrorName = "UnknownError"
+ EventListResponseEventSessionErrorPropertiesErrorNameMessageOutputLengthError EventListResponseEventSessionErrorPropertiesErrorName = "MessageOutputLengthError"
+ EventListResponseEventSessionErrorPropertiesErrorNameMessageAbortedError EventListResponseEventSessionErrorPropertiesErrorName = "MessageAbortedError"
+)
+
+func (r EventListResponseEventSessionErrorPropertiesErrorName) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionErrorPropertiesErrorNameProviderAuthError, EventListResponseEventSessionErrorPropertiesErrorNameUnknownError, EventListResponseEventSessionErrorPropertiesErrorNameMessageOutputLengthError, EventListResponseEventSessionErrorPropertiesErrorNameMessageAbortedError:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventSessionErrorType string
+
+const (
+ EventListResponseEventSessionErrorTypeSessionError EventListResponseEventSessionErrorType = "session.error"
+)
+
+func (r EventListResponseEventSessionErrorType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventSessionErrorTypeSessionError:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventServerConnected struct {
+ Properties interface{} `json:"properties,required"`
+ Type EventListResponseEventServerConnectedType `json:"type,required"`
+ JSON eventListResponseEventServerConnectedJSON `json:"-"`
+}
+
+// eventListResponseEventServerConnectedJSON contains the JSON metadata for the
+// struct [EventListResponseEventServerConnected]
+type eventListResponseEventServerConnectedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventServerConnected) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventServerConnectedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventServerConnected) implementsEventListResponse() {}
+
+type EventListResponseEventServerConnectedType string
+
+const (
+ EventListResponseEventServerConnectedTypeServerConnected EventListResponseEventServerConnectedType = "server.connected"
+)
+
+func (r EventListResponseEventServerConnectedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventServerConnectedTypeServerConnected:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventFileWatcherUpdated struct {
+ Properties EventListResponseEventFileWatcherUpdatedProperties `json:"properties,required"`
+ Type EventListResponseEventFileWatcherUpdatedType `json:"type,required"`
+ JSON eventListResponseEventFileWatcherUpdatedJSON `json:"-"`
+}
+
+// eventListResponseEventFileWatcherUpdatedJSON contains the JSON metadata for the
+// struct [EventListResponseEventFileWatcherUpdated]
+type eventListResponseEventFileWatcherUpdatedJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileWatcherUpdated) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileWatcherUpdatedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventFileWatcherUpdated) implementsEventListResponse() {}
+
+type EventListResponseEventFileWatcherUpdatedProperties struct {
+ Event EventListResponseEventFileWatcherUpdatedPropertiesEvent `json:"event,required"`
+ File string `json:"file,required"`
+ JSON eventListResponseEventFileWatcherUpdatedPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventFileWatcherUpdatedPropertiesJSON contains the JSON
+// metadata for the struct [EventListResponseEventFileWatcherUpdatedProperties]
+type eventListResponseEventFileWatcherUpdatedPropertiesJSON struct {
+ Event apijson.Field
+ File apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventFileWatcherUpdatedProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventFileWatcherUpdatedPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventFileWatcherUpdatedPropertiesEvent string
+
+const (
+ EventListResponseEventFileWatcherUpdatedPropertiesEventRename EventListResponseEventFileWatcherUpdatedPropertiesEvent = "rename"
+ EventListResponseEventFileWatcherUpdatedPropertiesEventChange EventListResponseEventFileWatcherUpdatedPropertiesEvent = "change"
+)
+
+func (r EventListResponseEventFileWatcherUpdatedPropertiesEvent) IsKnown() bool {
+ switch r {
+ case EventListResponseEventFileWatcherUpdatedPropertiesEventRename, EventListResponseEventFileWatcherUpdatedPropertiesEventChange:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventFileWatcherUpdatedType string
+
+const (
+ EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated EventListResponseEventFileWatcherUpdatedType = "file.watcher.updated"
+)
+
+func (r EventListResponseEventFileWatcherUpdatedType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventFileWatcherUpdatedTypeFileWatcherUpdated:
+ return true
+ }
+ return false
+}
+
+type EventListResponseEventIdeInstalled struct {
+ Properties EventListResponseEventIdeInstalledProperties `json:"properties,required"`
+ Type EventListResponseEventIdeInstalledType `json:"type,required"`
+ JSON eventListResponseEventIdeInstalledJSON `json:"-"`
+}
+
+// eventListResponseEventIdeInstalledJSON contains the JSON metadata for the struct
+// [EventListResponseEventIdeInstalled]
+type eventListResponseEventIdeInstalledJSON struct {
+ Properties apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventIdeInstalled) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventIdeInstalledJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r EventListResponseEventIdeInstalled) implementsEventListResponse() {}
+
+type EventListResponseEventIdeInstalledProperties struct {
+ Ide string `json:"ide,required"`
+ JSON eventListResponseEventIdeInstalledPropertiesJSON `json:"-"`
+}
+
+// eventListResponseEventIdeInstalledPropertiesJSON contains the JSON metadata for
+// the struct [EventListResponseEventIdeInstalledProperties]
+type eventListResponseEventIdeInstalledPropertiesJSON struct {
+ Ide apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *EventListResponseEventIdeInstalledProperties) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r eventListResponseEventIdeInstalledPropertiesJSON) RawJSON() string {
+ return r.raw
+}
+
+type EventListResponseEventIdeInstalledType string
+
+const (
+ EventListResponseEventIdeInstalledTypeIdeInstalled EventListResponseEventIdeInstalledType = "ide.installed"
+)
+
+func (r EventListResponseEventIdeInstalledType) IsKnown() bool {
+ switch r {
+ case EventListResponseEventIdeInstalledTypeIdeInstalled:
+ return true
+ }
+ return false
+}
+
+type EventListResponseType string
+
+const (
+ EventListResponseTypeInstallationUpdated EventListResponseType = "installation.updated"
+ EventListResponseTypeLspClientDiagnostics EventListResponseType = "lsp.client.diagnostics"
+ EventListResponseTypeMessageUpdated EventListResponseType = "message.updated"
+ EventListResponseTypeMessageRemoved EventListResponseType = "message.removed"
+ EventListResponseTypeMessagePartUpdated EventListResponseType = "message.part.updated"
+ EventListResponseTypeMessagePartRemoved EventListResponseType = "message.part.removed"
+ EventListResponseTypeStorageWrite EventListResponseType = "storage.write"
+ EventListResponseTypePermissionUpdated EventListResponseType = "permission.updated"
+ EventListResponseTypeFileEdited EventListResponseType = "file.edited"
+ EventListResponseTypeSessionUpdated EventListResponseType = "session.updated"
+ EventListResponseTypeSessionDeleted EventListResponseType = "session.deleted"
+ EventListResponseTypeSessionIdle EventListResponseType = "session.idle"
+ EventListResponseTypeSessionError EventListResponseType = "session.error"
+ EventListResponseTypeServerConnected EventListResponseType = "server.connected"
+ EventListResponseTypeFileWatcherUpdated EventListResponseType = "file.watcher.updated"
+ EventListResponseTypeIdeInstalled EventListResponseType = "ide.installed"
+)
+
+func (r EventListResponseType) IsKnown() bool {
+ switch r {
+ case EventListResponseTypeInstallationUpdated, EventListResponseTypeLspClientDiagnostics, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeMessagePartRemoved, EventListResponseTypeStorageWrite, EventListResponseTypePermissionUpdated, EventListResponseTypeFileEdited, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeServerConnected, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled:
+ return true
+ }
+ return false
+}
diff --git a/packages/sdk/examples/.keep b/packages/sdk/go/examples/.keep
index 0651c89c0..d8c73e937 100644
--- a/packages/sdk/examples/.keep
+++ b/packages/sdk/go/examples/.keep
@@ -1,4 +1,4 @@
File generated from our OpenAPI spec by Stainless.
This directory can be used to store example files demonstrating usage of this SDK.
-It is ignored by Stainless code generation and its content (other than this keep file) won't be touched.
+It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file
diff --git a/packages/sdk/go/field.go b/packages/sdk/go/field.go
new file mode 100644
index 000000000..56d2f8903
--- /dev/null
+++ b/packages/sdk/go/field.go
@@ -0,0 +1,50 @@
+package opencode
+
+import (
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "io"
+)
+
+// F is a param field helper used to initialize a [param.Field] generic struct.
+// This helps specify null, zero values, and overrides, as well as normal values.
+// You can read more about this in our [README].
+//
+// [README]: https://pkg.go.dev/github.com/sst/opencode-sdk-go#readme-request-fields
+func F[T any](value T) param.Field[T] { return param.Field[T]{Value: value, Present: true} }
+
+// Null is a param field helper which explicitly sends null to the API.
+func Null[T any]() param.Field[T] { return param.Field[T]{Null: true, Present: true} }
+
+// Raw is a param field helper for specifying values for fields when the
+// type you are looking to send is different from the type that is specified in
+// the SDK. For example, if the type of the field is an integer, but you want
+// to send a float, you could do that by setting the corresponding field with
+// Raw[int](0.5).
+func Raw[T any](value any) param.Field[T] { return param.Field[T]{Raw: value, Present: true} }
+
+// Int is a param field helper which helps specify integers. This is
+// particularly helpful when specifying integer constants for fields.
+func Int(value int64) param.Field[int64] { return F(value) }
+
+// String is a param field helper which helps specify strings.
+func String(value string) param.Field[string] { return F(value) }
+
+// Float is a param field helper which helps specify floats.
+func Float(value float64) param.Field[float64] { return F(value) }
+
+// Bool is a param field helper which helps specify bools.
+func Bool(value bool) param.Field[bool] { return F(value) }
+
+// FileParam is a param field helper which helps files with a mime content-type.
+func FileParam(reader io.Reader, filename string, contentType string) param.Field[io.Reader] {
+ return F[io.Reader](&file{reader, filename, contentType})
+}
+
+type file struct {
+ io.Reader
+ name string
+ contentType string
+}
+
+func (f *file) ContentType() string { return f.contentType }
+func (f *file) Filename() string { return f.name }
diff --git a/packages/sdk/go/file.go b/packages/sdk/go/file.go
new file mode 100644
index 000000000..0a8a4b2b6
--- /dev/null
+++ b/packages/sdk/go/file.go
@@ -0,0 +1,142 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+ "net/url"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/apiquery"
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+// FileService contains methods and other services that help with interacting with
+// the opencode 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 [NewFileService] method instead.
+type FileService struct {
+ Options []option.RequestOption
+}
+
+// NewFileService 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 NewFileService(opts ...option.RequestOption) (r *FileService) {
+ r = &FileService{}
+ r.Options = opts
+ return
+}
+
+// Read a file
+func (r *FileService) Read(ctx context.Context, query FileReadParams, opts ...option.RequestOption) (res *FileReadResponse, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "file"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
+ return
+}
+
+// Get file status
+func (r *FileService) Status(ctx context.Context, opts ...option.RequestOption) (res *[]File, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "file/status"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+type File struct {
+ Added int64 `json:"added,required"`
+ Path string `json:"path,required"`
+ Removed int64 `json:"removed,required"`
+ Status FileStatus `json:"status,required"`
+ JSON fileJSON `json:"-"`
+}
+
+// fileJSON contains the JSON metadata for the struct [File]
+type fileJSON struct {
+ Added apijson.Field
+ Path apijson.Field
+ Removed apijson.Field
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *File) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r fileJSON) RawJSON() string {
+ return r.raw
+}
+
+type FileStatus string
+
+const (
+ FileStatusAdded FileStatus = "added"
+ FileStatusDeleted FileStatus = "deleted"
+ FileStatusModified FileStatus = "modified"
+)
+
+func (r FileStatus) IsKnown() bool {
+ switch r {
+ case FileStatusAdded, FileStatusDeleted, FileStatusModified:
+ return true
+ }
+ return false
+}
+
+type FileReadResponse struct {
+ Content string `json:"content,required"`
+ Type FileReadResponseType `json:"type,required"`
+ JSON fileReadResponseJSON `json:"-"`
+}
+
+// fileReadResponseJSON contains the JSON metadata for the struct
+// [FileReadResponse]
+type fileReadResponseJSON struct {
+ Content apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FileReadResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r fileReadResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type FileReadResponseType string
+
+const (
+ FileReadResponseTypeRaw FileReadResponseType = "raw"
+ FileReadResponseTypePatch FileReadResponseType = "patch"
+)
+
+func (r FileReadResponseType) IsKnown() bool {
+ switch r {
+ case FileReadResponseTypeRaw, FileReadResponseTypePatch:
+ return true
+ }
+ return false
+}
+
+type FileReadParams struct {
+ Path param.Field[string] `query:"path,required"`
+}
+
+// URLQuery serializes [FileReadParams]'s query parameters as `url.Values`.
+func (r FileReadParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
diff --git a/packages/sdk/go/file_test.go b/packages/sdk/go/file_test.go
new file mode 100644
index 000000000..60212ea24
--- /dev/null
+++ b/packages/sdk/go/file_test.go
@@ -0,0 +1,60 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestFileRead(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.File.Read(context.TODO(), opencode.FileReadParams{
+ Path: opencode.F("path"),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestFileStatus(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.File.Status(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/find.go b/packages/sdk/go/find.go
new file mode 100644
index 000000000..a993a353f
--- /dev/null
+++ b/packages/sdk/go/find.go
@@ -0,0 +1,326 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+ "net/url"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/apiquery"
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+// FindService contains methods and other services that help with interacting with
+// the opencode 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 [NewFindService] method instead.
+type FindService struct {
+ Options []option.RequestOption
+}
+
+// NewFindService 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 NewFindService(opts ...option.RequestOption) (r *FindService) {
+ r = &FindService{}
+ r.Options = opts
+ return
+}
+
+// Find files
+func (r *FindService) Files(ctx context.Context, query FindFilesParams, opts ...option.RequestOption) (res *[]string, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "find/file"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
+ return
+}
+
+// Find workspace symbols
+func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts ...option.RequestOption) (res *[]Symbol, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "find/symbol"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
+ return
+}
+
+// Find text in files
+func (r *FindService) Text(ctx context.Context, query FindTextParams, opts ...option.RequestOption) (res *[]FindTextResponse, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "find"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
+ return
+}
+
+type Symbol struct {
+ Kind float64 `json:"kind,required"`
+ Location SymbolLocation `json:"location,required"`
+ Name string `json:"name,required"`
+ JSON symbolJSON `json:"-"`
+}
+
+// symbolJSON contains the JSON metadata for the struct [Symbol]
+type symbolJSON struct {
+ Kind apijson.Field
+ Location apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Symbol) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocation struct {
+ Range SymbolLocationRange `json:"range,required"`
+ Uri string `json:"uri,required"`
+ JSON symbolLocationJSON `json:"-"`
+}
+
+// symbolLocationJSON contains the JSON metadata for the struct [SymbolLocation]
+type symbolLocationJSON struct {
+ Range apijson.Field
+ Uri apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocation) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRange struct {
+ End SymbolLocationRangeEnd `json:"end,required"`
+ Start SymbolLocationRangeStart `json:"start,required"`
+ JSON symbolLocationRangeJSON `json:"-"`
+}
+
+// symbolLocationRangeJSON contains the JSON metadata for the struct
+// [SymbolLocationRange]
+type symbolLocationRangeJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRange) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationRangeJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRangeEnd struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolLocationRangeEndJSON `json:"-"`
+}
+
+// symbolLocationRangeEndJSON contains the JSON metadata for the struct
+// [SymbolLocationRangeEnd]
+type symbolLocationRangeEndJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRangeEnd) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationRangeEndJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRangeStart struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolLocationRangeStartJSON `json:"-"`
+}
+
+// symbolLocationRangeStartJSON contains the JSON metadata for the struct
+// [SymbolLocationRangeStart]
+type symbolLocationRangeStartJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRangeStart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationRangeStartJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindTextResponse struct {
+ AbsoluteOffset float64 `json:"absolute_offset,required"`
+ LineNumber float64 `json:"line_number,required"`
+ Lines FindTextResponseLines `json:"lines,required"`
+ Path FindTextResponsePath `json:"path,required"`
+ Submatches []FindTextResponseSubmatch `json:"submatches,required"`
+ JSON findTextResponseJSON `json:"-"`
+}
+
+// findTextResponseJSON contains the JSON metadata for the struct
+// [FindTextResponse]
+type findTextResponseJSON struct {
+ AbsoluteOffset apijson.Field
+ LineNumber apijson.Field
+ Lines apijson.Field
+ Path apijson.Field
+ Submatches apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FindTextResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r findTextResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindTextResponseLines struct {
+ Text string `json:"text,required"`
+ JSON findTextResponseLinesJSON `json:"-"`
+}
+
+// findTextResponseLinesJSON contains the JSON metadata for the struct
+// [FindTextResponseLines]
+type findTextResponseLinesJSON struct {
+ Text apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FindTextResponseLines) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r findTextResponseLinesJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindTextResponsePath struct {
+ Text string `json:"text,required"`
+ JSON findTextResponsePathJSON `json:"-"`
+}
+
+// findTextResponsePathJSON contains the JSON metadata for the struct
+// [FindTextResponsePath]
+type findTextResponsePathJSON struct {
+ Text apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FindTextResponsePath) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r findTextResponsePathJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindTextResponseSubmatch struct {
+ End float64 `json:"end,required"`
+ Match FindTextResponseSubmatchesMatch `json:"match,required"`
+ Start float64 `json:"start,required"`
+ JSON findTextResponseSubmatchJSON `json:"-"`
+}
+
+// findTextResponseSubmatchJSON contains the JSON metadata for the struct
+// [FindTextResponseSubmatch]
+type findTextResponseSubmatchJSON struct {
+ End apijson.Field
+ Match apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FindTextResponseSubmatch) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r findTextResponseSubmatchJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindTextResponseSubmatchesMatch struct {
+ Text string `json:"text,required"`
+ JSON findTextResponseSubmatchesMatchJSON `json:"-"`
+}
+
+// findTextResponseSubmatchesMatchJSON contains the JSON metadata for the struct
+// [FindTextResponseSubmatchesMatch]
+type findTextResponseSubmatchesMatchJSON struct {
+ Text apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FindTextResponseSubmatchesMatch) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r findTextResponseSubmatchesMatchJSON) RawJSON() string {
+ return r.raw
+}
+
+type FindFilesParams struct {
+ Query param.Field[string] `query:"query,required"`
+}
+
+// URLQuery serializes [FindFilesParams]'s query parameters as `url.Values`.
+func (r FindFilesParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type FindSymbolsParams struct {
+ Query param.Field[string] `query:"query,required"`
+}
+
+// URLQuery serializes [FindSymbolsParams]'s query parameters as `url.Values`.
+func (r FindSymbolsParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type FindTextParams struct {
+ Pattern param.Field[string] `query:"pattern,required"`
+}
+
+// URLQuery serializes [FindTextParams]'s query parameters as `url.Values`.
+func (r FindTextParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatComma,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
diff --git a/packages/sdk/go/find_test.go b/packages/sdk/go/find_test.go
new file mode 100644
index 000000000..e2f1caa16
--- /dev/null
+++ b/packages/sdk/go/find_test.go
@@ -0,0 +1,86 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestFindFiles(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Find.Files(context.TODO(), opencode.FindFilesParams{
+ Query: opencode.F("query"),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestFindSymbols(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Find.Symbols(context.TODO(), opencode.FindSymbolsParams{
+ Query: opencode.F("query"),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestFindText(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Find.Text(context.TODO(), opencode.FindTextParams{
+ Pattern: opencode.F("pattern"),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/go.mod b/packages/sdk/go/go.mod
new file mode 100644
index 000000000..2817d3013
--- /dev/null
+++ b/packages/sdk/go/go.mod
@@ -0,0 +1,13 @@
+module github.com/sst/opencode-sdk-go
+
+go 1.21
+
+require (
+ github.com/tidwall/gjson v1.14.4
+ github.com/tidwall/sjson v1.2.5
+)
+
+require (
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.1 // indirect
+)
diff --git a/packages/sdk/go/go.sum b/packages/sdk/go/go.sum
new file mode 100644
index 000000000..a70a5e0a8
--- /dev/null
+++ b/packages/sdk/go/go.sum
@@ -0,0 +1,10 @@
+github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
+github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
+github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
+github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
diff --git a/packages/sdk/go/internal/apierror/apierror.go b/packages/sdk/go/internal/apierror/apierror.go
new file mode 100644
index 000000000..24307fc36
--- /dev/null
+++ b/packages/sdk/go/internal/apierror/apierror.go
@@ -0,0 +1,53 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package apierror
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httputil"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+)
+
+// Error represents an error that originates from the API, i.e. when a request is
+// made and the API returns a response with a HTTP status code. Other errors are
+// not wrapped by this SDK.
+type Error struct {
+ JSON errorJSON `json:"-"`
+ StatusCode int
+ Request *http.Request
+ Response *http.Response
+}
+
+// errorJSON contains the JSON metadata for the struct [Error]
+type errorJSON struct {
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Error) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r errorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *Error) Error() string {
+ // Attempt to re-populate the response body
+ return fmt.Sprintf("%s \"%s\": %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.RawJSON())
+}
+
+func (r *Error) DumpRequest(body bool) []byte {
+ if r.Request.GetBody != nil {
+ r.Request.Body, _ = r.Request.GetBody()
+ }
+ out, _ := httputil.DumpRequestOut(r.Request, body)
+ return out
+}
+
+func (r *Error) DumpResponse(body bool) []byte {
+ out, _ := httputil.DumpResponse(r.Response, body)
+ return out
+}
diff --git a/packages/sdk/go/internal/apiform/encoder.go b/packages/sdk/go/internal/apiform/encoder.go
new file mode 100644
index 000000000..243a1a123
--- /dev/null
+++ b/packages/sdk/go/internal/apiform/encoder.go
@@ -0,0 +1,383 @@
+package apiform
+
+import (
+ "fmt"
+ "io"
+ "mime/multipart"
+ "net/textproto"
+ "path"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/sst/opencode-sdk-go/internal/param"
+)
+
+var encoders sync.Map // map[encoderEntry]encoderFunc
+
+func Marshal(value interface{}, writer *multipart.Writer) error {
+ e := &encoder{dateFormat: time.RFC3339}
+ return e.marshal(value, writer)
+}
+
+func MarshalRoot(value interface{}, writer *multipart.Writer) error {
+ e := &encoder{root: true, dateFormat: time.RFC3339}
+ return e.marshal(value, writer)
+}
+
+type encoder struct {
+ dateFormat string
+ root bool
+}
+
+type encoderFunc func(key string, value reflect.Value, writer *multipart.Writer) error
+
+type encoderField struct {
+ tag parsedStructTag
+ fn encoderFunc
+ idx []int
+}
+
+type encoderEntry struct {
+ reflect.Type
+ dateFormat string
+ root bool
+}
+
+func (e *encoder) marshal(value interface{}, writer *multipart.Writer) error {
+ val := reflect.ValueOf(value)
+ if !val.IsValid() {
+ return nil
+ }
+ typ := val.Type()
+ enc := e.typeEncoder(typ)
+ return enc("", val, writer)
+}
+
+func (e *encoder) typeEncoder(t reflect.Type) encoderFunc {
+ entry := encoderEntry{
+ Type: t,
+ dateFormat: e.dateFormat,
+ root: e.root,
+ }
+
+ if fi, ok := encoders.Load(entry); ok {
+ return fi.(encoderFunc)
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ var (
+ wg sync.WaitGroup
+ f encoderFunc
+ )
+ wg.Add(1)
+ fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(key string, v reflect.Value, writer *multipart.Writer) error {
+ wg.Wait()
+ return f(key, v, writer)
+ }))
+ if loaded {
+ return fi.(encoderFunc)
+ }
+
+ // Compute the real encoder and replace the indirect func with it.
+ f = e.newTypeEncoder(t)
+ wg.Done()
+ encoders.Store(entry, f)
+ return f
+}
+
+func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc {
+ if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
+ return e.newTimeTypeEncoder()
+ }
+ if t.ConvertibleTo(reflect.TypeOf((*io.Reader)(nil)).Elem()) {
+ return e.newReaderTypeEncoder()
+ }
+ e.root = false
+ switch t.Kind() {
+ case reflect.Pointer:
+ inner := t.Elem()
+
+ innerEncoder := e.typeEncoder(inner)
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ if !v.IsValid() || v.IsNil() {
+ return nil
+ }
+ return innerEncoder(key, v.Elem(), writer)
+ }
+ case reflect.Struct:
+ return e.newStructTypeEncoder(t)
+ case reflect.Slice, reflect.Array:
+ return e.newArrayTypeEncoder(t)
+ case reflect.Map:
+ return e.newMapEncoder(t)
+ case reflect.Interface:
+ return e.newInterfaceEncoder()
+ default:
+ return e.newPrimitiveTypeEncoder(t)
+ }
+}
+
+func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc {
+ switch t.Kind() {
+ // Note that we could use `gjson` to encode these types but it would complicate our
+ // code more and this current code shouldn't cause any issues
+ case reflect.String:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, v.String())
+ }
+ case reflect.Bool:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ if v.Bool() {
+ return writer.WriteField(key, "true")
+ }
+ return writer.WriteField(key, "false")
+ }
+ case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, strconv.FormatInt(v.Int(), 10))
+ }
+ case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, strconv.FormatUint(v.Uint(), 10))
+ }
+ case reflect.Float32:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, strconv.FormatFloat(v.Float(), 'f', -1, 32))
+ }
+ case reflect.Float64:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, strconv.FormatFloat(v.Float(), 'f', -1, 64))
+ }
+ default:
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ return fmt.Errorf("unknown type received at primitive encoder: %s", t.String())
+ }
+ }
+}
+
+func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
+ itemEncoder := e.typeEncoder(t.Elem())
+
+ return func(key string, v reflect.Value, writer *multipart.Writer) error {
+ if key != "" {
+ key = key + "."
+ }
+ for i := 0; i < v.Len(); i++ {
+ err := itemEncoder(key+strconv.Itoa(i), v.Index(i), writer)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+}
+
+func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
+ if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) {
+ return e.newFieldTypeEncoder(t)
+ }
+
+ encoderFields := []encoderField{}
+ extraEncoder := (*encoderField)(nil)
+
+ // This helper allows us to recursively collect field encoders into a flat
+ // array. The parameter `index` keeps track of the access patterns necessary
+ // to get to some field.
+ var collectEncoderFields func(r reflect.Type, index []int)
+ collectEncoderFields = func(r reflect.Type, index []int) {
+ for i := 0; i < r.NumField(); i++ {
+ idx := append(index, i)
+ field := t.FieldByIndex(idx)
+ if !field.IsExported() {
+ continue
+ }
+ // If this is an embedded struct, traverse one level deeper to extract
+ // the field and get their encoders as well.
+ if field.Anonymous {
+ collectEncoderFields(field.Type, idx)
+ continue
+ }
+ // If json tag is not present, then we skip, which is intentionally
+ // different behavior from the stdlib.
+ ptag, ok := parseFormStructTag(field)
+ if !ok {
+ continue
+ }
+ // We only want to support unexported field if they're tagged with
+ // `extras` because that field shouldn't be part of the public API. We
+ // also want to only keep the top level extras
+ if ptag.extras && len(index) == 0 {
+ extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx}
+ continue
+ }
+ if ptag.name == "-" {
+ continue
+ }
+
+ dateFormat, ok := parseFormatStructTag(field)
+ oldFormat := e.dateFormat
+ if ok {
+ switch dateFormat {
+ case "date-time":
+ e.dateFormat = time.RFC3339
+ case "date":
+ e.dateFormat = "2006-01-02"
+ }
+ }
+ encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx})
+ e.dateFormat = oldFormat
+ }
+ }
+ collectEncoderFields(t, []int{})
+
+ // Ensure deterministic output by sorting by lexicographic order
+ sort.Slice(encoderFields, func(i, j int) bool {
+ return encoderFields[i].tag.name < encoderFields[j].tag.name
+ })
+
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ if key != "" {
+ key = key + "."
+ }
+
+ for _, ef := range encoderFields {
+ field := value.FieldByIndex(ef.idx)
+ err := ef.fn(key+ef.tag.name, field, writer)
+ if err != nil {
+ return err
+ }
+ }
+
+ if extraEncoder != nil {
+ err := e.encodeMapEntries(key, value.FieldByIndex(extraEncoder.idx), writer)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+}
+
+func (e *encoder) newFieldTypeEncoder(t reflect.Type) encoderFunc {
+ f, _ := t.FieldByName("Value")
+ enc := e.typeEncoder(f.Type)
+
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ present := value.FieldByName("Present")
+ if !present.Bool() {
+ return nil
+ }
+ null := value.FieldByName("Null")
+ if null.Bool() {
+ return nil
+ }
+ raw := value.FieldByName("Raw")
+ if !raw.IsNil() {
+ return e.typeEncoder(raw.Type())(key, raw, writer)
+ }
+ return enc(key, value.FieldByName("Value"), writer)
+ }
+}
+
+func (e *encoder) newTimeTypeEncoder() encoderFunc {
+ format := e.dateFormat
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ return writer.WriteField(key, value.Convert(reflect.TypeOf(time.Time{})).Interface().(time.Time).Format(format))
+ }
+}
+
+func (e encoder) newInterfaceEncoder() encoderFunc {
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ value = value.Elem()
+ if !value.IsValid() {
+ return nil
+ }
+ return e.typeEncoder(value.Type())(key, value, writer)
+ }
+}
+
+var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
+
+func escapeQuotes(s string) string {
+ return quoteEscaper.Replace(s)
+}
+
+func (e *encoder) newReaderTypeEncoder() encoderFunc {
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ reader := value.Convert(reflect.TypeOf((*io.Reader)(nil)).Elem()).Interface().(io.Reader)
+ filename := "anonymous_file"
+ contentType := "application/octet-stream"
+ if named, ok := reader.(interface{ Filename() string }); ok {
+ filename = named.Filename()
+ } else if named, ok := reader.(interface{ Name() string }); ok {
+ filename = path.Base(named.Name())
+ }
+ if typed, ok := reader.(interface{ ContentType() string }); ok {
+ contentType = typed.ContentType()
+ }
+
+ // Below is taken almost 1-for-1 from [multipart.CreateFormFile]
+ h := make(textproto.MIMEHeader)
+ h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes(key), escapeQuotes(filename)))
+ h.Set("Content-Type", contentType)
+ filewriter, err := writer.CreatePart(h)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(filewriter, reader)
+ return err
+ }
+}
+
+// Given a []byte of json (may either be an empty object or an object that already contains entries)
+// encode all of the entries in the map to the json byte array.
+func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipart.Writer) error {
+ type mapPair struct {
+ key string
+ value reflect.Value
+ }
+
+ if key != "" {
+ key = key + "."
+ }
+
+ pairs := []mapPair{}
+
+ iter := v.MapRange()
+ for iter.Next() {
+ if iter.Key().Type().Kind() == reflect.String {
+ pairs = append(pairs, mapPair{key: iter.Key().String(), value: iter.Value()})
+ } else {
+ return fmt.Errorf("cannot encode a map with a non string key")
+ }
+ }
+
+ // Ensure deterministic output
+ sort.Slice(pairs, func(i, j int) bool {
+ return pairs[i].key < pairs[j].key
+ })
+
+ elementEncoder := e.typeEncoder(v.Type().Elem())
+ for _, p := range pairs {
+ err := elementEncoder(key+string(p.key), p.value, writer)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc {
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ return e.encodeMapEntries(key, value, writer)
+ }
+}
diff --git a/packages/sdk/go/internal/apiform/form.go b/packages/sdk/go/internal/apiform/form.go
new file mode 100644
index 000000000..5445116e9
--- /dev/null
+++ b/packages/sdk/go/internal/apiform/form.go
@@ -0,0 +1,5 @@
+package apiform
+
+type Marshaler interface {
+ MarshalMultipart() ([]byte, string, error)
+}
diff --git a/packages/sdk/go/internal/apiform/form_test.go b/packages/sdk/go/internal/apiform/form_test.go
new file mode 100644
index 000000000..39d1460c0
--- /dev/null
+++ b/packages/sdk/go/internal/apiform/form_test.go
@@ -0,0 +1,440 @@
+package apiform
+
+import (
+ "bytes"
+ "mime/multipart"
+ "strings"
+ "testing"
+ "time"
+)
+
+func P[T any](v T) *T { return &v }
+
+type Primitives struct {
+ A bool `form:"a"`
+ B int `form:"b"`
+ C uint `form:"c"`
+ D float64 `form:"d"`
+ E float32 `form:"e"`
+ F []int `form:"f"`
+}
+
+type PrimitivePointers struct {
+ A *bool `form:"a"`
+ B *int `form:"b"`
+ C *uint `form:"c"`
+ D *float64 `form:"d"`
+ E *float32 `form:"e"`
+ F *[]int `form:"f"`
+}
+
+type Slices struct {
+ Slice []Primitives `form:"slices"`
+}
+
+type DateTime struct {
+ Date time.Time `form:"date" format:"date"`
+ DateTime time.Time `form:"date-time" format:"date-time"`
+}
+
+type AdditionalProperties struct {
+ A bool `form:"a"`
+ Extras map[string]interface{} `form:"-,extras"`
+}
+
+type TypedAdditionalProperties struct {
+ A bool `form:"a"`
+ Extras map[string]int `form:"-,extras"`
+}
+
+type EmbeddedStructs struct {
+ AdditionalProperties
+ A *int `form:"number2"`
+ Extras map[string]interface{} `form:"-,extras"`
+}
+
+type Recursive struct {
+ Name string `form:"name"`
+ Child *Recursive `form:"child"`
+}
+
+type UnknownStruct struct {
+ Unknown interface{} `form:"unknown"`
+}
+
+type UnionStruct struct {
+ Union Union `form:"union" format:"date"`
+}
+
+type Union interface {
+ union()
+}
+
+type UnionInteger int64
+
+func (UnionInteger) union() {}
+
+type UnionStructA struct {
+ Type string `form:"type"`
+ A string `form:"a"`
+ B string `form:"b"`
+}
+
+func (UnionStructA) union() {}
+
+type UnionStructB struct {
+ Type string `form:"type"`
+ A string `form:"a"`
+}
+
+func (UnionStructB) union() {}
+
+type UnionTime time.Time
+
+func (UnionTime) union() {}
+
+type ReaderStruct struct {
+}
+
+var tests = map[string]struct {
+ buf string
+ val interface{}
+}{
+ "map_string": {
+ `--xxx
+Content-Disposition: form-data; name="foo"
+
+bar
+--xxx--
+`,
+ map[string]string{"foo": "bar"},
+ },
+
+ "map_interface": {
+ `--xxx
+Content-Disposition: form-data; name="a"
+
+1
+--xxx
+Content-Disposition: form-data; name="b"
+
+str
+--xxx
+Content-Disposition: form-data; name="c"
+
+false
+--xxx--
+`,
+ map[string]interface{}{"a": float64(1), "b": "str", "c": false},
+ },
+
+ "primitive_struct": {
+ `--xxx
+Content-Disposition: form-data; name="a"
+
+false
+--xxx
+Content-Disposition: form-data; name="b"
+
+237628372683
+--xxx
+Content-Disposition: form-data; name="c"
+
+654
+--xxx
+Content-Disposition: form-data; name="d"
+
+9999.43
+--xxx
+Content-Disposition: form-data; name="e"
+
+43.76
+--xxx
+Content-Disposition: form-data; name="f.0"
+
+1
+--xxx
+Content-Disposition: form-data; name="f.1"
+
+2
+--xxx
+Content-Disposition: form-data; name="f.2"
+
+3
+--xxx
+Content-Disposition: form-data; name="f.3"
+
+4
+--xxx--
+`,
+ Primitives{A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ },
+
+ "slices": {
+ `--xxx
+Content-Disposition: form-data; name="slices.0.a"
+
+false
+--xxx
+Content-Disposition: form-data; name="slices.0.b"
+
+237628372683
+--xxx
+Content-Disposition: form-data; name="slices.0.c"
+
+654
+--xxx
+Content-Disposition: form-data; name="slices.0.d"
+
+9999.43
+--xxx
+Content-Disposition: form-data; name="slices.0.e"
+
+43.76
+--xxx
+Content-Disposition: form-data; name="slices.0.f.0"
+
+1
+--xxx
+Content-Disposition: form-data; name="slices.0.f.1"
+
+2
+--xxx
+Content-Disposition: form-data; name="slices.0.f.2"
+
+3
+--xxx
+Content-Disposition: form-data; name="slices.0.f.3"
+
+4
+--xxx--
+`,
+ Slices{
+ Slice: []Primitives{{A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}}},
+ },
+ },
+
+ "primitive_pointer_struct": {
+ `--xxx
+Content-Disposition: form-data; name="a"
+
+false
+--xxx
+Content-Disposition: form-data; name="b"
+
+237628372683
+--xxx
+Content-Disposition: form-data; name="c"
+
+654
+--xxx
+Content-Disposition: form-data; name="d"
+
+9999.43
+--xxx
+Content-Disposition: form-data; name="e"
+
+43.76
+--xxx
+Content-Disposition: form-data; name="f.0"
+
+1
+--xxx
+Content-Disposition: form-data; name="f.1"
+
+2
+--xxx
+Content-Disposition: form-data; name="f.2"
+
+3
+--xxx
+Content-Disposition: form-data; name="f.3"
+
+4
+--xxx
+Content-Disposition: form-data; name="f.4"
+
+5
+--xxx--
+`,
+ PrimitivePointers{
+ A: P(false),
+ B: P(237628372683),
+ C: P(uint(654)),
+ D: P(9999.43),
+ E: P(float32(43.76)),
+ F: &[]int{1, 2, 3, 4, 5},
+ },
+ },
+
+ "datetime_struct": {
+ `--xxx
+Content-Disposition: form-data; name="date"
+
+2006-01-02
+--xxx
+Content-Disposition: form-data; name="date-time"
+
+2006-01-02T15:04:05Z
+--xxx--
+`,
+ DateTime{
+ Date: time.Date(2006, time.January, 2, 0, 0, 0, 0, time.UTC),
+ DateTime: time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC),
+ },
+ },
+
+ "additional_properties": {
+ `--xxx
+Content-Disposition: form-data; name="a"
+
+true
+--xxx
+Content-Disposition: form-data; name="bar"
+
+value
+--xxx
+Content-Disposition: form-data; name="foo"
+
+true
+--xxx--
+`,
+ AdditionalProperties{
+ A: true,
+ Extras: map[string]interface{}{
+ "bar": "value",
+ "foo": true,
+ },
+ },
+ },
+
+ "recursive_struct": {
+ `--xxx
+Content-Disposition: form-data; name="child.name"
+
+Alex
+--xxx
+Content-Disposition: form-data; name="name"
+
+Robert
+--xxx--
+`,
+ Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}},
+ },
+
+ "unknown_struct_number": {
+ `--xxx
+Content-Disposition: form-data; name="unknown"
+
+12
+--xxx--
+`,
+ UnknownStruct{
+ Unknown: 12.,
+ },
+ },
+
+ "unknown_struct_map": {
+ `--xxx
+Content-Disposition: form-data; name="unknown.foo"
+
+bar
+--xxx--
+`,
+ UnknownStruct{
+ Unknown: map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ },
+
+ "union_integer": {
+ `--xxx
+Content-Disposition: form-data; name="union"
+
+12
+--xxx--
+`,
+ UnionStruct{
+ Union: UnionInteger(12),
+ },
+ },
+
+ "union_struct_discriminated_a": {
+ `--xxx
+Content-Disposition: form-data; name="union.a"
+
+foo
+--xxx
+Content-Disposition: form-data; name="union.b"
+
+bar
+--xxx
+Content-Disposition: form-data; name="union.type"
+
+typeA
+--xxx--
+`,
+
+ UnionStruct{
+ Union: UnionStructA{
+ Type: "typeA",
+ A: "foo",
+ B: "bar",
+ },
+ },
+ },
+
+ "union_struct_discriminated_b": {
+ `--xxx
+Content-Disposition: form-data; name="union.a"
+
+foo
+--xxx
+Content-Disposition: form-data; name="union.type"
+
+typeB
+--xxx--
+`,
+ UnionStruct{
+ Union: UnionStructB{
+ Type: "typeB",
+ A: "foo",
+ },
+ },
+ },
+
+ "union_struct_time": {
+ `--xxx
+Content-Disposition: form-data; name="union"
+
+2010-05-23
+--xxx--
+`,
+ UnionStruct{
+ Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)),
+ },
+ },
+}
+
+func TestEncode(t *testing.T) {
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ buf := bytes.NewBuffer(nil)
+ writer := multipart.NewWriter(buf)
+ writer.SetBoundary("xxx")
+ err := Marshal(test.val, writer)
+ if err != nil {
+ t.Errorf("serialization of %v failed with error %v", test.val, err)
+ }
+ err = writer.Close()
+ if err != nil {
+ t.Errorf("serialization of %v failed with error %v", test.val, err)
+ }
+ raw := buf.Bytes()
+ if string(raw) != strings.ReplaceAll(test.buf, "\n", "\r\n") {
+ t.Errorf("expected %+#v to serialize to '%s' but got '%s'", test.val, test.buf, string(raw))
+ }
+ })
+ }
+}
diff --git a/packages/sdk/go/internal/apiform/tag.go b/packages/sdk/go/internal/apiform/tag.go
new file mode 100644
index 000000000..b22e054fc
--- /dev/null
+++ b/packages/sdk/go/internal/apiform/tag.go
@@ -0,0 +1,48 @@
+package apiform
+
+import (
+ "reflect"
+ "strings"
+)
+
+const jsonStructTag = "json"
+const formStructTag = "form"
+const formatStructTag = "format"
+
+type parsedStructTag struct {
+ name string
+ required bool
+ extras bool
+ metadata bool
+}
+
+func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
+ raw, ok := field.Tag.Lookup(formStructTag)
+ if !ok {
+ raw, ok = field.Tag.Lookup(jsonStructTag)
+ }
+ if !ok {
+ return
+ }
+ parts := strings.Split(raw, ",")
+ if len(parts) == 0 {
+ return tag, false
+ }
+ tag.name = parts[0]
+ for _, part := range parts[1:] {
+ switch part {
+ case "required":
+ tag.required = true
+ case "extras":
+ tag.extras = true
+ case "metadata":
+ tag.metadata = true
+ }
+ }
+ return
+}
+
+func parseFormatStructTag(field reflect.StructField) (format string, ok bool) {
+ format, ok = field.Tag.Lookup(formatStructTag)
+ return
+}
diff --git a/packages/sdk/go/internal/apijson/decoder.go b/packages/sdk/go/internal/apijson/decoder.go
new file mode 100644
index 000000000..68b7ed6be
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/decoder.go
@@ -0,0 +1,670 @@
+package apijson
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+ "strconv"
+ "sync"
+ "time"
+ "unsafe"
+
+ "github.com/tidwall/gjson"
+)
+
+// decoders is a synchronized map with roughly the following type:
+// map[reflect.Type]decoderFunc
+var decoders sync.Map
+
+// Unmarshal is similar to [encoding/json.Unmarshal] and parses the JSON-encoded
+// data and stores it in the given pointer.
+func Unmarshal(raw []byte, to any) error {
+ d := &decoderBuilder{dateFormat: time.RFC3339}
+ return d.unmarshal(raw, to)
+}
+
+// UnmarshalRoot is like Unmarshal, but doesn't try to call MarshalJSON on the
+// root element. Useful if a struct's UnmarshalJSON is overrode to use the
+// behavior of this encoder versus the standard library.
+func UnmarshalRoot(raw []byte, to any) error {
+ d := &decoderBuilder{dateFormat: time.RFC3339, root: true}
+ return d.unmarshal(raw, to)
+}
+
+// decoderBuilder contains the 'compile-time' state of the decoder.
+type decoderBuilder struct {
+ // Whether or not this is the first element and called by [UnmarshalRoot], see
+ // the documentation there to see why this is necessary.
+ root bool
+ // The dateFormat (a format string for [time.Format]) which is chosen by the
+ // last struct tag that was seen.
+ dateFormat string
+}
+
+// decoderState contains the 'run-time' state of the decoder.
+type decoderState struct {
+ strict bool
+ exactness exactness
+}
+
+// Exactness refers to how close to the type the result was if deserialization
+// was successful. This is useful in deserializing unions, where you want to try
+// each entry, first with strict, then with looser validation, without actually
+// having to do a lot of redundant work by marshalling twice (or maybe even more
+// times).
+type exactness int8
+
+const (
+ // Some values had to fudged a bit, for example by converting a string to an
+ // int, or an enum with extra values.
+ loose exactness = iota
+ // There are some extra arguments, but other wise it matches the union.
+ extras
+ // Exactly right.
+ exact
+)
+
+type decoderFunc func(node gjson.Result, value reflect.Value, state *decoderState) error
+
+type decoderField struct {
+ tag parsedStructTag
+ fn decoderFunc
+ idx []int
+ goname string
+}
+
+type decoderEntry struct {
+ reflect.Type
+ dateFormat string
+ root bool
+}
+
+func (d *decoderBuilder) unmarshal(raw []byte, to any) error {
+ value := reflect.ValueOf(to).Elem()
+ result := gjson.ParseBytes(raw)
+ if !value.IsValid() {
+ return fmt.Errorf("apijson: cannot marshal into invalid value")
+ }
+ return d.typeDecoder(value.Type())(result, value, &decoderState{strict: false, exactness: exact})
+}
+
+func (d *decoderBuilder) typeDecoder(t reflect.Type) decoderFunc {
+ entry := decoderEntry{
+ Type: t,
+ dateFormat: d.dateFormat,
+ root: d.root,
+ }
+
+ if fi, ok := decoders.Load(entry); ok {
+ return fi.(decoderFunc)
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ var (
+ wg sync.WaitGroup
+ f decoderFunc
+ )
+ wg.Add(1)
+ fi, loaded := decoders.LoadOrStore(entry, decoderFunc(func(node gjson.Result, v reflect.Value, state *decoderState) error {
+ wg.Wait()
+ return f(node, v, state)
+ }))
+ if loaded {
+ return fi.(decoderFunc)
+ }
+
+ // Compute the real decoder and replace the indirect func with it.
+ f = d.newTypeDecoder(t)
+ wg.Done()
+ decoders.Store(entry, f)
+ return f
+}
+
+func indirectUnmarshalerDecoder(n gjson.Result, v reflect.Value, state *decoderState) error {
+ return v.Addr().Interface().(json.Unmarshaler).UnmarshalJSON([]byte(n.Raw))
+}
+
+func unmarshalerDecoder(n gjson.Result, v reflect.Value, state *decoderState) error {
+ if v.Kind() == reflect.Pointer && v.CanSet() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ return v.Interface().(json.Unmarshaler).UnmarshalJSON([]byte(n.Raw))
+}
+
+func (d *decoderBuilder) newTypeDecoder(t reflect.Type) decoderFunc {
+ if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
+ return d.newTimeTypeDecoder(t)
+ }
+ if !d.root && t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()) {
+ return unmarshalerDecoder
+ }
+ if !d.root && reflect.PointerTo(t).Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()) {
+ if _, ok := unionVariants[t]; !ok {
+ return indirectUnmarshalerDecoder
+ }
+ }
+ d.root = false
+
+ if _, ok := unionRegistry[t]; ok {
+ return d.newUnionDecoder(t)
+ }
+
+ switch t.Kind() {
+ case reflect.Pointer:
+ inner := t.Elem()
+ innerDecoder := d.typeDecoder(inner)
+
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ if !v.IsValid() {
+ return fmt.Errorf("apijson: unexpected invalid reflection value %+#v", v)
+ }
+
+ newValue := reflect.New(inner).Elem()
+ err := innerDecoder(n, newValue, state)
+ if err != nil {
+ return err
+ }
+
+ v.Set(newValue.Addr())
+ return nil
+ }
+ case reflect.Struct:
+ return d.newStructTypeDecoder(t)
+ case reflect.Array:
+ fallthrough
+ case reflect.Slice:
+ return d.newArrayTypeDecoder(t)
+ case reflect.Map:
+ return d.newMapDecoder(t)
+ case reflect.Interface:
+ return func(node gjson.Result, value reflect.Value, state *decoderState) error {
+ if !value.IsValid() {
+ return fmt.Errorf("apijson: unexpected invalid value %+#v", value)
+ }
+ if node.Value() != nil && value.CanSet() {
+ value.Set(reflect.ValueOf(node.Value()))
+ }
+ return nil
+ }
+ default:
+ return d.newPrimitiveTypeDecoder(t)
+ }
+}
+
+// newUnionDecoder returns a decoderFunc that deserializes into a union using an
+// algorithm roughly similar to Pydantic's [smart algorithm].
+//
+// Conceptually this is equivalent to choosing the best schema based on how 'exact'
+// the deserialization is for each of the schemas.
+//
+// If there is a tie in the level of exactness, then the tie is broken
+// left-to-right.
+//
+// [smart algorithm]: https://docs.pydantic.dev/latest/concepts/unions/#smart-mode
+func (d *decoderBuilder) newUnionDecoder(t reflect.Type) decoderFunc {
+ unionEntry, ok := unionRegistry[t]
+ if !ok {
+ panic("apijson: couldn't find union of type " + t.String() + " in union registry")
+ }
+ decoders := []decoderFunc{}
+ for _, variant := range unionEntry.variants {
+ decoder := d.typeDecoder(variant.Type)
+ decoders = append(decoders, decoder)
+ }
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ // If there is a discriminator match, circumvent the exactness logic entirely
+ for idx, variant := range unionEntry.variants {
+ decoder := decoders[idx]
+ if variant.TypeFilter != n.Type {
+ continue
+ }
+
+ if len(unionEntry.discriminatorKey) != 0 {
+ discriminatorValue := n.Get(unionEntry.discriminatorKey).Value()
+ if discriminatorValue == variant.DiscriminatorValue {
+ inner := reflect.New(variant.Type).Elem()
+ err := decoder(n, inner, state)
+ v.Set(inner)
+ return err
+ }
+ }
+ }
+
+ // Set bestExactness to worse than loose
+ bestExactness := loose - 1
+ for idx, variant := range unionEntry.variants {
+ decoder := decoders[idx]
+ if variant.TypeFilter != n.Type {
+ continue
+ }
+ sub := decoderState{strict: state.strict, exactness: exact}
+ inner := reflect.New(variant.Type).Elem()
+ err := decoder(n, inner, &sub)
+ if err != nil {
+ continue
+ }
+ if sub.exactness == exact {
+ v.Set(inner)
+ return nil
+ }
+ if sub.exactness > bestExactness {
+ v.Set(inner)
+ bestExactness = sub.exactness
+ }
+ }
+
+ if bestExactness < loose {
+ return errors.New("apijson: was not able to coerce type as union")
+ }
+
+ if guardStrict(state, bestExactness != exact) {
+ return errors.New("apijson: was not able to coerce type as union strictly")
+ }
+
+ return nil
+ }
+}
+
+func (d *decoderBuilder) newMapDecoder(t reflect.Type) decoderFunc {
+ keyType := t.Key()
+ itemType := t.Elem()
+ itemDecoder := d.typeDecoder(itemType)
+
+ return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
+ mapValue := reflect.MakeMapWithSize(t, len(node.Map()))
+
+ node.ForEach(func(key, value gjson.Result) bool {
+ // It's fine for us to just use `ValueOf` here because the key types will
+ // always be primitive types so we don't need to decode it using the standard pattern
+ keyValue := reflect.ValueOf(key.Value())
+ if !keyValue.IsValid() {
+ if err == nil {
+ err = fmt.Errorf("apijson: received invalid key type %v", keyValue.String())
+ }
+ return false
+ }
+ if keyValue.Type() != keyType {
+ if err == nil {
+ err = fmt.Errorf("apijson: expected key type %v but got %v", keyType, keyValue.Type())
+ }
+ return false
+ }
+
+ itemValue := reflect.New(itemType).Elem()
+ itemerr := itemDecoder(value, itemValue, state)
+ if itemerr != nil {
+ if err == nil {
+ err = itemerr
+ }
+ return false
+ }
+
+ mapValue.SetMapIndex(keyValue, itemValue)
+ return true
+ })
+
+ if err != nil {
+ return err
+ }
+ value.Set(mapValue)
+ return nil
+ }
+}
+
+func (d *decoderBuilder) newArrayTypeDecoder(t reflect.Type) decoderFunc {
+ itemDecoder := d.typeDecoder(t.Elem())
+
+ return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
+ if !node.IsArray() {
+ return fmt.Errorf("apijson: could not deserialize to an array")
+ }
+
+ arrayNode := node.Array()
+
+ arrayValue := reflect.MakeSlice(reflect.SliceOf(t.Elem()), len(arrayNode), len(arrayNode))
+ for i, itemNode := range arrayNode {
+ err = itemDecoder(itemNode, arrayValue.Index(i), state)
+ if err != nil {
+ return err
+ }
+ }
+
+ value.Set(arrayValue)
+ return nil
+ }
+}
+
+func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
+ // map of json field name to struct field decoders
+ decoderFields := map[string]decoderField{}
+ anonymousDecoders := []decoderField{}
+ extraDecoder := (*decoderField)(nil)
+ inlineDecoder := (*decoderField)(nil)
+
+ for i := 0; i < t.NumField(); i++ {
+ idx := []int{i}
+ field := t.FieldByIndex(idx)
+ if !field.IsExported() {
+ continue
+ }
+ // If this is an embedded struct, traverse one level deeper to extract
+ // the fields and get their encoders as well.
+ if field.Anonymous {
+ anonymousDecoders = append(anonymousDecoders, decoderField{
+ fn: d.typeDecoder(field.Type),
+ idx: idx[:],
+ })
+ continue
+ }
+ // If json tag is not present, then we skip, which is intentionally
+ // different behavior from the stdlib.
+ ptag, ok := parseJSONStructTag(field)
+ if !ok {
+ continue
+ }
+ // We only want to support unexported fields if they're tagged with
+ // `extras` because that field shouldn't be part of the public API.
+ if ptag.extras {
+ extraDecoder = &decoderField{ptag, d.typeDecoder(field.Type.Elem()), idx, field.Name}
+ continue
+ }
+ if ptag.inline {
+ inlineDecoder = &decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name}
+ continue
+ }
+ if ptag.metadata {
+ continue
+ }
+
+ oldFormat := d.dateFormat
+ dateFormat, ok := parseFormatStructTag(field)
+ if ok {
+ switch dateFormat {
+ case "date-time":
+ d.dateFormat = time.RFC3339
+ case "date":
+ d.dateFormat = "2006-01-02"
+ }
+ }
+ decoderFields[ptag.name] = decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name}
+ d.dateFormat = oldFormat
+ }
+
+ return func(node gjson.Result, value reflect.Value, state *decoderState) (err error) {
+ if field := value.FieldByName("JSON"); field.IsValid() {
+ if raw := field.FieldByName("raw"); raw.IsValid() {
+ setUnexportedField(raw, node.Raw)
+ }
+ }
+
+ for _, decoder := range anonymousDecoders {
+ // ignore errors
+ decoder.fn(node, value.FieldByIndex(decoder.idx), state)
+ }
+
+ if inlineDecoder != nil {
+ var meta Field
+ dest := value.FieldByIndex(inlineDecoder.idx)
+ isValid := false
+ if dest.IsValid() && node.Type != gjson.Null {
+ err = inlineDecoder.fn(node, dest, state)
+ if err == nil {
+ isValid = true
+ }
+ }
+
+ if node.Type == gjson.Null {
+ meta = Field{
+ raw: node.Raw,
+ status: null,
+ }
+ } else if !isValid {
+ meta = Field{
+ raw: node.Raw,
+ status: invalid,
+ }
+ } else if isValid {
+ meta = Field{
+ raw: node.Raw,
+ status: valid,
+ }
+ }
+ if metadata := getSubField(value, inlineDecoder.idx, inlineDecoder.goname); metadata.IsValid() {
+ metadata.Set(reflect.ValueOf(meta))
+ }
+ return err
+ }
+
+ typedExtraType := reflect.Type(nil)
+ typedExtraFields := reflect.Value{}
+ if extraDecoder != nil {
+ typedExtraType = value.FieldByIndex(extraDecoder.idx).Type()
+ typedExtraFields = reflect.MakeMap(typedExtraType)
+ }
+ untypedExtraFields := map[string]Field{}
+
+ for fieldName, itemNode := range node.Map() {
+ df, explicit := decoderFields[fieldName]
+ var (
+ dest reflect.Value
+ fn decoderFunc
+ meta Field
+ )
+ if explicit {
+ fn = df.fn
+ dest = value.FieldByIndex(df.idx)
+ }
+ if !explicit && extraDecoder != nil {
+ dest = reflect.New(typedExtraType.Elem()).Elem()
+ fn = extraDecoder.fn
+ }
+
+ isValid := false
+ if dest.IsValid() && itemNode.Type != gjson.Null {
+ err = fn(itemNode, dest, state)
+ if err == nil {
+ isValid = true
+ }
+ }
+
+ if itemNode.Type == gjson.Null {
+ meta = Field{
+ raw: itemNode.Raw,
+ status: null,
+ }
+ } else if !isValid {
+ meta = Field{
+ raw: itemNode.Raw,
+ status: invalid,
+ }
+ } else if isValid {
+ meta = Field{
+ raw: itemNode.Raw,
+ status: valid,
+ }
+ }
+
+ if explicit {
+ if metadata := getSubField(value, df.idx, df.goname); metadata.IsValid() {
+ metadata.Set(reflect.ValueOf(meta))
+ }
+ }
+ if !explicit {
+ untypedExtraFields[fieldName] = meta
+ }
+ if !explicit && extraDecoder != nil {
+ typedExtraFields.SetMapIndex(reflect.ValueOf(fieldName), dest)
+ }
+ }
+
+ if extraDecoder != nil && typedExtraFields.Len() > 0 {
+ value.FieldByIndex(extraDecoder.idx).Set(typedExtraFields)
+ }
+
+ // Set exactness to 'extras' if there are untyped, extra fields.
+ if len(untypedExtraFields) > 0 && state.exactness > extras {
+ state.exactness = extras
+ }
+
+ if metadata := getSubField(value, []int{-1}, "ExtraFields"); metadata.IsValid() && len(untypedExtraFields) > 0 {
+ metadata.Set(reflect.ValueOf(untypedExtraFields))
+ }
+ return nil
+ }
+}
+
+func (d *decoderBuilder) newPrimitiveTypeDecoder(t reflect.Type) decoderFunc {
+ switch t.Kind() {
+ case reflect.String:
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ v.SetString(n.String())
+ if guardStrict(state, n.Type != gjson.String) {
+ return fmt.Errorf("apijson: failed to parse string strictly")
+ }
+ // Everything that is not an object can be loosely stringified.
+ if n.Type == gjson.JSON {
+ return fmt.Errorf("apijson: failed to parse string")
+ }
+ if guardUnknown(state, v) {
+ return fmt.Errorf("apijson: failed string enum validation")
+ }
+ return nil
+ }
+ case reflect.Bool:
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ v.SetBool(n.Bool())
+ if guardStrict(state, n.Type != gjson.True && n.Type != gjson.False) {
+ return fmt.Errorf("apijson: failed to parse bool strictly")
+ }
+ // Numbers and strings that are either 'true' or 'false' can be loosely
+ // deserialized as bool.
+ if n.Type == gjson.String && (n.Raw != "true" && n.Raw != "false") || n.Type == gjson.JSON {
+ return fmt.Errorf("apijson: failed to parse bool")
+ }
+ if guardUnknown(state, v) {
+ return fmt.Errorf("apijson: failed bool enum validation")
+ }
+ return nil
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ v.SetInt(n.Int())
+ if guardStrict(state, n.Type != gjson.Number || n.Num != float64(int(n.Num))) {
+ return fmt.Errorf("apijson: failed to parse int strictly")
+ }
+ // Numbers, booleans, and strings that maybe look like numbers can be
+ // loosely deserialized as numbers.
+ if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
+ return fmt.Errorf("apijson: failed to parse int")
+ }
+ if guardUnknown(state, v) {
+ return fmt.Errorf("apijson: failed int enum validation")
+ }
+ return nil
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ v.SetUint(n.Uint())
+ if guardStrict(state, n.Type != gjson.Number || n.Num != float64(int(n.Num)) || n.Num < 0) {
+ return fmt.Errorf("apijson: failed to parse uint strictly")
+ }
+ // Numbers, booleans, and strings that maybe look like numbers can be
+ // loosely deserialized as uint.
+ if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
+ return fmt.Errorf("apijson: failed to parse uint")
+ }
+ if guardUnknown(state, v) {
+ return fmt.Errorf("apijson: failed uint enum validation")
+ }
+ return nil
+ }
+ case reflect.Float32, reflect.Float64:
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ v.SetFloat(n.Float())
+ if guardStrict(state, n.Type != gjson.Number) {
+ return fmt.Errorf("apijson: failed to parse float strictly")
+ }
+ // Numbers, booleans, and strings that maybe look like numbers can be
+ // loosely deserialized as floats.
+ if n.Type == gjson.JSON || (n.Type == gjson.String && !canParseAsNumber(n.Str)) {
+ return fmt.Errorf("apijson: failed to parse float")
+ }
+ if guardUnknown(state, v) {
+ return fmt.Errorf("apijson: failed float enum validation")
+ }
+ return nil
+ }
+ default:
+ return func(node gjson.Result, v reflect.Value, state *decoderState) error {
+ return fmt.Errorf("unknown type received at primitive decoder: %s", t.String())
+ }
+ }
+}
+
+func (d *decoderBuilder) newTimeTypeDecoder(t reflect.Type) decoderFunc {
+ format := d.dateFormat
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ parsed, err := time.Parse(format, n.Str)
+ if err == nil {
+ v.Set(reflect.ValueOf(parsed).Convert(t))
+ return nil
+ }
+
+ if guardStrict(state, true) {
+ return err
+ }
+
+ layouts := []string{
+ "2006-01-02",
+ "2006-01-02T15:04:05Z07:00",
+ "2006-01-02T15:04:05Z0700",
+ "2006-01-02T15:04:05",
+ "2006-01-02 15:04:05Z07:00",
+ "2006-01-02 15:04:05Z0700",
+ "2006-01-02 15:04:05",
+ }
+
+ for _, layout := range layouts {
+ parsed, err := time.Parse(layout, n.Str)
+ if err == nil {
+ v.Set(reflect.ValueOf(parsed).Convert(t))
+ return nil
+ }
+ }
+
+ return fmt.Errorf("unable to leniently parse date-time string: %s", n.Str)
+ }
+}
+
+func setUnexportedField(field reflect.Value, value interface{}) {
+ reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Set(reflect.ValueOf(value))
+}
+
+func guardStrict(state *decoderState, cond bool) bool {
+ if !cond {
+ return false
+ }
+
+ if state.strict {
+ return true
+ }
+
+ state.exactness = loose
+ return false
+}
+
+func canParseAsNumber(str string) bool {
+ _, err := strconv.ParseFloat(str, 64)
+ return err == nil
+}
+
+func guardUnknown(state *decoderState, v reflect.Value) bool {
+ if have, ok := v.Interface().(interface{ IsKnown() bool }); guardStrict(state, ok && !have.IsKnown()) {
+ return true
+ }
+ return false
+}
diff --git a/packages/sdk/go/internal/apijson/encoder.go b/packages/sdk/go/internal/apijson/encoder.go
new file mode 100644
index 000000000..0e5f89e17
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/encoder.go
@@ -0,0 +1,398 @@
+package apijson
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/tidwall/sjson"
+
+ "github.com/sst/opencode-sdk-go/internal/param"
+)
+
+var encoders sync.Map // map[encoderEntry]encoderFunc
+
+func Marshal(value interface{}) ([]byte, error) {
+ e := &encoder{dateFormat: time.RFC3339}
+ return e.marshal(value)
+}
+
+func MarshalRoot(value interface{}) ([]byte, error) {
+ e := &encoder{root: true, dateFormat: time.RFC3339}
+ return e.marshal(value)
+}
+
+type encoder struct {
+ dateFormat string
+ root bool
+}
+
+type encoderFunc func(value reflect.Value) ([]byte, error)
+
+type encoderField struct {
+ tag parsedStructTag
+ fn encoderFunc
+ idx []int
+}
+
+type encoderEntry struct {
+ reflect.Type
+ dateFormat string
+ root bool
+}
+
+func (e *encoder) marshal(value interface{}) ([]byte, error) {
+ val := reflect.ValueOf(value)
+ if !val.IsValid() {
+ return nil, nil
+ }
+ typ := val.Type()
+ enc := e.typeEncoder(typ)
+ return enc(val)
+}
+
+func (e *encoder) typeEncoder(t reflect.Type) encoderFunc {
+ entry := encoderEntry{
+ Type: t,
+ dateFormat: e.dateFormat,
+ root: e.root,
+ }
+
+ if fi, ok := encoders.Load(entry); ok {
+ return fi.(encoderFunc)
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ var (
+ wg sync.WaitGroup
+ f encoderFunc
+ )
+ wg.Add(1)
+ fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(v reflect.Value) ([]byte, error) {
+ wg.Wait()
+ return f(v)
+ }))
+ if loaded {
+ return fi.(encoderFunc)
+ }
+
+ // Compute the real encoder and replace the indirect func with it.
+ f = e.newTypeEncoder(t)
+ wg.Done()
+ encoders.Store(entry, f)
+ return f
+}
+
+func marshalerEncoder(v reflect.Value) ([]byte, error) {
+ return v.Interface().(json.Marshaler).MarshalJSON()
+}
+
+func indirectMarshalerEncoder(v reflect.Value) ([]byte, error) {
+ return v.Addr().Interface().(json.Marshaler).MarshalJSON()
+}
+
+func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc {
+ if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
+ return e.newTimeTypeEncoder()
+ }
+ if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) {
+ return marshalerEncoder
+ }
+ if !e.root && reflect.PointerTo(t).Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) {
+ return indirectMarshalerEncoder
+ }
+ e.root = false
+ switch t.Kind() {
+ case reflect.Pointer:
+ inner := t.Elem()
+
+ innerEncoder := e.typeEncoder(inner)
+ return func(v reflect.Value) ([]byte, error) {
+ if !v.IsValid() || v.IsNil() {
+ return nil, nil
+ }
+ return innerEncoder(v.Elem())
+ }
+ case reflect.Struct:
+ return e.newStructTypeEncoder(t)
+ case reflect.Array:
+ fallthrough
+ case reflect.Slice:
+ return e.newArrayTypeEncoder(t)
+ case reflect.Map:
+ return e.newMapEncoder(t)
+ case reflect.Interface:
+ return e.newInterfaceEncoder()
+ default:
+ return e.newPrimitiveTypeEncoder(t)
+ }
+}
+
+func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc {
+ switch t.Kind() {
+ // Note that we could use `gjson` to encode these types but it would complicate our
+ // code more and this current code shouldn't cause any issues
+ case reflect.String:
+ return func(v reflect.Value) ([]byte, error) {
+ return json.Marshal(v.Interface())
+ }
+ case reflect.Bool:
+ return func(v reflect.Value) ([]byte, error) {
+ if v.Bool() {
+ return []byte("true"), nil
+ }
+ return []byte("false"), nil
+ }
+ case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
+ return func(v reflect.Value) ([]byte, error) {
+ return []byte(strconv.FormatInt(v.Int(), 10)), nil
+ }
+ case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return func(v reflect.Value) ([]byte, error) {
+ return []byte(strconv.FormatUint(v.Uint(), 10)), nil
+ }
+ case reflect.Float32:
+ return func(v reflect.Value) ([]byte, error) {
+ return []byte(strconv.FormatFloat(v.Float(), 'f', -1, 32)), nil
+ }
+ case reflect.Float64:
+ return func(v reflect.Value) ([]byte, error) {
+ return []byte(strconv.FormatFloat(v.Float(), 'f', -1, 64)), nil
+ }
+ default:
+ return func(v reflect.Value) ([]byte, error) {
+ return nil, fmt.Errorf("unknown type received at primitive encoder: %s", t.String())
+ }
+ }
+}
+
+func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
+ itemEncoder := e.typeEncoder(t.Elem())
+
+ return func(value reflect.Value) ([]byte, error) {
+ json := []byte("[]")
+ for i := 0; i < value.Len(); i++ {
+ var value, err = itemEncoder(value.Index(i))
+ if err != nil {
+ return nil, err
+ }
+ if value == nil {
+ // Assume that empty items should be inserted as `null` so that the output array
+ // will be the same length as the input array
+ value = []byte("null")
+ }
+
+ json, err = sjson.SetRawBytes(json, "-1", value)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return json, nil
+ }
+}
+
+func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
+ if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) {
+ return e.newFieldTypeEncoder(t)
+ }
+
+ encoderFields := []encoderField{}
+ extraEncoder := (*encoderField)(nil)
+
+ // This helper allows us to recursively collect field encoders into a flat
+ // array. The parameter `index` keeps track of the access patterns necessary
+ // to get to some field.
+ var collectEncoderFields func(r reflect.Type, index []int)
+ collectEncoderFields = func(r reflect.Type, index []int) {
+ for i := 0; i < r.NumField(); i++ {
+ idx := append(index, i)
+ field := t.FieldByIndex(idx)
+ if !field.IsExported() {
+ continue
+ }
+ // If this is an embedded struct, traverse one level deeper to extract
+ // the field and get their encoders as well.
+ if field.Anonymous {
+ collectEncoderFields(field.Type, idx)
+ continue
+ }
+ // If json tag is not present, then we skip, which is intentionally
+ // different behavior from the stdlib.
+ ptag, ok := parseJSONStructTag(field)
+ if !ok {
+ continue
+ }
+ // We only want to support unexported field if they're tagged with
+ // `extras` because that field shouldn't be part of the public API. We
+ // also want to only keep the top level extras
+ if ptag.extras && len(index) == 0 {
+ extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx}
+ continue
+ }
+ if ptag.name == "-" {
+ continue
+ }
+
+ dateFormat, ok := parseFormatStructTag(field)
+ oldFormat := e.dateFormat
+ if ok {
+ switch dateFormat {
+ case "date-time":
+ e.dateFormat = time.RFC3339
+ case "date":
+ e.dateFormat = "2006-01-02"
+ }
+ }
+ encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx})
+ e.dateFormat = oldFormat
+ }
+ }
+ collectEncoderFields(t, []int{})
+
+ // Ensure deterministic output by sorting by lexicographic order
+ sort.Slice(encoderFields, func(i, j int) bool {
+ return encoderFields[i].tag.name < encoderFields[j].tag.name
+ })
+
+ return func(value reflect.Value) (json []byte, err error) {
+ json = []byte("{}")
+
+ for _, ef := range encoderFields {
+ field := value.FieldByIndex(ef.idx)
+ encoded, err := ef.fn(field)
+ if err != nil {
+ return nil, err
+ }
+ if encoded == nil {
+ continue
+ }
+ json, err = sjson.SetRawBytes(json, ef.tag.name, encoded)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if extraEncoder != nil {
+ json, err = e.encodeMapEntries(json, value.FieldByIndex(extraEncoder.idx))
+ if err != nil {
+ return nil, err
+ }
+ }
+ return
+ }
+}
+
+func (e *encoder) newFieldTypeEncoder(t reflect.Type) encoderFunc {
+ f, _ := t.FieldByName("Value")
+ enc := e.typeEncoder(f.Type)
+
+ return func(value reflect.Value) (json []byte, err error) {
+ present := value.FieldByName("Present")
+ if !present.Bool() {
+ return nil, nil
+ }
+ null := value.FieldByName("Null")
+ if null.Bool() {
+ return []byte("null"), nil
+ }
+ raw := value.FieldByName("Raw")
+ if !raw.IsNil() {
+ return e.typeEncoder(raw.Type())(raw)
+ }
+ return enc(value.FieldByName("Value"))
+ }
+}
+
+func (e *encoder) newTimeTypeEncoder() encoderFunc {
+ format := e.dateFormat
+ return func(value reflect.Value) (json []byte, err error) {
+ return []byte(`"` + value.Convert(reflect.TypeOf(time.Time{})).Interface().(time.Time).Format(format) + `"`), nil
+ }
+}
+
+func (e encoder) newInterfaceEncoder() encoderFunc {
+ return func(value reflect.Value) ([]byte, error) {
+ value = value.Elem()
+ if !value.IsValid() {
+ return nil, nil
+ }
+ return e.typeEncoder(value.Type())(value)
+ }
+}
+
+// Given a []byte of json (may either be an empty object or an object that already contains entries)
+// encode all of the entries in the map to the json byte array.
+func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error) {
+ type mapPair struct {
+ key []byte
+ value reflect.Value
+ }
+
+ pairs := []mapPair{}
+ keyEncoder := e.typeEncoder(v.Type().Key())
+
+ iter := v.MapRange()
+ for iter.Next() {
+ var encodedKeyString string
+ if iter.Key().Type().Kind() == reflect.String {
+ encodedKeyString = iter.Key().String()
+ } else {
+ var err error
+ encodedKeyBytes, err := keyEncoder(iter.Key())
+ if err != nil {
+ return nil, err
+ }
+ encodedKeyString = string(encodedKeyBytes)
+ }
+ encodedKey := []byte(sjsonReplacer.Replace(encodedKeyString))
+ pairs = append(pairs, mapPair{key: encodedKey, value: iter.Value()})
+ }
+
+ // Ensure deterministic output
+ sort.Slice(pairs, func(i, j int) bool {
+ return bytes.Compare(pairs[i].key, pairs[j].key) < 0
+ })
+
+ elementEncoder := e.typeEncoder(v.Type().Elem())
+ for _, p := range pairs {
+ encodedValue, err := elementEncoder(p.value)
+ if err != nil {
+ return nil, err
+ }
+ if len(encodedValue) == 0 {
+ continue
+ }
+ json, err = sjson.SetRawBytes(json, string(p.key), encodedValue)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return json, nil
+}
+
+func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc {
+ return func(value reflect.Value) ([]byte, error) {
+ json := []byte("{}")
+ var err error
+ json, err = e.encodeMapEntries(json, value)
+ if err != nil {
+ return nil, err
+ }
+ return json, nil
+ }
+}
+
+// If we want to set a literal key value into JSON using sjson, we need to make sure it doesn't have
+// special characters that sjson interprets as a path.
+var sjsonReplacer *strings.Replacer = strings.NewReplacer(".", "\\.", ":", "\\:", "*", "\\*")
diff --git a/packages/sdk/go/internal/apijson/field.go b/packages/sdk/go/internal/apijson/field.go
new file mode 100644
index 000000000..3ef207c58
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/field.go
@@ -0,0 +1,41 @@
+package apijson
+
+import "reflect"
+
+type status uint8
+
+const (
+ missing status = iota
+ null
+ invalid
+ valid
+)
+
+type Field struct {
+ raw string
+ status status
+}
+
+// Returns true if the field is explicitly `null` _or_ if it is not present at all (ie, missing).
+// To check if the field's key is present in the JSON with an explicit null value,
+// you must check `f.IsNull() && !f.IsMissing()`.
+func (j Field) IsNull() bool { return j.status <= null }
+func (j Field) IsMissing() bool { return j.status == missing }
+func (j Field) IsInvalid() bool { return j.status == invalid }
+func (j Field) Raw() string { return j.raw }
+
+func getSubField(root reflect.Value, index []int, name string) reflect.Value {
+ strct := root.FieldByIndex(index[:len(index)-1])
+ if !strct.IsValid() {
+ panic("couldn't find encapsulating struct for field " + name)
+ }
+ meta := strct.FieldByName("JSON")
+ if !meta.IsValid() {
+ return reflect.Value{}
+ }
+ field := meta.FieldByName(name)
+ if !field.IsValid() {
+ return reflect.Value{}
+ }
+ return field
+}
diff --git a/packages/sdk/go/internal/apijson/field_test.go b/packages/sdk/go/internal/apijson/field_test.go
new file mode 100644
index 000000000..2e170c76f
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/field_test.go
@@ -0,0 +1,66 @@
+package apijson
+
+import (
+ "testing"
+ "time"
+
+ "github.com/sst/opencode-sdk-go/internal/param"
+)
+
+type Struct struct {
+ A string `json:"a"`
+ B int64 `json:"b"`
+}
+
+type FieldStruct struct {
+ A param.Field[string] `json:"a"`
+ B param.Field[int64] `json:"b"`
+ C param.Field[Struct] `json:"c"`
+ D param.Field[time.Time] `json:"d" format:"date"`
+ E param.Field[time.Time] `json:"e" format:"date-time"`
+ F param.Field[int64] `json:"f"`
+}
+
+func TestFieldMarshal(t *testing.T) {
+ tests := map[string]struct {
+ value interface{}
+ expected string
+ }{
+ "null_string": {param.Field[string]{Present: true, Null: true}, "null"},
+ "null_int": {param.Field[int]{Present: true, Null: true}, "null"},
+ "null_int64": {param.Field[int64]{Present: true, Null: true}, "null"},
+ "null_struct": {param.Field[Struct]{Present: true, Null: true}, "null"},
+
+ "string": {param.Field[string]{Present: true, Value: "string"}, `"string"`},
+ "int": {param.Field[int]{Present: true, Value: 123}, "123"},
+ "int64": {param.Field[int64]{Present: true, Value: int64(123456789123456789)}, "123456789123456789"},
+ "struct": {param.Field[Struct]{Present: true, Value: Struct{A: "yo", B: 123}}, `{"a":"yo","b":123}`},
+
+ "string_raw": {param.Field[int]{Present: true, Raw: "string"}, `"string"`},
+ "int_raw": {param.Field[int]{Present: true, Raw: 123}, "123"},
+ "int64_raw": {param.Field[int]{Present: true, Raw: int64(123456789123456789)}, "123456789123456789"},
+ "struct_raw": {param.Field[int]{Present: true, Raw: Struct{A: "yo", B: 123}}, `{"a":"yo","b":123}`},
+
+ "param_struct": {
+ FieldStruct{
+ A: param.Field[string]{Present: true, Value: "hello"},
+ B: param.Field[int64]{Present: true, Value: int64(12)},
+ D: param.Field[time.Time]{Present: true, Value: time.Date(2023, time.March, 18, 14, 47, 38, 0, time.UTC)},
+ E: param.Field[time.Time]{Present: true, Value: time.Date(2023, time.March, 18, 14, 47, 38, 0, time.UTC)},
+ },
+ `{"a":"hello","b":12,"d":"2023-03-18","e":"2023-03-18T14:47:38Z"}`,
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ b, err := Marshal(test.value)
+ if err != nil {
+ t.Fatalf("didn't expect error %v", err)
+ }
+ if string(b) != test.expected {
+ t.Fatalf("expected %s, received %s", test.expected, string(b))
+ }
+ })
+ }
+}
diff --git a/packages/sdk/go/internal/apijson/json_test.go b/packages/sdk/go/internal/apijson/json_test.go
new file mode 100644
index 000000000..e6563448f
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/json_test.go
@@ -0,0 +1,617 @@
+package apijson
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/tidwall/gjson"
+)
+
+func P[T any](v T) *T { return &v }
+
+type Primitives struct {
+ A bool `json:"a"`
+ B int `json:"b"`
+ C uint `json:"c"`
+ D float64 `json:"d"`
+ E float32 `json:"e"`
+ F []int `json:"f"`
+}
+
+type PrimitivePointers struct {
+ A *bool `json:"a"`
+ B *int `json:"b"`
+ C *uint `json:"c"`
+ D *float64 `json:"d"`
+ E *float32 `json:"e"`
+ F *[]int `json:"f"`
+}
+
+type Slices struct {
+ Slice []Primitives `json:"slices"`
+}
+
+type DateTime struct {
+ Date time.Time `json:"date" format:"date"`
+ DateTime time.Time `json:"date-time" format:"date-time"`
+}
+
+type AdditionalProperties struct {
+ A bool `json:"a"`
+ ExtraFields map[string]interface{} `json:"-,extras"`
+}
+
+type TypedAdditionalProperties struct {
+ A bool `json:"a"`
+ ExtraFields map[string]int `json:"-,extras"`
+}
+
+type EmbeddedStruct struct {
+ A bool `json:"a"`
+ B string `json:"b"`
+
+ JSON EmbeddedStructJSON
+}
+
+type EmbeddedStructJSON struct {
+ A Field
+ B Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+type EmbeddedStructs struct {
+ EmbeddedStruct
+ A *int `json:"a"`
+ ExtraFields map[string]interface{} `json:"-,extras"`
+
+ JSON EmbeddedStructsJSON
+}
+
+type EmbeddedStructsJSON struct {
+ A Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+type Recursive struct {
+ Name string `json:"name"`
+ Child *Recursive `json:"child"`
+}
+
+type JSONFieldStruct struct {
+ A bool `json:"a"`
+ B int64 `json:"b"`
+ C string `json:"c"`
+ D string `json:"d"`
+ ExtraFields map[string]int64 `json:"-,extras"`
+ JSON JSONFieldStructJSON `json:"-,metadata"`
+}
+
+type JSONFieldStructJSON struct {
+ A Field
+ B Field
+ C Field
+ D Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+type UnknownStruct struct {
+ Unknown interface{} `json:"unknown"`
+}
+
+type UnionStruct struct {
+ Union Union `json:"union" format:"date"`
+}
+
+type Union interface {
+ union()
+}
+
+type Inline struct {
+ InlineField Primitives `json:"-,inline"`
+ JSON InlineJSON `json:"-,metadata"`
+}
+
+type InlineArray struct {
+ InlineField []string `json:"-,inline"`
+ JSON InlineJSON `json:"-,metadata"`
+}
+
+type InlineJSON struct {
+ InlineField Field
+ raw string
+}
+
+type UnionInteger int64
+
+func (UnionInteger) union() {}
+
+type UnionStructA struct {
+ Type string `json:"type"`
+ A string `json:"a"`
+ B string `json:"b"`
+}
+
+func (UnionStructA) union() {}
+
+type UnionStructB struct {
+ Type string `json:"type"`
+ A string `json:"a"`
+}
+
+func (UnionStructB) union() {}
+
+type UnionTime time.Time
+
+func (UnionTime) union() {}
+
+func init() {
+ RegisterUnion(reflect.TypeOf((*Union)(nil)).Elem(), "type",
+ UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(UnionTime{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.Number,
+ Type: reflect.TypeOf(UnionInteger(0)),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ DiscriminatorValue: "typeA",
+ Type: reflect.TypeOf(UnionStructA{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ DiscriminatorValue: "typeB",
+ Type: reflect.TypeOf(UnionStructB{}),
+ },
+ )
+}
+
+type ComplexUnionStruct struct {
+ Union ComplexUnion `json:"union"`
+}
+
+type ComplexUnion interface {
+ complexUnion()
+}
+
+type ComplexUnionA struct {
+ Boo string `json:"boo"`
+ Foo bool `json:"foo"`
+}
+
+func (ComplexUnionA) complexUnion() {}
+
+type ComplexUnionB struct {
+ Boo bool `json:"boo"`
+ Foo string `json:"foo"`
+}
+
+func (ComplexUnionB) complexUnion() {}
+
+type ComplexUnionC struct {
+ Boo int64 `json:"boo"`
+}
+
+func (ComplexUnionC) complexUnion() {}
+
+type ComplexUnionTypeA struct {
+ Baz int64 `json:"baz"`
+ Type TypeA `json:"type"`
+}
+
+func (ComplexUnionTypeA) complexUnion() {}
+
+type TypeA string
+
+func (t TypeA) IsKnown() bool {
+ return t == "a"
+}
+
+type ComplexUnionTypeB struct {
+ Baz int64 `json:"baz"`
+ Type TypeB `json:"type"`
+}
+
+type TypeB string
+
+func (t TypeB) IsKnown() bool {
+ return t == "b"
+}
+
+type UnmarshalStruct struct {
+ Foo string `json:"foo"`
+ prop bool `json:"-"`
+}
+
+func (r *UnmarshalStruct) UnmarshalJSON(json []byte) error {
+ r.prop = true
+ return UnmarshalRoot(json, r)
+}
+
+func (ComplexUnionTypeB) complexUnion() {}
+
+func init() {
+ RegisterUnion(reflect.TypeOf((*ComplexUnion)(nil)).Elem(), "",
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ComplexUnionA{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ComplexUnionB{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ComplexUnionC{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ComplexUnionTypeA{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ComplexUnionTypeB{}),
+ },
+ )
+}
+
+type MarshallingUnionStruct struct {
+ Union MarshallingUnion
+}
+
+func (r *MarshallingUnionStruct) UnmarshalJSON(data []byte) (err error) {
+ *r = MarshallingUnionStruct{}
+ err = UnmarshalRoot(data, &r.Union)
+ return
+}
+
+func (r MarshallingUnionStruct) MarshalJSON() (data []byte, err error) {
+ return MarshalRoot(r.Union)
+}
+
+type MarshallingUnion interface {
+ marshallingUnion()
+}
+
+type MarshallingUnionA struct {
+ Boo string `json:"boo"`
+}
+
+func (MarshallingUnionA) marshallingUnion() {}
+
+func (r *MarshallingUnionA) UnmarshalJSON(data []byte) (err error) {
+ return UnmarshalRoot(data, r)
+}
+
+type MarshallingUnionB struct {
+ Foo string `json:"foo"`
+}
+
+func (MarshallingUnionB) marshallingUnion() {}
+
+func (r *MarshallingUnionB) UnmarshalJSON(data []byte) (err error) {
+ return UnmarshalRoot(data, r)
+}
+
+func init() {
+ RegisterUnion(
+ reflect.TypeOf((*MarshallingUnion)(nil)).Elem(),
+ "",
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(MarshallingUnionA{}),
+ },
+ UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(MarshallingUnionB{}),
+ },
+ )
+}
+
+var tests = map[string]struct {
+ buf string
+ val interface{}
+}{
+ "true": {"true", true},
+ "false": {"false", false},
+ "int": {"1", 1},
+ "int_bigger": {"12324", 12324},
+ "int_string_coerce": {`"65"`, 65},
+ "int_boolean_coerce": {"true", 1},
+ "int64": {"1", int64(1)},
+ "int64_huge": {"123456789123456789", int64(123456789123456789)},
+ "uint": {"1", uint(1)},
+ "uint_bigger": {"12324", uint(12324)},
+ "uint_coerce": {`"65"`, uint(65)},
+ "float_1.54": {"1.54", float32(1.54)},
+ "float_1.89": {"1.89", float64(1.89)},
+ "string": {`"str"`, "str"},
+ "string_int_coerce": {`12`, "12"},
+ "array_string": {`["foo","bar"]`, []string{"foo", "bar"}},
+ "array_int": {`[1,2]`, []int{1, 2}},
+ "array_int_coerce": {`["1",2]`, []int{1, 2}},
+
+ "ptr_true": {"true", P(true)},
+ "ptr_false": {"false", P(false)},
+ "ptr_int": {"1", P(1)},
+ "ptr_int_bigger": {"12324", P(12324)},
+ "ptr_int_string_coerce": {`"65"`, P(65)},
+ "ptr_int_boolean_coerce": {"true", P(1)},
+ "ptr_int64": {"1", P(int64(1))},
+ "ptr_int64_huge": {"123456789123456789", P(int64(123456789123456789))},
+ "ptr_uint": {"1", P(uint(1))},
+ "ptr_uint_bigger": {"12324", P(uint(12324))},
+ "ptr_uint_coerce": {`"65"`, P(uint(65))},
+ "ptr_float_1.54": {"1.54", P(float32(1.54))},
+ "ptr_float_1.89": {"1.89", P(float64(1.89))},
+
+ "date_time": {`"2007-03-01T13:00:00Z"`, time.Date(2007, time.March, 1, 13, 0, 0, 0, time.UTC)},
+ "date_time_nano_coerce": {`"2007-03-01T13:03:05.123456789Z"`, time.Date(2007, time.March, 1, 13, 3, 5, 123456789, time.UTC)},
+
+ "date_time_missing_t_coerce": {`"2007-03-01 13:03:05Z"`, time.Date(2007, time.March, 1, 13, 3, 5, 0, time.UTC)},
+ "date_time_missing_timezone_coerce": {`"2007-03-01T13:03:05"`, time.Date(2007, time.March, 1, 13, 3, 5, 0, time.UTC)},
+ // note: using -1200 to minimize probability of conflicting with the local timezone of the test runner
+ // see https://en.wikipedia.org/wiki/UTC%E2%88%9212:00
+ "date_time_missing_timezone_colon_coerce": {`"2007-03-01T13:03:05-1200"`, time.Date(2007, time.March, 1, 13, 3, 5, 0, time.FixedZone("", -12*60*60))},
+ "date_time_nano_missing_t_coerce": {`"2007-03-01 13:03:05.123456789Z"`, time.Date(2007, time.March, 1, 13, 3, 5, 123456789, time.UTC)},
+
+ "map_string": {`{"foo":"bar"}`, map[string]string{"foo": "bar"}},
+ "map_string_with_sjson_path_chars": {`{":a.b.c*:d*-1e.f":"bar"}`, map[string]string{":a.b.c*:d*-1e.f": "bar"}},
+ "map_interface": {`{"a":1,"b":"str","c":false}`, map[string]interface{}{"a": float64(1), "b": "str", "c": false}},
+
+ "primitive_struct": {
+ `{"a":false,"b":237628372683,"c":654,"d":9999.43,"e":43.76,"f":[1,2,3,4]}`,
+ Primitives{A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ },
+
+ "slices": {
+ `{"slices":[{"a":false,"b":237628372683,"c":654,"d":9999.43,"e":43.76,"f":[1,2,3,4]}]}`,
+ Slices{
+ Slice: []Primitives{{A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}}},
+ },
+ },
+
+ "primitive_pointer_struct": {
+ `{"a":false,"b":237628372683,"c":654,"d":9999.43,"e":43.76,"f":[1,2,3,4,5]}`,
+ PrimitivePointers{
+ A: P(false),
+ B: P(237628372683),
+ C: P(uint(654)),
+ D: P(9999.43),
+ E: P(float32(43.76)),
+ F: &[]int{1, 2, 3, 4, 5},
+ },
+ },
+
+ "datetime_struct": {
+ `{"date":"2006-01-02","date-time":"2006-01-02T15:04:05Z"}`,
+ DateTime{
+ Date: time.Date(2006, time.January, 2, 0, 0, 0, 0, time.UTC),
+ DateTime: time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC),
+ },
+ },
+
+ "additional_properties": {
+ `{"a":true,"bar":"value","foo":true}`,
+ AdditionalProperties{
+ A: true,
+ ExtraFields: map[string]interface{}{
+ "bar": "value",
+ "foo": true,
+ },
+ },
+ },
+
+ "embedded_struct": {
+ `{"a":1,"b":"bar"}`,
+ EmbeddedStructs{
+ EmbeddedStruct: EmbeddedStruct{
+ A: true,
+ B: "bar",
+ JSON: EmbeddedStructJSON{
+ A: Field{raw: `1`, status: valid},
+ B: Field{raw: `"bar"`, status: valid},
+ raw: `{"a":1,"b":"bar"}`,
+ },
+ },
+ A: P(1),
+ ExtraFields: map[string]interface{}{"b": "bar"},
+ JSON: EmbeddedStructsJSON{
+ A: Field{raw: `1`, status: valid},
+ ExtraFields: map[string]Field{
+ "b": {raw: `"bar"`, status: valid},
+ },
+ raw: `{"a":1,"b":"bar"}`,
+ },
+ },
+ },
+
+ "recursive_struct": {
+ `{"child":{"name":"Alex"},"name":"Robert"}`,
+ Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}},
+ },
+
+ "metadata_coerce": {
+ `{"a":"12","b":"12","c":null,"extra_typed":12,"extra_untyped":{"foo":"bar"}}`,
+ JSONFieldStruct{
+ A: false,
+ B: 12,
+ C: "",
+ JSON: JSONFieldStructJSON{
+ raw: `{"a":"12","b":"12","c":null,"extra_typed":12,"extra_untyped":{"foo":"bar"}}`,
+ A: Field{raw: `"12"`, status: invalid},
+ B: Field{raw: `"12"`, status: valid},
+ C: Field{raw: "null", status: null},
+ D: Field{raw: "", status: missing},
+ ExtraFields: map[string]Field{
+ "extra_typed": {
+ raw: "12",
+ status: valid,
+ },
+ "extra_untyped": {
+ raw: `{"foo":"bar"}`,
+ status: invalid,
+ },
+ },
+ },
+ ExtraFields: map[string]int64{
+ "extra_typed": 12,
+ "extra_untyped": 0,
+ },
+ },
+ },
+
+ "unknown_struct_number": {
+ `{"unknown":12}`,
+ UnknownStruct{
+ Unknown: 12.,
+ },
+ },
+
+ "unknown_struct_map": {
+ `{"unknown":{"foo":"bar"}}`,
+ UnknownStruct{
+ Unknown: map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ },
+
+ "union_integer": {
+ `{"union":12}`,
+ UnionStruct{
+ Union: UnionInteger(12),
+ },
+ },
+
+ "union_struct_discriminated_a": {
+ `{"union":{"a":"foo","b":"bar","type":"typeA"}}`,
+ UnionStruct{
+ Union: UnionStructA{
+ Type: "typeA",
+ A: "foo",
+ B: "bar",
+ },
+ },
+ },
+
+ "union_struct_discriminated_b": {
+ `{"union":{"a":"foo","type":"typeB"}}`,
+ UnionStruct{
+ Union: UnionStructB{
+ Type: "typeB",
+ A: "foo",
+ },
+ },
+ },
+
+ "union_struct_time": {
+ `{"union":"2010-05-23"}`,
+ UnionStruct{
+ Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)),
+ },
+ },
+
+ "complex_union_a": {
+ `{"union":{"boo":"12","foo":true}}`,
+ ComplexUnionStruct{Union: ComplexUnionA{Boo: "12", Foo: true}},
+ },
+
+ "complex_union_b": {
+ `{"union":{"boo":true,"foo":"12"}}`,
+ ComplexUnionStruct{Union: ComplexUnionB{Boo: true, Foo: "12"}},
+ },
+
+ "complex_union_c": {
+ `{"union":{"boo":12}}`,
+ ComplexUnionStruct{Union: ComplexUnionC{Boo: 12}},
+ },
+
+ "complex_union_type_a": {
+ `{"union":{"baz":12,"type":"a"}}`,
+ ComplexUnionStruct{Union: ComplexUnionTypeA{Baz: 12, Type: TypeA("a")}},
+ },
+
+ "complex_union_type_b": {
+ `{"union":{"baz":12,"type":"b"}}`,
+ ComplexUnionStruct{Union: ComplexUnionTypeB{Baz: 12, Type: TypeB("b")}},
+ },
+
+ "marshalling_union_a": {
+ `{"boo":"hello"}`,
+ MarshallingUnionStruct{Union: MarshallingUnionA{Boo: "hello"}},
+ },
+ "marshalling_union_b": {
+ `{"foo":"hi"}`,
+ MarshallingUnionStruct{Union: MarshallingUnionB{Foo: "hi"}},
+ },
+
+ "unmarshal": {
+ `{"foo":"hello"}`,
+ &UnmarshalStruct{Foo: "hello", prop: true},
+ },
+
+ "array_of_unmarshal": {
+ `[{"foo":"hello"}]`,
+ []UnmarshalStruct{{Foo: "hello", prop: true}},
+ },
+
+ "inline_coerce": {
+ `{"a":false,"b":237628372683,"c":654,"d":9999.43,"e":43.76,"f":[1,2,3,4]}`,
+ Inline{
+ InlineField: Primitives{A: false, B: 237628372683, C: 0x28e, D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ JSON: InlineJSON{
+ InlineField: Field{raw: "{\"a\":false,\"b\":237628372683,\"c\":654,\"d\":9999.43,\"e\":43.76,\"f\":[1,2,3,4]}", status: 3},
+ raw: "{\"a\":false,\"b\":237628372683,\"c\":654,\"d\":9999.43,\"e\":43.76,\"f\":[1,2,3,4]}",
+ },
+ },
+ },
+
+ "inline_array_coerce": {
+ `["Hello","foo","bar"]`,
+ InlineArray{
+ InlineField: []string{"Hello", "foo", "bar"},
+ JSON: InlineJSON{
+ InlineField: Field{raw: `["Hello","foo","bar"]`, status: 3},
+ raw: `["Hello","foo","bar"]`,
+ },
+ },
+ },
+}
+
+func TestDecode(t *testing.T) {
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ result := reflect.New(reflect.TypeOf(test.val))
+ if err := Unmarshal([]byte(test.buf), result.Interface()); err != nil {
+ t.Fatalf("deserialization of %v failed with error %v", result, err)
+ }
+ if !reflect.DeepEqual(result.Elem().Interface(), test.val) {
+ t.Fatalf("expected '%s' to deserialize to \n%#v\nbut got\n%#v", test.buf, test.val, result.Elem().Interface())
+ }
+ })
+ }
+}
+
+func TestEncode(t *testing.T) {
+ for name, test := range tests {
+ if strings.HasSuffix(name, "_coerce") {
+ continue
+ }
+ t.Run(name, func(t *testing.T) {
+ raw, err := Marshal(test.val)
+ if err != nil {
+ t.Fatalf("serialization of %v failed with error %v", test.val, err)
+ }
+ if string(raw) != test.buf {
+ t.Fatalf("expected %+#v to serialize to %s but got %s", test.val, test.buf, string(raw))
+ }
+ })
+ }
+}
diff --git a/packages/sdk/go/internal/apijson/port.go b/packages/sdk/go/internal/apijson/port.go
new file mode 100644
index 000000000..502ab7780
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/port.go
@@ -0,0 +1,120 @@
+package apijson
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// Port copies over values from one struct to another struct.
+func Port(from any, to any) error {
+ toVal := reflect.ValueOf(to)
+ fromVal := reflect.ValueOf(from)
+
+ if toVal.Kind() != reflect.Ptr || toVal.IsNil() {
+ return fmt.Errorf("destination must be a non-nil pointer")
+ }
+
+ for toVal.Kind() == reflect.Ptr {
+ toVal = toVal.Elem()
+ }
+ toType := toVal.Type()
+
+ for fromVal.Kind() == reflect.Ptr {
+ fromVal = fromVal.Elem()
+ }
+ fromType := fromVal.Type()
+
+ if toType.Kind() != reflect.Struct {
+ return fmt.Errorf("destination must be a non-nil pointer to a struct (%v %v)", toType, toType.Kind())
+ }
+
+ values := map[string]reflect.Value{}
+ fields := map[string]reflect.Value{}
+
+ fromJSON := fromVal.FieldByName("JSON")
+ toJSON := toVal.FieldByName("JSON")
+
+ // Iterate through the fields of v and load all the "normal" fields in the struct to the map of
+ // string to reflect.Value, as well as their raw .JSON.Foo counterpart indicated by j.
+ var getFields func(t reflect.Type, v reflect.Value)
+ getFields = func(t reflect.Type, v reflect.Value) {
+ j := v.FieldByName("JSON")
+
+ // Recurse into anonymous fields first, since the fields on the object should win over the fields in the
+ // embedded object.
+ for i := 0; i < t.NumField(); i++ {
+ field := t.Field(i)
+ if field.Anonymous {
+ getFields(field.Type, v.Field(i))
+ continue
+ }
+ }
+
+ for i := 0; i < t.NumField(); i++ {
+ field := t.Field(i)
+ ptag, ok := parseJSONStructTag(field)
+ if !ok || ptag.name == "-" {
+ continue
+ }
+ values[ptag.name] = v.Field(i)
+ if j.IsValid() {
+ fields[ptag.name] = j.FieldByName(field.Name)
+ }
+ }
+ }
+ getFields(fromType, fromVal)
+
+ // Use the values from the previous step to populate the 'to' struct.
+ for i := 0; i < toType.NumField(); i++ {
+ field := toType.Field(i)
+ ptag, ok := parseJSONStructTag(field)
+ if !ok {
+ continue
+ }
+ if ptag.name == "-" {
+ continue
+ }
+ if value, ok := values[ptag.name]; ok {
+ delete(values, ptag.name)
+ if field.Type.Kind() == reflect.Interface {
+ toVal.Field(i).Set(value)
+ } else {
+ switch value.Kind() {
+ case reflect.String:
+ toVal.Field(i).SetString(value.String())
+ case reflect.Bool:
+ toVal.Field(i).SetBool(value.Bool())
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ toVal.Field(i).SetInt(value.Int())
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ toVal.Field(i).SetUint(value.Uint())
+ case reflect.Float32, reflect.Float64:
+ toVal.Field(i).SetFloat(value.Float())
+ default:
+ toVal.Field(i).Set(value)
+ }
+ }
+ }
+
+ if fromJSONField, ok := fields[ptag.name]; ok {
+ if toJSONField := toJSON.FieldByName(field.Name); toJSONField.IsValid() {
+ toJSONField.Set(fromJSONField)
+ }
+ }
+ }
+
+ // Finally, copy over the .JSON.raw and .JSON.ExtraFields
+ if toJSON.IsValid() {
+ if raw := toJSON.FieldByName("raw"); raw.IsValid() {
+ setUnexportedField(raw, fromJSON.Interface().(interface{ RawJSON() string }).RawJSON())
+ }
+
+ if toExtraFields := toJSON.FieldByName("ExtraFields"); toExtraFields.IsValid() {
+ if fromExtraFields := fromJSON.FieldByName("ExtraFields"); fromExtraFields.IsValid() {
+ setUnexportedField(toExtraFields, fromExtraFields.Interface())
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/packages/sdk/go/internal/apijson/port_test.go b/packages/sdk/go/internal/apijson/port_test.go
new file mode 100644
index 000000000..115405335
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/port_test.go
@@ -0,0 +1,257 @@
+package apijson
+
+import (
+ "reflect"
+ "testing"
+)
+
+type Metadata struct {
+ CreatedAt string `json:"created_at"`
+}
+
+// Card is the "combined" type of CardVisa and CardMastercard
+type Card struct {
+ Processor CardProcessor `json:"processor"`
+ Data any `json:"data"`
+ IsFoo bool `json:"is_foo"`
+ IsBar bool `json:"is_bar"`
+ Metadata Metadata `json:"metadata"`
+ Value interface{} `json:"value"`
+
+ JSON cardJSON
+}
+
+type cardJSON struct {
+ Processor Field
+ Data Field
+ IsFoo Field
+ IsBar Field
+ Metadata Field
+ Value Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+func (r cardJSON) RawJSON() string { return r.raw }
+
+type CardProcessor string
+
+// CardVisa
+type CardVisa struct {
+ Processor CardVisaProcessor `json:"processor"`
+ Data CardVisaData `json:"data"`
+ IsFoo bool `json:"is_foo"`
+ Metadata Metadata `json:"metadata"`
+ Value string `json:"value"`
+
+ JSON cardVisaJSON
+}
+
+type cardVisaJSON struct {
+ Processor Field
+ Data Field
+ IsFoo Field
+ Metadata Field
+ Value Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+func (r cardVisaJSON) RawJSON() string { return r.raw }
+
+type CardVisaProcessor string
+
+type CardVisaData struct {
+ Foo string `json:"foo"`
+}
+
+// CardMastercard
+type CardMastercard struct {
+ Processor CardMastercardProcessor `json:"processor"`
+ Data CardMastercardData `json:"data"`
+ IsBar bool `json:"is_bar"`
+ Metadata Metadata `json:"metadata"`
+ Value bool `json:"value"`
+
+ JSON cardMastercardJSON
+}
+
+type cardMastercardJSON struct {
+ Processor Field
+ Data Field
+ IsBar Field
+ Metadata Field
+ Value Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+func (r cardMastercardJSON) RawJSON() string { return r.raw }
+
+type CardMastercardProcessor string
+
+type CardMastercardData struct {
+ Bar int64 `json:"bar"`
+}
+
+type CommonFields struct {
+ Metadata Metadata `json:"metadata"`
+ Value string `json:"value"`
+
+ JSON commonFieldsJSON
+}
+
+type commonFieldsJSON struct {
+ Metadata Field
+ Value Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+type CardEmbedded struct {
+ CommonFields
+ Processor CardVisaProcessor `json:"processor"`
+ Data CardVisaData `json:"data"`
+ IsFoo bool `json:"is_foo"`
+
+ JSON cardEmbeddedJSON
+}
+
+type cardEmbeddedJSON struct {
+ Processor Field
+ Data Field
+ IsFoo Field
+ ExtraFields map[string]Field
+ raw string
+}
+
+func (r cardEmbeddedJSON) RawJSON() string { return r.raw }
+
+var portTests = map[string]struct {
+ from any
+ to any
+}{
+ "visa to card": {
+ CardVisa{
+ Processor: "visa",
+ IsFoo: true,
+ Data: CardVisaData{
+ Foo: "foo",
+ },
+ Metadata: Metadata{
+ CreatedAt: "Mar 29 2024",
+ },
+ Value: "value",
+ JSON: cardVisaJSON{
+ raw: `{"processor":"visa","is_foo":true,"data":{"foo":"foo"}}`,
+ Processor: Field{raw: `"visa"`, status: valid},
+ IsFoo: Field{raw: `true`, status: valid},
+ Data: Field{raw: `{"foo":"foo"}`, status: valid},
+ Value: Field{raw: `"value"`, status: valid},
+ ExtraFields: map[string]Field{"extra": {raw: `"yo"`, status: valid}},
+ },
+ },
+ Card{
+ Processor: "visa",
+ IsFoo: true,
+ IsBar: false,
+ Data: CardVisaData{
+ Foo: "foo",
+ },
+ Metadata: Metadata{
+ CreatedAt: "Mar 29 2024",
+ },
+ Value: "value",
+ JSON: cardJSON{
+ raw: `{"processor":"visa","is_foo":true,"data":{"foo":"foo"}}`,
+ Processor: Field{raw: `"visa"`, status: valid},
+ IsFoo: Field{raw: `true`, status: valid},
+ Data: Field{raw: `{"foo":"foo"}`, status: valid},
+ Value: Field{raw: `"value"`, status: valid},
+ ExtraFields: map[string]Field{"extra": {raw: `"yo"`, status: valid}},
+ },
+ },
+ },
+ "mastercard to card": {
+ CardMastercard{
+ Processor: "mastercard",
+ IsBar: true,
+ Data: CardMastercardData{
+ Bar: 13,
+ },
+ Value: false,
+ },
+ Card{
+ Processor: "mastercard",
+ IsFoo: false,
+ IsBar: true,
+ Data: CardMastercardData{
+ Bar: 13,
+ },
+ Value: false,
+ },
+ },
+ "embedded to card": {
+ CardEmbedded{
+ CommonFields: CommonFields{
+ Metadata: Metadata{
+ CreatedAt: "Mar 29 2024",
+ },
+ Value: "embedded_value",
+ JSON: commonFieldsJSON{
+ Metadata: Field{raw: `{"created_at":"Mar 29 2024"}`, status: valid},
+ Value: Field{raw: `"embedded_value"`, status: valid},
+ raw: `should not matter`,
+ },
+ },
+ Processor: "visa",
+ IsFoo: true,
+ Data: CardVisaData{
+ Foo: "embedded_foo",
+ },
+ JSON: cardEmbeddedJSON{
+ raw: `{"processor":"visa","is_foo":true,"data":{"foo":"embedded_foo"},"metadata":{"created_at":"Mar 29 2024"},"value":"embedded_value"}`,
+ Processor: Field{raw: `"visa"`, status: valid},
+ IsFoo: Field{raw: `true`, status: valid},
+ Data: Field{raw: `{"foo":"embedded_foo"}`, status: valid},
+ },
+ },
+ Card{
+ Processor: "visa",
+ IsFoo: true,
+ IsBar: false,
+ Data: CardVisaData{
+ Foo: "embedded_foo",
+ },
+ Metadata: Metadata{
+ CreatedAt: "Mar 29 2024",
+ },
+ Value: "embedded_value",
+ JSON: cardJSON{
+ raw: `{"processor":"visa","is_foo":true,"data":{"foo":"embedded_foo"},"metadata":{"created_at":"Mar 29 2024"},"value":"embedded_value"}`,
+ Processor: Field{raw: `"visa"`, status: 0x3},
+ IsFoo: Field{raw: "true", status: 0x3},
+ Data: Field{raw: `{"foo":"embedded_foo"}`, status: 0x3},
+ Metadata: Field{raw: `{"created_at":"Mar 29 2024"}`, status: 0x3},
+ Value: Field{raw: `"embedded_value"`, status: 0x3},
+ },
+ },
+ },
+}
+
+func TestPort(t *testing.T) {
+ for name, test := range portTests {
+ t.Run(name, func(t *testing.T) {
+ toVal := reflect.New(reflect.TypeOf(test.to))
+
+ err := Port(test.from, toVal.Interface())
+ if err != nil {
+ t.Fatalf("port of %v failed with error %v", test.from, err)
+ }
+
+ if !reflect.DeepEqual(toVal.Elem().Interface(), test.to) {
+ t.Fatalf("expected:\n%+#v\n\nto port to:\n%+#v\n\nbut got:\n%+#v", test.from, test.to, toVal.Elem().Interface())
+ }
+ })
+ }
+}
diff --git a/packages/sdk/go/internal/apijson/registry.go b/packages/sdk/go/internal/apijson/registry.go
new file mode 100644
index 000000000..119cc5ff8
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/registry.go
@@ -0,0 +1,41 @@
+package apijson
+
+import (
+ "reflect"
+
+ "github.com/tidwall/gjson"
+)
+
+type UnionVariant struct {
+ TypeFilter gjson.Type
+ DiscriminatorValue interface{}
+ Type reflect.Type
+}
+
+var unionRegistry = map[reflect.Type]unionEntry{}
+var unionVariants = map[reflect.Type]interface{}{}
+
+type unionEntry struct {
+ discriminatorKey string
+ variants []UnionVariant
+}
+
+func RegisterUnion(typ reflect.Type, discriminator string, variants ...UnionVariant) {
+ unionRegistry[typ] = unionEntry{
+ discriminatorKey: discriminator,
+ variants: variants,
+ }
+ for _, variant := range variants {
+ unionVariants[variant.Type] = typ
+ }
+}
+
+// Useful to wrap a union type to force it to use [apijson.UnmarshalJSON] since you cannot define an
+// UnmarshalJSON function on the interface itself.
+type UnionUnmarshaler[T any] struct {
+ Value T
+}
+
+func (c *UnionUnmarshaler[T]) UnmarshalJSON(buf []byte) error {
+ return UnmarshalRoot(buf, &c.Value)
+}
diff --git a/packages/sdk/go/internal/apijson/tag.go b/packages/sdk/go/internal/apijson/tag.go
new file mode 100644
index 000000000..812fb3caf
--- /dev/null
+++ b/packages/sdk/go/internal/apijson/tag.go
@@ -0,0 +1,47 @@
+package apijson
+
+import (
+ "reflect"
+ "strings"
+)
+
+const jsonStructTag = "json"
+const formatStructTag = "format"
+
+type parsedStructTag struct {
+ name string
+ required bool
+ extras bool
+ metadata bool
+ inline bool
+}
+
+func parseJSONStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
+ raw, ok := field.Tag.Lookup(jsonStructTag)
+ if !ok {
+ return
+ }
+ parts := strings.Split(raw, ",")
+ if len(parts) == 0 {
+ return tag, false
+ }
+ tag.name = parts[0]
+ for _, part := range parts[1:] {
+ switch part {
+ case "required":
+ tag.required = true
+ case "extras":
+ tag.extras = true
+ case "metadata":
+ tag.metadata = true
+ case "inline":
+ tag.inline = true
+ }
+ }
+ return
+}
+
+func parseFormatStructTag(field reflect.StructField) (format string, ok bool) {
+ format, ok = field.Tag.Lookup(formatStructTag)
+ return
+}
diff --git a/packages/sdk/go/internal/apiquery/encoder.go b/packages/sdk/go/internal/apiquery/encoder.go
new file mode 100644
index 000000000..0922c2316
--- /dev/null
+++ b/packages/sdk/go/internal/apiquery/encoder.go
@@ -0,0 +1,341 @@
+package apiquery
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/sst/opencode-sdk-go/internal/param"
+)
+
+var encoders sync.Map // map[reflect.Type]encoderFunc
+
+type encoder struct {
+ dateFormat string
+ root bool
+ settings QuerySettings
+}
+
+type encoderFunc func(key string, value reflect.Value) []Pair
+
+type encoderField struct {
+ tag parsedStructTag
+ fn encoderFunc
+ idx []int
+}
+
+type encoderEntry struct {
+ reflect.Type
+ dateFormat string
+ root bool
+ settings QuerySettings
+}
+
+type Pair struct {
+ key string
+ value string
+}
+
+func (e *encoder) typeEncoder(t reflect.Type) encoderFunc {
+ entry := encoderEntry{
+ Type: t,
+ dateFormat: e.dateFormat,
+ root: e.root,
+ settings: e.settings,
+ }
+
+ if fi, ok := encoders.Load(entry); ok {
+ return fi.(encoderFunc)
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ var (
+ wg sync.WaitGroup
+ f encoderFunc
+ )
+ wg.Add(1)
+ fi, loaded := encoders.LoadOrStore(entry, encoderFunc(func(key string, v reflect.Value) []Pair {
+ wg.Wait()
+ return f(key, v)
+ }))
+ if loaded {
+ return fi.(encoderFunc)
+ }
+
+ // Compute the real encoder and replace the indirect func with it.
+ f = e.newTypeEncoder(t)
+ wg.Done()
+ encoders.Store(entry, f)
+ return f
+}
+
+func marshalerEncoder(key string, value reflect.Value) []Pair {
+ s, _ := value.Interface().(json.Marshaler).MarshalJSON()
+ return []Pair{{key, string(s)}}
+}
+
+func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc {
+ if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
+ return e.newTimeTypeEncoder(t)
+ }
+ if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) {
+ return marshalerEncoder
+ }
+ e.root = false
+ switch t.Kind() {
+ case reflect.Pointer:
+ encoder := e.typeEncoder(t.Elem())
+ return func(key string, value reflect.Value) (pairs []Pair) {
+ if !value.IsValid() || value.IsNil() {
+ return
+ }
+ pairs = encoder(key, value.Elem())
+ return
+ }
+ case reflect.Struct:
+ return e.newStructTypeEncoder(t)
+ case reflect.Array:
+ fallthrough
+ case reflect.Slice:
+ return e.newArrayTypeEncoder(t)
+ case reflect.Map:
+ return e.newMapEncoder(t)
+ case reflect.Interface:
+ return e.newInterfaceEncoder()
+ default:
+ return e.newPrimitiveTypeEncoder(t)
+ }
+}
+
+func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
+ if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) {
+ return e.newFieldTypeEncoder(t)
+ }
+
+ encoderFields := []encoderField{}
+
+ // This helper allows us to recursively collect field encoders into a flat
+ // array. The parameter `index` keeps track of the access patterns necessary
+ // to get to some field.
+ var collectEncoderFields func(r reflect.Type, index []int)
+ collectEncoderFields = func(r reflect.Type, index []int) {
+ for i := 0; i < r.NumField(); i++ {
+ idx := append(index, i)
+ field := t.FieldByIndex(idx)
+ if !field.IsExported() {
+ continue
+ }
+ // If this is an embedded struct, traverse one level deeper to extract
+ // the field and get their encoders as well.
+ if field.Anonymous {
+ collectEncoderFields(field.Type, idx)
+ continue
+ }
+ // If query tag is not present, then we skip, which is intentionally
+ // different behavior from the stdlib.
+ ptag, ok := parseQueryStructTag(field)
+ if !ok {
+ continue
+ }
+
+ if ptag.name == "-" && !ptag.inline {
+ continue
+ }
+
+ dateFormat, ok := parseFormatStructTag(field)
+ oldFormat := e.dateFormat
+ if ok {
+ switch dateFormat {
+ case "date-time":
+ e.dateFormat = time.RFC3339
+ case "date":
+ e.dateFormat = "2006-01-02"
+ }
+ }
+ encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx})
+ e.dateFormat = oldFormat
+ }
+ }
+ collectEncoderFields(t, []int{})
+
+ return func(key string, value reflect.Value) (pairs []Pair) {
+ for _, ef := range encoderFields {
+ var subkey string = e.renderKeyPath(key, ef.tag.name)
+ if ef.tag.inline {
+ subkey = key
+ }
+
+ field := value.FieldByIndex(ef.idx)
+ pairs = append(pairs, ef.fn(subkey, field)...)
+ }
+ return
+ }
+}
+
+func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc {
+ keyEncoder := e.typeEncoder(t.Key())
+ elementEncoder := e.typeEncoder(t.Elem())
+ return func(key string, value reflect.Value) (pairs []Pair) {
+ iter := value.MapRange()
+ for iter.Next() {
+ encodedKey := keyEncoder("", iter.Key())
+ if len(encodedKey) != 1 {
+ panic("Unexpected number of parts for encoded map key. Are you using a non-primitive for this map?")
+ }
+ subkey := encodedKey[0].value
+ keyPath := e.renderKeyPath(key, subkey)
+ pairs = append(pairs, elementEncoder(keyPath, iter.Value())...)
+ }
+ return
+ }
+}
+
+func (e *encoder) renderKeyPath(key string, subkey string) string {
+ if len(key) == 0 {
+ return subkey
+ }
+ if e.settings.NestedFormat == NestedQueryFormatDots {
+ return fmt.Sprintf("%s.%s", key, subkey)
+ }
+ return fmt.Sprintf("%s[%s]", key, subkey)
+}
+
+func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
+ switch e.settings.ArrayFormat {
+ case ArrayQueryFormatComma:
+ innerEncoder := e.typeEncoder(t.Elem())
+ return func(key string, v reflect.Value) []Pair {
+ elements := []string{}
+ for i := 0; i < v.Len(); i++ {
+ for _, pair := range innerEncoder("", v.Index(i)) {
+ elements = append(elements, pair.value)
+ }
+ }
+ if len(elements) == 0 {
+ return []Pair{}
+ }
+ return []Pair{{key, strings.Join(elements, ",")}}
+ }
+ case ArrayQueryFormatRepeat:
+ innerEncoder := e.typeEncoder(t.Elem())
+ return func(key string, value reflect.Value) (pairs []Pair) {
+ for i := 0; i < value.Len(); i++ {
+ pairs = append(pairs, innerEncoder(key, value.Index(i))...)
+ }
+ return pairs
+ }
+ case ArrayQueryFormatIndices:
+ panic("The array indices format is not supported yet")
+ case ArrayQueryFormatBrackets:
+ innerEncoder := e.typeEncoder(t.Elem())
+ return func(key string, value reflect.Value) []Pair {
+ pairs := []Pair{}
+ for i := 0; i < value.Len(); i++ {
+ pairs = append(pairs, innerEncoder(key+"[]", value.Index(i))...)
+ }
+ return pairs
+ }
+ default:
+ panic(fmt.Sprintf("Unknown ArrayFormat value: %d", e.settings.ArrayFormat))
+ }
+}
+
+func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc {
+ switch t.Kind() {
+ case reflect.Pointer:
+ inner := t.Elem()
+
+ innerEncoder := e.newPrimitiveTypeEncoder(inner)
+ return func(key string, v reflect.Value) []Pair {
+ if !v.IsValid() || v.IsNil() {
+ return nil
+ }
+ return innerEncoder(key, v.Elem())
+ }
+ case reflect.String:
+ return func(key string, v reflect.Value) []Pair {
+ return []Pair{{key, v.String()}}
+ }
+ case reflect.Bool:
+ return func(key string, v reflect.Value) []Pair {
+ if v.Bool() {
+ return []Pair{{key, "true"}}
+ }
+ return []Pair{{key, "false"}}
+ }
+ case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
+ return func(key string, v reflect.Value) []Pair {
+ return []Pair{{key, strconv.FormatInt(v.Int(), 10)}}
+ }
+ case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return func(key string, v reflect.Value) []Pair {
+ return []Pair{{key, strconv.FormatUint(v.Uint(), 10)}}
+ }
+ case reflect.Float32, reflect.Float64:
+ return func(key string, v reflect.Value) []Pair {
+ return []Pair{{key, strconv.FormatFloat(v.Float(), 'f', -1, 64)}}
+ }
+ case reflect.Complex64, reflect.Complex128:
+ bitSize := 64
+ if t.Kind() == reflect.Complex128 {
+ bitSize = 128
+ }
+ return func(key string, v reflect.Value) []Pair {
+ return []Pair{{key, strconv.FormatComplex(v.Complex(), 'f', -1, bitSize)}}
+ }
+ default:
+ return func(key string, v reflect.Value) []Pair {
+ return nil
+ }
+ }
+}
+
+func (e *encoder) newFieldTypeEncoder(t reflect.Type) encoderFunc {
+ f, _ := t.FieldByName("Value")
+ enc := e.typeEncoder(f.Type)
+
+ return func(key string, value reflect.Value) []Pair {
+ present := value.FieldByName("Present")
+ if !present.Bool() {
+ return nil
+ }
+ null := value.FieldByName("Null")
+ if null.Bool() {
+ // TODO: Error?
+ return nil
+ }
+ raw := value.FieldByName("Raw")
+ if !raw.IsNil() {
+ return e.typeEncoder(raw.Type())(key, raw)
+ }
+ return enc(key, value.FieldByName("Value"))
+ }
+}
+
+func (e *encoder) newTimeTypeEncoder(t reflect.Type) encoderFunc {
+ format := e.dateFormat
+ return func(key string, value reflect.Value) []Pair {
+ return []Pair{{
+ key,
+ value.Convert(reflect.TypeOf(time.Time{})).Interface().(time.Time).Format(format),
+ }}
+ }
+}
+
+func (e encoder) newInterfaceEncoder() encoderFunc {
+ return func(key string, value reflect.Value) []Pair {
+ value = value.Elem()
+ if !value.IsValid() {
+ return nil
+ }
+ return e.typeEncoder(value.Type())(key, value)
+ }
+
+}
diff --git a/packages/sdk/go/internal/apiquery/query.go b/packages/sdk/go/internal/apiquery/query.go
new file mode 100644
index 000000000..6f90e9935
--- /dev/null
+++ b/packages/sdk/go/internal/apiquery/query.go
@@ -0,0 +1,50 @@
+package apiquery
+
+import (
+ "net/url"
+ "reflect"
+ "time"
+)
+
+func MarshalWithSettings(value interface{}, settings QuerySettings) url.Values {
+ e := encoder{time.RFC3339, true, settings}
+ kv := url.Values{}
+ val := reflect.ValueOf(value)
+ if !val.IsValid() {
+ return nil
+ }
+ typ := val.Type()
+ for _, pair := range e.typeEncoder(typ)("", val) {
+ kv.Add(pair.key, pair.value)
+ }
+ return kv
+}
+
+func Marshal(value interface{}) url.Values {
+ return MarshalWithSettings(value, QuerySettings{})
+}
+
+type Queryer interface {
+ URLQuery() url.Values
+}
+
+type QuerySettings struct {
+ NestedFormat NestedQueryFormat
+ ArrayFormat ArrayQueryFormat
+}
+
+type NestedQueryFormat int
+
+const (
+ NestedQueryFormatBrackets NestedQueryFormat = iota
+ NestedQueryFormatDots
+)
+
+type ArrayQueryFormat int
+
+const (
+ ArrayQueryFormatComma ArrayQueryFormat = iota
+ ArrayQueryFormatRepeat
+ ArrayQueryFormatIndices
+ ArrayQueryFormatBrackets
+)
diff --git a/packages/sdk/go/internal/apiquery/query_test.go b/packages/sdk/go/internal/apiquery/query_test.go
new file mode 100644
index 000000000..1e740d6a9
--- /dev/null
+++ b/packages/sdk/go/internal/apiquery/query_test.go
@@ -0,0 +1,335 @@
+package apiquery
+
+import (
+ "net/url"
+ "testing"
+ "time"
+)
+
+func P[T any](v T) *T { return &v }
+
+type Primitives struct {
+ A bool `query:"a"`
+ B int `query:"b"`
+ C uint `query:"c"`
+ D float64 `query:"d"`
+ E float32 `query:"e"`
+ F []int `query:"f"`
+}
+
+type PrimitivePointers struct {
+ A *bool `query:"a"`
+ B *int `query:"b"`
+ C *uint `query:"c"`
+ D *float64 `query:"d"`
+ E *float32 `query:"e"`
+ F *[]int `query:"f"`
+}
+
+type Slices struct {
+ Slice []Primitives `query:"slices"`
+ Mixed []interface{} `query:"mixed"`
+}
+
+type DateTime struct {
+ Date time.Time `query:"date" format:"date"`
+ DateTime time.Time `query:"date-time" format:"date-time"`
+}
+
+type AdditionalProperties struct {
+ A bool `query:"a"`
+ Extras map[string]interface{} `query:"-,inline"`
+}
+
+type Recursive struct {
+ Name string `query:"name"`
+ Child *Recursive `query:"child"`
+}
+
+type UnknownStruct struct {
+ Unknown interface{} `query:"unknown"`
+}
+
+type UnionStruct struct {
+ Union Union `query:"union" format:"date"`
+}
+
+type Union interface {
+ union()
+}
+
+type UnionInteger int64
+
+func (UnionInteger) union() {}
+
+type UnionString string
+
+func (UnionString) union() {}
+
+type UnionStructA struct {
+ Type string `query:"type"`
+ A string `query:"a"`
+ B string `query:"b"`
+}
+
+func (UnionStructA) union() {}
+
+type UnionStructB struct {
+ Type string `query:"type"`
+ A string `query:"a"`
+}
+
+func (UnionStructB) union() {}
+
+type UnionTime time.Time
+
+func (UnionTime) union() {}
+
+type DeeplyNested struct {
+ A DeeplyNested1 `query:"a"`
+}
+
+type DeeplyNested1 struct {
+ B DeeplyNested2 `query:"b"`
+}
+
+type DeeplyNested2 struct {
+ C DeeplyNested3 `query:"c"`
+}
+
+type DeeplyNested3 struct {
+ D *string `query:"d"`
+}
+
+var tests = map[string]struct {
+ enc string
+ val interface{}
+ settings QuerySettings
+}{
+ "primitives": {
+ "a=false&b=237628372683&c=654&d=9999.43&e=43.7599983215332&f=1,2,3,4",
+ Primitives{A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ QuerySettings{},
+ },
+
+ "slices_brackets": {
+ `mixed[]=1&mixed[]=2.3&mixed[]=hello&slices[][a]=false&slices[][a]=false&slices[][b]=237628372683&slices[][b]=237628372683&slices[][c]=654&slices[][c]=654&slices[][d]=9999.43&slices[][d]=9999.43&slices[][e]=43.7599983215332&slices[][e]=43.7599983215332&slices[][f][]=1&slices[][f][]=2&slices[][f][]=3&slices[][f][]=4&slices[][f][]=1&slices[][f][]=2&slices[][f][]=3&slices[][f][]=4`,
+ Slices{
+ Slice: []Primitives{
+ {A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ {A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ },
+ Mixed: []interface{}{1, 2.3, "hello"},
+ },
+ QuerySettings{ArrayFormat: ArrayQueryFormatBrackets},
+ },
+
+ "slices_comma": {
+ `mixed=1,2.3,hello`,
+ Slices{
+ Mixed: []interface{}{1, 2.3, "hello"},
+ },
+ QuerySettings{ArrayFormat: ArrayQueryFormatComma},
+ },
+
+ "slices_repeat": {
+ `mixed=1&mixed=2.3&mixed=hello&slices[a]=false&slices[a]=false&slices[b]=237628372683&slices[b]=237628372683&slices[c]=654&slices[c]=654&slices[d]=9999.43&slices[d]=9999.43&slices[e]=43.7599983215332&slices[e]=43.7599983215332&slices[f]=1&slices[f]=2&slices[f]=3&slices[f]=4&slices[f]=1&slices[f]=2&slices[f]=3&slices[f]=4`,
+ Slices{
+ Slice: []Primitives{
+ {A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ {A: false, B: 237628372683, C: uint(654), D: 9999.43, E: 43.76, F: []int{1, 2, 3, 4}},
+ },
+ Mixed: []interface{}{1, 2.3, "hello"},
+ },
+ QuerySettings{ArrayFormat: ArrayQueryFormatRepeat},
+ },
+
+ "primitive_pointer_struct": {
+ "a=false&b=237628372683&c=654&d=9999.43&e=43.7599983215332&f=1,2,3,4,5",
+ PrimitivePointers{
+ A: P(false),
+ B: P(237628372683),
+ C: P(uint(654)),
+ D: P(9999.43),
+ E: P(float32(43.76)),
+ F: &[]int{1, 2, 3, 4, 5},
+ },
+ QuerySettings{},
+ },
+
+ "datetime_struct": {
+ `date=2006-01-02&date-time=2006-01-02T15:04:05Z`,
+ DateTime{
+ Date: time.Date(2006, time.January, 2, 0, 0, 0, 0, time.UTC),
+ DateTime: time.Date(2006, time.January, 2, 15, 4, 5, 0, time.UTC),
+ },
+ QuerySettings{},
+ },
+
+ "additional_properties": {
+ `a=true&bar=value&foo=true`,
+ AdditionalProperties{
+ A: true,
+ Extras: map[string]interface{}{
+ "bar": "value",
+ "foo": true,
+ },
+ },
+ QuerySettings{},
+ },
+
+ "recursive_struct_brackets": {
+ `child[name]=Alex&name=Robert`,
+ Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}},
+ QuerySettings{NestedFormat: NestedQueryFormatBrackets},
+ },
+
+ "recursive_struct_dots": {
+ `child.name=Alex&name=Robert`,
+ Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}},
+ QuerySettings{NestedFormat: NestedQueryFormatDots},
+ },
+
+ "unknown_struct_number": {
+ `unknown=12`,
+ UnknownStruct{
+ Unknown: 12.,
+ },
+ QuerySettings{},
+ },
+
+ "unknown_struct_map_brackets": {
+ `unknown[foo]=bar`,
+ UnknownStruct{
+ Unknown: map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatBrackets},
+ },
+
+ "unknown_struct_map_dots": {
+ `unknown.foo=bar`,
+ UnknownStruct{
+ Unknown: map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatDots},
+ },
+
+ "union_string": {
+ `union=hello`,
+ UnionStruct{
+ Union: UnionString("hello"),
+ },
+ QuerySettings{},
+ },
+
+ "union_integer": {
+ `union=12`,
+ UnionStruct{
+ Union: UnionInteger(12),
+ },
+ QuerySettings{},
+ },
+
+ "union_struct_discriminated_a": {
+ `union[a]=foo&union[b]=bar&union[type]=typeA`,
+ UnionStruct{
+ Union: UnionStructA{
+ Type: "typeA",
+ A: "foo",
+ B: "bar",
+ },
+ },
+ QuerySettings{},
+ },
+
+ "union_struct_discriminated_b": {
+ `union[a]=foo&union[type]=typeB`,
+ UnionStruct{
+ Union: UnionStructB{
+ Type: "typeB",
+ A: "foo",
+ },
+ },
+ QuerySettings{},
+ },
+
+ "union_struct_time": {
+ `union=2010-05-23`,
+ UnionStruct{
+ Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)),
+ },
+ QuerySettings{},
+ },
+
+ "deeply_nested_brackets": {
+ `a[b][c][d]=hello`,
+ DeeplyNested{
+ A: DeeplyNested1{
+ B: DeeplyNested2{
+ C: DeeplyNested3{
+ D: P("hello"),
+ },
+ },
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatBrackets},
+ },
+
+ "deeply_nested_dots": {
+ `a.b.c.d=hello`,
+ DeeplyNested{
+ A: DeeplyNested1{
+ B: DeeplyNested2{
+ C: DeeplyNested3{
+ D: P("hello"),
+ },
+ },
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatDots},
+ },
+
+ "deeply_nested_brackets_empty": {
+ ``,
+ DeeplyNested{
+ A: DeeplyNested1{
+ B: DeeplyNested2{
+ C: DeeplyNested3{
+ D: nil,
+ },
+ },
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatBrackets},
+ },
+
+ "deeply_nested_dots_empty": {
+ ``,
+ DeeplyNested{
+ A: DeeplyNested1{
+ B: DeeplyNested2{
+ C: DeeplyNested3{
+ D: nil,
+ },
+ },
+ },
+ },
+ QuerySettings{NestedFormat: NestedQueryFormatDots},
+ },
+}
+
+func TestEncode(t *testing.T) {
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ values := MarshalWithSettings(test.val, test.settings)
+ str, _ := url.QueryUnescape(values.Encode())
+ if str != test.enc {
+ t.Fatalf("expected %+#v to serialize to %s but got %s", test.val, test.enc, str)
+ }
+ })
+ }
+}
diff --git a/packages/sdk/go/internal/apiquery/tag.go b/packages/sdk/go/internal/apiquery/tag.go
new file mode 100644
index 000000000..7ccd739c2
--- /dev/null
+++ b/packages/sdk/go/internal/apiquery/tag.go
@@ -0,0 +1,41 @@
+package apiquery
+
+import (
+ "reflect"
+ "strings"
+)
+
+const queryStructTag = "query"
+const formatStructTag = "format"
+
+type parsedStructTag struct {
+ name string
+ omitempty bool
+ inline bool
+}
+
+func parseQueryStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
+ raw, ok := field.Tag.Lookup(queryStructTag)
+ if !ok {
+ return
+ }
+ parts := strings.Split(raw, ",")
+ if len(parts) == 0 {
+ return tag, false
+ }
+ tag.name = parts[0]
+ for _, part := range parts[1:] {
+ switch part {
+ case "omitempty":
+ tag.omitempty = true
+ case "inline":
+ tag.inline = true
+ }
+ }
+ return
+}
+
+func parseFormatStructTag(field reflect.StructField) (format string, ok bool) {
+ format, ok = field.Tag.Lookup(formatStructTag)
+ return
+}
diff --git a/packages/sdk/go/internal/param/field.go b/packages/sdk/go/internal/param/field.go
new file mode 100644
index 000000000..4d0fd9c6f
--- /dev/null
+++ b/packages/sdk/go/internal/param/field.go
@@ -0,0 +1,29 @@
+package param
+
+import (
+ "fmt"
+)
+
+type FieldLike interface{ field() }
+
+// Field is a wrapper used for all values sent to the API,
+// to distinguish zero values from null or omitted fields.
+//
+// It also allows sending arbitrary deserializable values.
+//
+// To instantiate a Field, use the helpers exported from
+// the package root: `F()`, `Null()`, `Raw()`, etc.
+type Field[T any] struct {
+ FieldLike
+ Value T
+ Null bool
+ Present bool
+ Raw any
+}
+
+func (f Field[T]) String() string {
+ if s, ok := any(f.Value).(fmt.Stringer); ok {
+ return s.String()
+ }
+ return fmt.Sprintf("%v", f.Value)
+}
diff --git a/packages/sdk/go/internal/requestconfig/requestconfig.go b/packages/sdk/go/internal/requestconfig/requestconfig.go
new file mode 100644
index 000000000..91b70cca5
--- /dev/null
+++ b/packages/sdk/go/internal/requestconfig/requestconfig.go
@@ -0,0 +1,629 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package requestconfig
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "math"
+ "math/rand"
+ "mime"
+ "net/http"
+ "net/url"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/sst/opencode-sdk-go/internal"
+ "github.com/sst/opencode-sdk-go/internal/apierror"
+ "github.com/sst/opencode-sdk-go/internal/apiform"
+ "github.com/sst/opencode-sdk-go/internal/apiquery"
+ "github.com/sst/opencode-sdk-go/internal/param"
+)
+
+func getDefaultHeaders() map[string]string {
+ return map[string]string{
+ "User-Agent": fmt.Sprintf("Opencode/Go %s", internal.PackageVersion),
+ }
+}
+
+func getNormalizedOS() string {
+ switch runtime.GOOS {
+ case "ios":
+ return "iOS"
+ case "android":
+ return "Android"
+ case "darwin":
+ return "MacOS"
+ case "window":
+ return "Windows"
+ case "freebsd":
+ return "FreeBSD"
+ case "openbsd":
+ return "OpenBSD"
+ case "linux":
+ return "Linux"
+ default:
+ return fmt.Sprintf("Other:%s", runtime.GOOS)
+ }
+}
+
+func getNormalizedArchitecture() string {
+ switch runtime.GOARCH {
+ case "386":
+ return "x32"
+ case "amd64":
+ return "x64"
+ case "arm":
+ return "arm"
+ case "arm64":
+ return "arm64"
+ default:
+ return fmt.Sprintf("other:%s", runtime.GOARCH)
+ }
+}
+
+func getPlatformProperties() map[string]string {
+ return map[string]string{
+ "X-Stainless-Lang": "go",
+ "X-Stainless-Package-Version": internal.PackageVersion,
+ "X-Stainless-OS": getNormalizedOS(),
+ "X-Stainless-Arch": getNormalizedArchitecture(),
+ "X-Stainless-Runtime": "go",
+ "X-Stainless-Runtime-Version": runtime.Version(),
+ }
+}
+
+type RequestOption interface {
+ Apply(*RequestConfig) error
+}
+
+type RequestOptionFunc func(*RequestConfig) error
+type PreRequestOptionFunc func(*RequestConfig) error
+
+func (s RequestOptionFunc) Apply(r *RequestConfig) error { return s(r) }
+func (s PreRequestOptionFunc) Apply(r *RequestConfig) error { return s(r) }
+
+func NewRequestConfig(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...RequestOption) (*RequestConfig, error) {
+ var reader io.Reader
+
+ contentType := "application/json"
+ hasSerializationFunc := false
+
+ if body, ok := body.(json.Marshaler); ok {
+ content, err := body.MarshalJSON()
+ if err != nil {
+ return nil, err
+ }
+ reader = bytes.NewBuffer(content)
+ hasSerializationFunc = true
+ }
+ if body, ok := body.(apiform.Marshaler); ok {
+ var (
+ content []byte
+ err error
+ )
+ content, contentType, err = body.MarshalMultipart()
+ if err != nil {
+ return nil, err
+ }
+ reader = bytes.NewBuffer(content)
+ hasSerializationFunc = true
+ }
+ if body, ok := body.(apiquery.Queryer); ok {
+ hasSerializationFunc = true
+ params := body.URLQuery().Encode()
+ if params != "" {
+ u = u + "?" + params
+ }
+ }
+ if body, ok := body.([]byte); ok {
+ reader = bytes.NewBuffer(body)
+ hasSerializationFunc = true
+ }
+ if body, ok := body.(io.Reader); ok {
+ reader = body
+ hasSerializationFunc = true
+ }
+
+ // Fallback to json serialization if none of the serialization functions that we expect
+ // to see is present.
+ if body != nil && !hasSerializationFunc {
+ content, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ reader = bytes.NewBuffer(content)
+ }
+
+ req, err := http.NewRequestWithContext(ctx, method, u, nil)
+ if err != nil {
+ return nil, err
+ }
+ if reader != nil {
+ req.Header.Set("Content-Type", contentType)
+ }
+
+ req.Header.Set("Accept", "application/json")
+ req.Header.Set("X-Stainless-Retry-Count", "0")
+ req.Header.Set("X-Stainless-Timeout", "0")
+ for k, v := range getDefaultHeaders() {
+ req.Header.Add(k, v)
+ }
+
+ for k, v := range getPlatformProperties() {
+ req.Header.Add(k, v)
+ }
+ cfg := RequestConfig{
+ MaxRetries: 2,
+ Context: ctx,
+ Request: req,
+ HTTPClient: http.DefaultClient,
+ Body: reader,
+ }
+ cfg.ResponseBodyInto = dst
+ err = cfg.Apply(opts...)
+ if err != nil {
+ return nil, err
+ }
+
+ // This must run after `cfg.Apply(...)` above in case the request timeout gets modified. We also only
+ // apply our own logic for it if it's still "0" from above. If it's not, then it was deleted or modified
+ // by the user and we should respect that.
+ if req.Header.Get("X-Stainless-Timeout") == "0" {
+ if cfg.RequestTimeout == time.Duration(0) {
+ req.Header.Del("X-Stainless-Timeout")
+ } else {
+ req.Header.Set("X-Stainless-Timeout", strconv.Itoa(int(cfg.RequestTimeout.Seconds())))
+ }
+ }
+
+ return &cfg, nil
+}
+
+func UseDefaultParam[T any](dst *param.Field[T], src *T) {
+ if !dst.Present && src != nil {
+ dst.Value = *src
+ dst.Present = true
+ }
+}
+
+// This interface is primarily used to describe an [*http.Client], but also
+// supports custom HTTP implementations.
+type HTTPDoer interface {
+ Do(req *http.Request) (*http.Response, error)
+}
+
+// RequestConfig represents all the state related to one request.
+//
+// Editing the variables inside RequestConfig directly is unstable api. Prefer
+// composing the RequestOption instead if possible.
+type RequestConfig struct {
+ MaxRetries int
+ RequestTimeout time.Duration
+ Context context.Context
+ Request *http.Request
+ BaseURL *url.URL
+ // DefaultBaseURL will be used if BaseURL is not explicitly overridden using
+ // WithBaseURL.
+ DefaultBaseURL *url.URL
+ CustomHTTPDoer HTTPDoer
+ HTTPClient *http.Client
+ Middlewares []middleware
+ // If ResponseBodyInto not nil, then we will attempt to deserialize into
+ // ResponseBodyInto. If Destination is a []byte, then it will return the body as
+ // is.
+ ResponseBodyInto interface{}
+ // ResponseInto copies the \*http.Response of the corresponding request into the
+ // given address
+ ResponseInto **http.Response
+ Body io.Reader
+}
+
+// middleware is exactly the same type as the Middleware type found in the [option] package,
+// but it is redeclared here for circular dependency issues.
+type middleware = func(*http.Request, middlewareNext) (*http.Response, error)
+
+// middlewareNext is exactly the same type as the MiddlewareNext type found in the [option] package,
+// but it is redeclared here for circular dependency issues.
+type middlewareNext = func(*http.Request) (*http.Response, error)
+
+func applyMiddleware(middleware middleware, next middlewareNext) middlewareNext {
+ return func(req *http.Request) (res *http.Response, err error) {
+ return middleware(req, next)
+ }
+}
+
+func shouldRetry(req *http.Request, res *http.Response) bool {
+ // If there is no way to recover the Body, then we shouldn't retry.
+ if req.Body != nil && req.GetBody == nil {
+ return false
+ }
+
+ // If there is no response, that indicates that there is a connection error
+ // so we retry the request.
+ if res == nil {
+ return true
+ }
+
+ // If the header explicitly wants a retry behavior, respect that over the
+ // http status code.
+ if res.Header.Get("x-should-retry") == "true" {
+ return true
+ }
+ if res.Header.Get("x-should-retry") == "false" {
+ return false
+ }
+
+ return res.StatusCode == http.StatusRequestTimeout ||
+ res.StatusCode == http.StatusConflict ||
+ res.StatusCode == http.StatusTooManyRequests ||
+ res.StatusCode >= http.StatusInternalServerError
+}
+
+func parseRetryAfterHeader(resp *http.Response) (time.Duration, bool) {
+ if resp == nil {
+ return 0, false
+ }
+
+ type retryData struct {
+ header string
+ units time.Duration
+
+ // custom is used when the regular algorithm failed and is optional.
+ // the returned duration is used verbatim (units is not applied).
+ custom func(string) (time.Duration, bool)
+ }
+
+ nop := func(string) (time.Duration, bool) { return 0, false }
+
+ // the headers are listed in order of preference
+ retries := []retryData{
+ {
+ header: "Retry-After-Ms",
+ units: time.Millisecond,
+ custom: nop,
+ },
+ {
+ header: "Retry-After",
+ units: time.Second,
+
+ // retry-after values are expressed in either number of
+ // seconds or an HTTP-date indicating when to try again
+ custom: func(ra string) (time.Duration, bool) {
+ t, err := time.Parse(time.RFC1123, ra)
+ if err != nil {
+ return 0, false
+ }
+ return time.Until(t), true
+ },
+ },
+ }
+
+ for _, retry := range retries {
+ v := resp.Header.Get(retry.header)
+ if v == "" {
+ continue
+ }
+ if retryAfter, err := strconv.ParseFloat(v, 64); err == nil {
+ return time.Duration(retryAfter * float64(retry.units)), true
+ }
+ if d, ok := retry.custom(v); ok {
+ return d, true
+ }
+ }
+
+ return 0, false
+}
+
+// isBeforeContextDeadline reports whether the non-zero Time t is
+// before ctx's deadline. If ctx does not have a deadline, it
+// always reports true (the deadline is considered infinite).
+func isBeforeContextDeadline(t time.Time, ctx context.Context) bool {
+ d, ok := ctx.Deadline()
+ if !ok {
+ return true
+ }
+ return t.Before(d)
+}
+
+// bodyWithTimeout is an io.ReadCloser which can observe a context's cancel func
+// to handle timeouts etc. It wraps an existing io.ReadCloser.
+type bodyWithTimeout struct {
+ stop func() // stops the time.Timer waiting to cancel the request
+ rc io.ReadCloser
+}
+
+func (b *bodyWithTimeout) Read(p []byte) (n int, err error) {
+ n, err = b.rc.Read(p)
+ if err == nil {
+ return n, nil
+ }
+ if err == io.EOF {
+ return n, err
+ }
+ return n, err
+}
+
+func (b *bodyWithTimeout) Close() error {
+ err := b.rc.Close()
+ b.stop()
+ return err
+}
+
+func retryDelay(res *http.Response, retryCount int) time.Duration {
+ // If the API asks us to wait a certain amount of time (and it's a reasonable amount),
+ // just do what it says.
+
+ if retryAfterDelay, ok := parseRetryAfterHeader(res); ok && 0 <= retryAfterDelay && retryAfterDelay < time.Minute {
+ return retryAfterDelay
+ }
+
+ maxDelay := 8 * time.Second
+ delay := time.Duration(0.5 * float64(time.Second) * math.Pow(2, float64(retryCount)))
+ if delay > maxDelay {
+ delay = maxDelay
+ }
+
+ jitter := rand.Int63n(int64(delay / 4))
+ delay -= time.Duration(jitter)
+ return delay
+}
+
+func (cfg *RequestConfig) Execute() (err error) {
+ if cfg.BaseURL == nil {
+ if cfg.DefaultBaseURL != nil {
+ cfg.BaseURL = cfg.DefaultBaseURL
+ } else {
+ return fmt.Errorf("requestconfig: base url is not set")
+ }
+ }
+
+ cfg.Request.URL, err = cfg.BaseURL.Parse(strings.TrimLeft(cfg.Request.URL.String(), "/"))
+ if err != nil {
+ return err
+ }
+
+ if cfg.Body != nil && cfg.Request.Body == nil {
+ switch body := cfg.Body.(type) {
+ case *bytes.Buffer:
+ b := body.Bytes()
+ cfg.Request.ContentLength = int64(body.Len())
+ cfg.Request.GetBody = func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(b)), nil }
+ cfg.Request.Body, _ = cfg.Request.GetBody()
+ case *bytes.Reader:
+ cfg.Request.ContentLength = int64(body.Len())
+ cfg.Request.GetBody = func() (io.ReadCloser, error) {
+ _, err := body.Seek(0, 0)
+ return io.NopCloser(body), err
+ }
+ cfg.Request.Body, _ = cfg.Request.GetBody()
+ default:
+ if rc, ok := body.(io.ReadCloser); ok {
+ cfg.Request.Body = rc
+ } else {
+ cfg.Request.Body = io.NopCloser(body)
+ }
+ }
+ }
+
+ handler := cfg.HTTPClient.Do
+ if cfg.CustomHTTPDoer != nil {
+ handler = cfg.CustomHTTPDoer.Do
+ }
+ for i := len(cfg.Middlewares) - 1; i >= 0; i -= 1 {
+ handler = applyMiddleware(cfg.Middlewares[i], handler)
+ }
+
+ // Don't send the current retry count in the headers if the caller modified the header defaults.
+ shouldSendRetryCount := cfg.Request.Header.Get("X-Stainless-Retry-Count") == "0"
+
+ var res *http.Response
+ var cancel context.CancelFunc
+ for retryCount := 0; retryCount <= cfg.MaxRetries; retryCount += 1 {
+ ctx := cfg.Request.Context()
+ if cfg.RequestTimeout != time.Duration(0) && isBeforeContextDeadline(time.Now().Add(cfg.RequestTimeout), ctx) {
+ ctx, cancel = context.WithTimeout(ctx, cfg.RequestTimeout)
+ defer func() {
+ // The cancel function is nil if it was handed off to be handled in a different scope.
+ if cancel != nil {
+ cancel()
+ }
+ }()
+ }
+
+ req := cfg.Request.Clone(ctx)
+ if shouldSendRetryCount {
+ req.Header.Set("X-Stainless-Retry-Count", strconv.Itoa(retryCount))
+ }
+
+ res, err = handler(req)
+ if ctx != nil && ctx.Err() != nil {
+ return ctx.Err()
+ }
+ if !shouldRetry(cfg.Request, res) || retryCount >= cfg.MaxRetries {
+ break
+ }
+
+ // Prepare next request and wait for the retry delay
+ if cfg.Request.GetBody != nil {
+ cfg.Request.Body, err = cfg.Request.GetBody()
+ if err != nil {
+ return err
+ }
+ }
+
+ // Can't actually refresh the body, so we don't attempt to retry here
+ if cfg.Request.GetBody == nil && cfg.Request.Body != nil {
+ break
+ }
+
+ time.Sleep(retryDelay(res, retryCount))
+ }
+
+ // Save *http.Response if it is requested to, even if there was an error making the request. This is
+ // useful in cases where you might want to debug by inspecting the response. Note that if err != nil,
+ // the response should be generally be empty, but there are edge cases.
+ if cfg.ResponseInto != nil {
+ *cfg.ResponseInto = res
+ }
+ if responseBodyInto, ok := cfg.ResponseBodyInto.(**http.Response); ok {
+ *responseBodyInto = res
+ }
+
+ // If there was a connection error in the final request or any other transport error,
+ // return that early without trying to coerce into an APIError.
+ if err != nil {
+ return err
+ }
+
+ if res.StatusCode >= 400 {
+ contents, err := io.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ return err
+ }
+
+ // If there is an APIError, re-populate the response body so that debugging
+ // utilities can conveniently dump the response without issue.
+ res.Body = io.NopCloser(bytes.NewBuffer(contents))
+
+ // Load the contents into the error format if it is provided.
+ aerr := apierror.Error{Request: cfg.Request, Response: res, StatusCode: res.StatusCode}
+ err = aerr.UnmarshalJSON(contents)
+ if err != nil {
+ return err
+ }
+ return &aerr
+ }
+
+ _, intoCustomResponseBody := cfg.ResponseBodyInto.(**http.Response)
+ if cfg.ResponseBodyInto == nil || intoCustomResponseBody {
+ // We aren't reading the response body in this scope, but whoever is will need the
+ // cancel func from the context to observe request timeouts.
+ // Put the cancel function in the response body so it can be handled elsewhere.
+ if cancel != nil {
+ res.Body = &bodyWithTimeout{rc: res.Body, stop: cancel}
+ cancel = nil
+ }
+ return nil
+ }
+
+ contents, err := io.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ return fmt.Errorf("error reading response body: %w", err)
+ }
+
+ // If we are not json, return plaintext
+ contentType := res.Header.Get("content-type")
+ mediaType, _, _ := mime.ParseMediaType(contentType)
+ isJSON := strings.Contains(mediaType, "application/json") || strings.HasSuffix(mediaType, "+json")
+ if !isJSON {
+ switch dst := cfg.ResponseBodyInto.(type) {
+ case *string:
+ *dst = string(contents)
+ case **string:
+ tmp := string(contents)
+ *dst = &tmp
+ case *[]byte:
+ *dst = contents
+ default:
+ return fmt.Errorf("expected destination type of 'string' or '[]byte' for responses with content-type '%s' that is not 'application/json'", contentType)
+ }
+ return nil
+ }
+
+ switch dst := cfg.ResponseBodyInto.(type) {
+ // If the response happens to be a byte array, deserialize the body as-is.
+ case *[]byte:
+ *dst = contents
+ default:
+ err = json.NewDecoder(bytes.NewReader(contents)).Decode(cfg.ResponseBodyInto)
+ if err != nil {
+ return fmt.Errorf("error parsing response json: %w", err)
+ }
+ }
+
+ return nil
+}
+
+func ExecuteNewRequest(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...RequestOption) error {
+ cfg, err := NewRequestConfig(ctx, method, u, body, dst, opts...)
+ if err != nil {
+ return err
+ }
+ return cfg.Execute()
+}
+
+func (cfg *RequestConfig) Clone(ctx context.Context) *RequestConfig {
+ if cfg == nil {
+ return nil
+ }
+ req := cfg.Request.Clone(ctx)
+ var err error
+ if req.Body != nil {
+ req.Body, err = req.GetBody()
+ }
+ if err != nil {
+ return nil
+ }
+ new := &RequestConfig{
+ MaxRetries: cfg.MaxRetries,
+ RequestTimeout: cfg.RequestTimeout,
+ Context: ctx,
+ Request: req,
+ BaseURL: cfg.BaseURL,
+ HTTPClient: cfg.HTTPClient,
+ Middlewares: cfg.Middlewares,
+ }
+
+ return new
+}
+
+func (cfg *RequestConfig) Apply(opts ...RequestOption) error {
+ for _, opt := range opts {
+ err := opt.Apply(cfg)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// PreRequestOptions is used to collect all the options which need to be known before
+// a call to [RequestConfig.ExecuteNewRequest], such as path parameters
+// or global defaults.
+// PreRequestOptions will return a [RequestConfig] with the options applied.
+//
+// Only request option functions of type [PreRequestOptionFunc] are applied.
+func PreRequestOptions(opts ...RequestOption) (RequestConfig, error) {
+ cfg := RequestConfig{}
+ for _, opt := range opts {
+ if opt, ok := opt.(PreRequestOptionFunc); ok {
+ err := opt.Apply(&cfg)
+ if err != nil {
+ return cfg, err
+ }
+ }
+ }
+ return cfg, nil
+}
+
+// WithDefaultBaseURL returns a RequestOption that sets the client's default Base URL.
+// This is always overridden by setting a base URL with WithBaseURL.
+// WithBaseURL should be used instead of WithDefaultBaseURL except in internal code.
+func WithDefaultBaseURL(baseURL string) RequestOption {
+ u, err := url.Parse(baseURL)
+ return RequestOptionFunc(func(r *RequestConfig) error {
+ if err != nil {
+ return err
+ }
+ r.DefaultBaseURL = u
+ return nil
+ })
+}
diff --git a/packages/sdk/go/internal/testutil/testutil.go b/packages/sdk/go/internal/testutil/testutil.go
new file mode 100644
index 000000000..826d266f2
--- /dev/null
+++ b/packages/sdk/go/internal/testutil/testutil.go
@@ -0,0 +1,27 @@
+package testutil
+
+import (
+ "net/http"
+ "os"
+ "strconv"
+ "testing"
+)
+
+func CheckTestServer(t *testing.T, url string) bool {
+ if _, err := http.Get(url); err != nil {
+ const SKIP_MOCK_TESTS = "SKIP_MOCK_TESTS"
+ if str, ok := os.LookupEnv(SKIP_MOCK_TESTS); ok {
+ skip, err := strconv.ParseBool(str)
+ if err != nil {
+ t.Fatalf("strconv.ParseBool(os.LookupEnv(%s)) failed: %s", SKIP_MOCK_TESTS, err)
+ }
+ if skip {
+ t.Skip("The test will not run without a mock Prism server running against your OpenAPI spec")
+ return false
+ }
+ t.Errorf("The test will not run without a mock Prism server running against your OpenAPI spec. You can set the environment variable %s to true to skip running any tests that require the mock server", SKIP_MOCK_TESTS)
+ return false
+ }
+ }
+ return true
+}
diff --git a/packages/sdk/go/internal/version.go b/packages/sdk/go/internal/version.go
new file mode 100644
index 000000000..64dcebbb4
--- /dev/null
+++ b/packages/sdk/go/internal/version.go
@@ -0,0 +1,5 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package internal
+
+const PackageVersion = "0.1.0-alpha.8" // x-release-please-version
diff --git a/packages/sdk/src/lib/.keep b/packages/sdk/go/lib/.keep
index 7554f8b20..5e2c99fdb 100644
--- a/packages/sdk/src/lib/.keep
+++ b/packages/sdk/go/lib/.keep
@@ -1,4 +1,4 @@
File generated from our OpenAPI spec by Stainless.
This directory can be used to store custom files to expand the SDK.
-It is ignored by Stainless code generation and its content (other than this keep file) won't be touched.
+It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file
diff --git a/packages/sdk/go/option/middleware.go b/packages/sdk/go/option/middleware.go
new file mode 100644
index 000000000..8ec9dd60b
--- /dev/null
+++ b/packages/sdk/go/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/packages/sdk/go/option/requestoption.go b/packages/sdk/go/option/requestoption.go
new file mode 100644
index 000000000..68478066b
--- /dev/null
+++ b/packages/sdk/go/option/requestoption.go
@@ -0,0 +1,267 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package option
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/tidwall/sjson"
+)
+
+// RequestOption is an option for the requests made by the opencode API Client
+// which can be supplied to clients, services, and methods. You can read more about this functional
+// options pattern in our [README].
+//
+// [README]: https://pkg.go.dev/github.com/sst/opencode-sdk-go#readme-requestoptions
+type RequestOption = requestconfig.RequestOption
+
+// WithBaseURL returns a RequestOption that sets the BaseURL for the client.
+//
+// For security reasons, ensure that the base URL is trusted.
+func WithBaseURL(base string) RequestOption {
+ u, err := url.Parse(base)
+ if err == nil && u.Path != "" && !strings.HasSuffix(u.Path, "/") {
+ u.Path += "/"
+ }
+
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ if err != nil {
+ return fmt.Errorf("requestoption: WithBaseURL failed to parse url %s", err)
+ }
+
+ r.BaseURL = u
+ return nil
+ })
+}
+
+// HTTPClient is primarily used to describe an [*http.Client], but also
+// supports custom implementations.
+//
+// For bespoke implementations, prefer using an [*http.Client] with a
+// custom transport. See [http.RoundTripper] for further information.
+type HTTPClient interface {
+ Do(*http.Request) (*http.Response, error)
+}
+
+// WithHTTPClient returns a RequestOption that changes the underlying http client used to make this
+// request, which by default is [http.DefaultClient].
+//
+// For custom uses cases, it is recommended to provide an [*http.Client] with a custom
+// [http.RoundTripper] as its transport, rather than directly implementing [HTTPClient].
+func WithHTTPClient(client HTTPClient) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ if client == nil {
+ return fmt.Errorf("requestoption: custom http client cannot be nil")
+ }
+
+ if c, ok := client.(*http.Client); ok {
+ // Prefer the native client if possible.
+ r.HTTPClient = c
+ r.CustomHTTPDoer = nil
+ } else {
+ r.CustomHTTPDoer = client
+ }
+
+ return nil
+ })
+}
+
+// MiddlewareNext is a function which is called by a middleware to pass an HTTP request
+// to the next stage in the middleware chain.
+type MiddlewareNext = func(*http.Request) (*http.Response, error)
+
+// Middleware is a function which intercepts HTTP requests, processing or modifying
+// them, and then passing the request to the next middleware or handler
+// in the chain by calling the provided MiddlewareNext function.
+type Middleware = func(*http.Request, MiddlewareNext) (*http.Response, error)
+
+// WithMiddleware returns a RequestOption that applies the given middleware
+// to the requests made. Each middleware will execute in the order they were given.
+func WithMiddleware(middlewares ...Middleware) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.Middlewares = append(r.Middlewares, middlewares...)
+ return nil
+ })
+}
+
+// WithMaxRetries returns a RequestOption that sets the maximum number of retries that the client
+// attempts to make. When given 0, the client only makes one request. By
+// default, the client retries two times.
+//
+// WithMaxRetries panics when retries is negative.
+func WithMaxRetries(retries int) RequestOption {
+ if retries < 0 {
+ panic("option: cannot have fewer than 0 retries")
+ }
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.MaxRetries = retries
+ return nil
+ })
+}
+
+// WithHeader returns a RequestOption that sets the header value to the associated key. It overwrites
+// any value if there was one already present.
+func WithHeader(key, value string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.Request.Header.Set(key, value)
+ return nil
+ })
+}
+
+// WithHeaderAdd returns a RequestOption that adds the header value to the associated key. It appends
+// onto any existing values.
+func WithHeaderAdd(key, value string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.Request.Header.Add(key, value)
+ return nil
+ })
+}
+
+// WithHeaderDel returns a RequestOption that deletes the header value(s) associated with the given key.
+func WithHeaderDel(key string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.Request.Header.Del(key)
+ return nil
+ })
+}
+
+// WithQuery returns a RequestOption that sets the query value to the associated key. It overwrites
+// any value if there was one already present.
+func WithQuery(key, value string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ query := r.Request.URL.Query()
+ query.Set(key, value)
+ r.Request.URL.RawQuery = query.Encode()
+ return nil
+ })
+}
+
+// WithQueryAdd returns a RequestOption that adds the query value to the associated key. It appends
+// onto any existing values.
+func WithQueryAdd(key, value string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ query := r.Request.URL.Query()
+ query.Add(key, value)
+ r.Request.URL.RawQuery = query.Encode()
+ return nil
+ })
+}
+
+// WithQueryDel returns a RequestOption that deletes the query value(s) associated with the key.
+func WithQueryDel(key string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ query := r.Request.URL.Query()
+ query.Del(key)
+ r.Request.URL.RawQuery = query.Encode()
+ return nil
+ })
+}
+
+// WithJSONSet returns a RequestOption that sets the body's JSON value associated with the key.
+// The key accepts a string as defined by the [sjson format].
+//
+// [sjson format]: https://github.com/tidwall/sjson
+func WithJSONSet(key string, value interface{}) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
+ var b []byte
+
+ if r.Body == nil {
+ b, err = sjson.SetBytes(nil, key, value)
+ if err != nil {
+ return err
+ }
+ } else if buffer, ok := r.Body.(*bytes.Buffer); ok {
+ b = buffer.Bytes()
+ b, err = sjson.SetBytes(b, key, value)
+ if err != nil {
+ return err
+ }
+ } else {
+ return fmt.Errorf("cannot use WithJSONSet on a body that is not serialized as *bytes.Buffer")
+ }
+
+ r.Body = bytes.NewBuffer(b)
+ return nil
+ })
+}
+
+// WithJSONDel returns a RequestOption that deletes the body's JSON value associated with the key.
+// The key accepts a string as defined by the [sjson format].
+//
+// [sjson format]: https://github.com/tidwall/sjson
+func WithJSONDel(key string) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
+ if buffer, ok := r.Body.(*bytes.Buffer); ok {
+ b := buffer.Bytes()
+ b, err = sjson.DeleteBytes(b, key)
+ if err != nil {
+ return err
+ }
+ r.Body = bytes.NewBuffer(b)
+ return nil
+ }
+
+ return fmt.Errorf("cannot use WithJSONDel on a body that is not serialized as *bytes.Buffer")
+ })
+}
+
+// WithResponseBodyInto returns a RequestOption that overwrites the deserialization target with
+// the given destination. If provided, we don't deserialize into the default struct.
+func WithResponseBodyInto(dst any) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.ResponseBodyInto = dst
+ return nil
+ })
+}
+
+// WithResponseInto returns a RequestOption that copies the [*http.Response] into the given address.
+func WithResponseInto(dst **http.Response) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.ResponseInto = dst
+ return nil
+ })
+}
+
+// WithRequestBody returns a RequestOption that provides a custom serialized body with the given
+// content type.
+//
+// body accepts an io.Reader or raw []bytes.
+func WithRequestBody(contentType string, body any) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ if reader, ok := body.(io.Reader); ok {
+ r.Body = reader
+ return r.Apply(WithHeader("Content-Type", contentType))
+ }
+
+ if b, ok := body.([]byte); ok {
+ r.Body = bytes.NewBuffer(b)
+ return r.Apply(WithHeader("Content-Type", contentType))
+ }
+
+ return fmt.Errorf("body must be a byte slice or implement io.Reader")
+ })
+}
+
+// WithRequestTimeout returns a RequestOption that sets the timeout for
+// each request attempt. This should be smaller than the timeout defined in
+// the context, which spans all retries.
+func WithRequestTimeout(dur time.Duration) RequestOption {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ r.RequestTimeout = dur
+ return nil
+ })
+}
+
+// WithEnvironmentProduction returns a RequestOption that sets the current
+// environment to be the "production" environment. An environment specifies which base URL
+// to use by default.
+func WithEnvironmentProduction() RequestOption {
+ return requestconfig.WithDefaultBaseURL("http://localhost:54321/")
+}
diff --git a/packages/sdk/go/packages/ssestream/ssestream.go b/packages/sdk/go/packages/ssestream/ssestream.go
new file mode 100644
index 000000000..cc0afb7b1
--- /dev/null
+++ b/packages/sdk/go/packages/ssestream/ssestream.go
@@ -0,0 +1,181 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package ssestream
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "io"
+ "net/http"
+ "strings"
+)
+
+type Decoder interface {
+ Event() Event
+ Next() bool
+ Close() error
+ Err() error
+}
+
+func NewDecoder(res *http.Response) Decoder {
+ if res == nil || res.Body == nil {
+ return nil
+ }
+
+ var decoder Decoder
+ contentType := res.Header.Get("content-type")
+ if t, ok := decoderTypes[contentType]; ok {
+ decoder = t(res.Body)
+ } else {
+ scn := bufio.NewScanner(res.Body)
+ scn.Buffer(nil, bufio.MaxScanTokenSize<<9)
+ decoder = &eventStreamDecoder{rc: res.Body, scn: scn}
+ }
+ return decoder
+}
+
+var decoderTypes = map[string](func(io.ReadCloser) Decoder){}
+
+func RegisterDecoder(contentType string, decoder func(io.ReadCloser) Decoder) {
+ decoderTypes[strings.ToLower(contentType)] = decoder
+}
+
+type Event struct {
+ Type string
+ Data []byte
+}
+
+// A base implementation of a Decoder for text/event-stream.
+type eventStreamDecoder struct {
+ evt Event
+ rc io.ReadCloser
+ scn *bufio.Scanner
+ err error
+}
+
+func (s *eventStreamDecoder) Next() bool {
+ if s.err != nil {
+ return false
+ }
+
+ event := ""
+ data := bytes.NewBuffer(nil)
+
+ for s.scn.Scan() {
+ txt := s.scn.Bytes()
+
+ // Dispatch event on an empty line
+ if len(txt) == 0 {
+ s.evt = Event{
+ Type: event,
+ Data: data.Bytes(),
+ }
+ return true
+ }
+
+ // Split a string like "event: bar" into name="event" and value=" bar".
+ name, value, _ := bytes.Cut(txt, []byte(":"))
+
+ // Consume an optional space after the colon if it exists.
+ if len(value) > 0 && value[0] == ' ' {
+ value = value[1:]
+ }
+
+ switch string(name) {
+ case "":
+ // An empty line in the for ": something" is a comment and should be ignored.
+ continue
+ case "event":
+ event = string(value)
+ case "data":
+ _, s.err = data.Write(value)
+ if s.err != nil {
+ break
+ }
+ _, s.err = data.WriteRune('\n')
+ if s.err != nil {
+ break
+ }
+ }
+ }
+
+ if s.scn.Err() != nil {
+ s.err = s.scn.Err()
+ }
+
+ return false
+}
+
+func (s *eventStreamDecoder) Event() Event {
+ return s.evt
+}
+
+func (s *eventStreamDecoder) Close() error {
+ return s.rc.Close()
+}
+
+func (s *eventStreamDecoder) Err() error {
+ return s.err
+}
+
+type Stream[T any] struct {
+ decoder Decoder
+ cur T
+ err error
+}
+
+func NewStream[T any](decoder Decoder, err error) *Stream[T] {
+ return &Stream[T]{
+ decoder: decoder,
+ err: err,
+ }
+}
+
+// Next returns false if the stream has ended or an error occurred.
+// Call Stream.Current() to get the current value.
+// Call Stream.Err() to get the error.
+//
+// for stream.Next() {
+// data := stream.Current()
+// }
+//
+// if stream.Err() != nil {
+// ...
+// }
+func (s *Stream[T]) Next() bool {
+ if s.err != nil {
+ return false
+ }
+
+ for s.decoder.Next() {
+ var nxt T
+ s.err = json.Unmarshal(s.decoder.Event().Data, &nxt)
+ if s.err != nil {
+ return false
+ }
+ s.cur = nxt
+ return true
+ }
+
+ // decoder.Next() may be false because of an error
+ s.err = s.decoder.Err()
+
+ return false
+}
+
+func (s *Stream[T]) Current() T {
+ return s.cur
+}
+
+func (s *Stream[T]) Err() error {
+ return s.err
+}
+
+func (s *Stream[T]) Close() error {
+ if s.decoder == nil {
+ // already closed
+ return nil
+ }
+ return s.decoder.Close()
+}
diff --git a/packages/sdk/release-please-config.json b/packages/sdk/go/release-please-config.json
index 1ebd0bde2..a38198eca 100644
--- a/packages/sdk/release-please-config.json
+++ b/packages/sdk/go/release-please-config.json
@@ -59,6 +59,9 @@
"hidden": true
}
],
- "release-type": "node",
- "extra-files": ["src/version.ts", "README.md"]
-}
+ "release-type": "go",
+ "extra-files": [
+ "internal/version.go",
+ "README.md"
+ ]
+} \ No newline at end of file
diff --git a/packages/sdk/scripts/bootstrap b/packages/sdk/go/scripts/bootstrap
index 0af58e251..d6ac16540 100755
--- a/packages/sdk/scripts/bootstrap
+++ b/packages/sdk/go/scripts/bootstrap
@@ -11,8 +11,6 @@ if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ];
}
fi
-echo "==> Installing Node dependencies…"
+echo "==> Installing Go dependencies…"
-PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm")
-
-$PACKAGE_MANAGER install
+go mod tidy -e
diff --git a/packages/sdk/go/scripts/format b/packages/sdk/go/scripts/format
new file mode 100755
index 000000000..db2a3fa29
--- /dev/null
+++ b/packages/sdk/go/scripts/format
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -e
+
+cd "$(dirname "$0")/.."
+
+echo "==> Running gofmt -s -w"
+gofmt -s -w .
diff --git a/packages/sdk/go/scripts/lint b/packages/sdk/go/scripts/lint
new file mode 100755
index 000000000..7e03a7beb
--- /dev/null
+++ b/packages/sdk/go/scripts/lint
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+set -e
+
+cd "$(dirname "$0")/.."
+
+echo "==> Running Go build"
+go build ./...
+
+echo "==> Checking tests compile"
+go test -run=^$ ./...
diff --git a/packages/sdk/scripts/mock b/packages/sdk/go/scripts/mock
index d2814ae6a..d2814ae6a 100755
--- a/packages/sdk/scripts/mock
+++ b/packages/sdk/go/scripts/mock
diff --git a/packages/sdk/scripts/test b/packages/sdk/go/scripts/test
index 2049e31b0..efebceaee 100755
--- a/packages/sdk/scripts/test
+++ b/packages/sdk/go/scripts/test
@@ -53,4 +53,4 @@ else
fi
echo "==> Running tests"
-./node_modules/.bin/jest "$@"
+go test ./... "$@"
diff --git a/packages/sdk/go/session.go b/packages/sdk/go/session.go
new file mode 100644
index 000000000..2598d51c6
--- /dev/null
+++ b/packages/sdk/go/session.go
@@ -0,0 +1,2117 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "reflect"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+ "github.com/sst/opencode-sdk-go/shared"
+ "github.com/tidwall/gjson"
+)
+
+// SessionService contains methods and other services that help with interacting
+// with the opencode 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 [NewSessionService] method instead.
+type SessionService struct {
+ Options []option.RequestOption
+}
+
+// NewSessionService 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 NewSessionService(opts ...option.RequestOption) (r *SessionService) {
+ r = &SessionService{}
+ r.Options = opts
+ return
+}
+
+// Create a new session
+func (r *SessionService) New(ctx context.Context, opts ...option.RequestOption) (res *Session, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "session"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+// List all sessions
+func (r *SessionService) List(ctx context.Context, opts ...option.RequestOption) (res *[]Session, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "session"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Delete a session and all its data
+func (r *SessionService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, &res, opts...)
+ return
+}
+
+// Abort a session
+func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/abort", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+// Create and send a new message to a session
+func (r *SessionService) Chat(ctx context.Context, id string, body SessionChatParams, opts ...option.RequestOption) (res *AssistantMessage, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/message", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Analyze the app and create an AGENTS.md file
+func (r *SessionService) Init(ctx context.Context, id string, body SessionInitParams, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/init", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// List messages for a session
+func (r *SessionService) Messages(ctx context.Context, id string, opts ...option.RequestOption) (res *[]SessionMessagesResponse, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/message", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// Revert a message
+func (r *SessionService) Revert(ctx context.Context, id string, body SessionRevertParams, opts ...option.RequestOption) (res *Session, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/revert", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Share a session
+func (r *SessionService) Share(ctx context.Context, id string, opts ...option.RequestOption) (res *Session, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/share", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+// Summarize the session
+func (r *SessionService) Summarize(ctx context.Context, id string, body SessionSummarizeParams, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/summarize", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Restore all reverted messages
+func (r *SessionService) Unrevert(ctx context.Context, id string, opts ...option.RequestOption) (res *Session, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/unrevert", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+// Unshare the session
+func (r *SessionService) Unshare(ctx context.Context, id string, opts ...option.RequestOption) (res *Session, err error) {
+ opts = append(r.Options[:], opts...)
+ if id == "" {
+ err = errors.New("missing required id parameter")
+ return
+ }
+ path := fmt.Sprintf("session/%s/share", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, &res, opts...)
+ return
+}
+
+type AssistantMessage struct {
+ ID string `json:"id,required"`
+ Cost float64 `json:"cost,required"`
+ Mode string `json:"mode,required"`
+ ModelID string `json:"modelID,required"`
+ Path AssistantMessagePath `json:"path,required"`
+ ProviderID string `json:"providerID,required"`
+ Role AssistantMessageRole `json:"role,required"`
+ SessionID string `json:"sessionID,required"`
+ System []string `json:"system,required"`
+ Time AssistantMessageTime `json:"time,required"`
+ Tokens AssistantMessageTokens `json:"tokens,required"`
+ Error AssistantMessageError `json:"error"`
+ Summary bool `json:"summary"`
+ JSON assistantMessageJSON `json:"-"`
+}
+
+// assistantMessageJSON contains the JSON metadata for the struct
+// [AssistantMessage]
+type assistantMessageJSON struct {
+ ID apijson.Field
+ Cost apijson.Field
+ Mode apijson.Field
+ ModelID apijson.Field
+ Path apijson.Field
+ ProviderID apijson.Field
+ Role apijson.Field
+ SessionID apijson.Field
+ System apijson.Field
+ Time apijson.Field
+ Tokens apijson.Field
+ Error apijson.Field
+ Summary apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessage) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessageJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r AssistantMessage) implementsMessage() {}
+
+type AssistantMessagePath struct {
+ Cwd string `json:"cwd,required"`
+ Root string `json:"root,required"`
+ JSON assistantMessagePathJSON `json:"-"`
+}
+
+// assistantMessagePathJSON contains the JSON metadata for the struct
+// [AssistantMessagePath]
+type assistantMessagePathJSON struct {
+ Cwd apijson.Field
+ Root apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessagePath) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessagePathJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessageRole string
+
+const (
+ AssistantMessageRoleAssistant AssistantMessageRole = "assistant"
+)
+
+func (r AssistantMessageRole) IsKnown() bool {
+ switch r {
+ case AssistantMessageRoleAssistant:
+ return true
+ }
+ return false
+}
+
+type AssistantMessageTime struct {
+ Created float64 `json:"created,required"`
+ Completed float64 `json:"completed"`
+ JSON assistantMessageTimeJSON `json:"-"`
+}
+
+// assistantMessageTimeJSON contains the JSON metadata for the struct
+// [AssistantMessageTime]
+type assistantMessageTimeJSON struct {
+ Created apijson.Field
+ Completed apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessageTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessageTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessageTokens struct {
+ Cache AssistantMessageTokensCache `json:"cache,required"`
+ Input float64 `json:"input,required"`
+ Output float64 `json:"output,required"`
+ Reasoning float64 `json:"reasoning,required"`
+ JSON assistantMessageTokensJSON `json:"-"`
+}
+
+// assistantMessageTokensJSON contains the JSON metadata for the struct
+// [AssistantMessageTokens]
+type assistantMessageTokensJSON struct {
+ Cache apijson.Field
+ Input apijson.Field
+ Output apijson.Field
+ Reasoning apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessageTokens) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessageTokensJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessageTokensCache struct {
+ Read float64 `json:"read,required"`
+ Write float64 `json:"write,required"`
+ JSON assistantMessageTokensCacheJSON `json:"-"`
+}
+
+// assistantMessageTokensCacheJSON contains the JSON metadata for the struct
+// [AssistantMessageTokensCache]
+type assistantMessageTokensCacheJSON struct {
+ Read apijson.Field
+ Write apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessageTokensCache) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessageTokensCacheJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessageError struct {
+ // This field can have the runtime type of [shared.ProviderAuthErrorData],
+ // [shared.UnknownErrorData], [interface{}].
+ Data interface{} `json:"data,required"`
+ Name AssistantMessageErrorName `json:"name,required"`
+ JSON assistantMessageErrorJSON `json:"-"`
+ union AssistantMessageErrorUnion
+}
+
+// assistantMessageErrorJSON contains the JSON metadata for the struct
+// [AssistantMessageError]
+type assistantMessageErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r assistantMessageErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *AssistantMessageError) UnmarshalJSON(data []byte) (err error) {
+ *r = AssistantMessageError{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [AssistantMessageErrorUnion] interface which you can cast to
+// the specific types for more type safety.
+//
+// Possible runtime types of the union are [shared.ProviderAuthError],
+// [shared.UnknownError], [AssistantMessageErrorMessageOutputLengthError],
+// [shared.MessageAbortedError].
+func (r AssistantMessageError) AsUnion() AssistantMessageErrorUnion {
+ return r.union
+}
+
+// Union satisfied by [shared.ProviderAuthError], [shared.UnknownError],
+// [AssistantMessageErrorMessageOutputLengthError] or [shared.MessageAbortedError].
+type AssistantMessageErrorUnion interface {
+ ImplementsAssistantMessageError()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*AssistantMessageErrorUnion)(nil)).Elem(),
+ "name",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.ProviderAuthError{}),
+ DiscriminatorValue: "ProviderAuthError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.UnknownError{}),
+ DiscriminatorValue: "UnknownError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(AssistantMessageErrorMessageOutputLengthError{}),
+ DiscriminatorValue: "MessageOutputLengthError",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(shared.MessageAbortedError{}),
+ DiscriminatorValue: "MessageAbortedError",
+ },
+ )
+}
+
+type AssistantMessageErrorMessageOutputLengthError struct {
+ Data interface{} `json:"data,required"`
+ Name AssistantMessageErrorMessageOutputLengthErrorName `json:"name,required"`
+ JSON assistantMessageErrorMessageOutputLengthErrorJSON `json:"-"`
+}
+
+// assistantMessageErrorMessageOutputLengthErrorJSON contains the JSON metadata for
+// the struct [AssistantMessageErrorMessageOutputLengthError]
+type assistantMessageErrorMessageOutputLengthErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessageErrorMessageOutputLengthError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessageErrorMessageOutputLengthErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r AssistantMessageErrorMessageOutputLengthError) ImplementsAssistantMessageError() {}
+
+type AssistantMessageErrorMessageOutputLengthErrorName string
+
+const (
+ AssistantMessageErrorMessageOutputLengthErrorNameMessageOutputLengthError AssistantMessageErrorMessageOutputLengthErrorName = "MessageOutputLengthError"
+)
+
+func (r AssistantMessageErrorMessageOutputLengthErrorName) IsKnown() bool {
+ switch r {
+ case AssistantMessageErrorMessageOutputLengthErrorNameMessageOutputLengthError:
+ return true
+ }
+ return false
+}
+
+type AssistantMessageErrorName string
+
+const (
+ AssistantMessageErrorNameProviderAuthError AssistantMessageErrorName = "ProviderAuthError"
+ AssistantMessageErrorNameUnknownError AssistantMessageErrorName = "UnknownError"
+ AssistantMessageErrorNameMessageOutputLengthError AssistantMessageErrorName = "MessageOutputLengthError"
+ AssistantMessageErrorNameMessageAbortedError AssistantMessageErrorName = "MessageAbortedError"
+)
+
+func (r AssistantMessageErrorName) IsKnown() bool {
+ switch r {
+ case AssistantMessageErrorNameProviderAuthError, AssistantMessageErrorNameUnknownError, AssistantMessageErrorNameMessageOutputLengthError, AssistantMessageErrorNameMessageAbortedError:
+ return true
+ }
+ return false
+}
+
+type FilePart struct {
+ ID string `json:"id,required"`
+ MessageID string `json:"messageID,required"`
+ Mime string `json:"mime,required"`
+ SessionID string `json:"sessionID,required"`
+ Type FilePartType `json:"type,required"`
+ URL string `json:"url,required"`
+ Filename string `json:"filename"`
+ Source FilePartSource `json:"source"`
+ JSON filePartJSON `json:"-"`
+}
+
+// filePartJSON contains the JSON metadata for the struct [FilePart]
+type filePartJSON struct {
+ ID apijson.Field
+ MessageID apijson.Field
+ Mime apijson.Field
+ SessionID apijson.Field
+ Type apijson.Field
+ URL apijson.Field
+ Filename apijson.Field
+ Source apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FilePart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r filePartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r FilePart) implementsPart() {}
+
+type FilePartType string
+
+const (
+ FilePartTypeFile FilePartType = "file"
+)
+
+func (r FilePartType) IsKnown() bool {
+ switch r {
+ case FilePartTypeFile:
+ return true
+ }
+ return false
+}
+
+type FilePartInputParam struct {
+ Mime param.Field[string] `json:"mime,required"`
+ Type param.Field[FilePartInputType] `json:"type,required"`
+ URL param.Field[string] `json:"url,required"`
+ ID param.Field[string] `json:"id"`
+ Filename param.Field[string] `json:"filename"`
+ Source param.Field[FilePartSourceUnionParam] `json:"source"`
+}
+
+func (r FilePartInputParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r FilePartInputParam) implementsSessionChatParamsPartUnion() {}
+
+type FilePartInputType string
+
+const (
+ FilePartInputTypeFile FilePartInputType = "file"
+)
+
+func (r FilePartInputType) IsKnown() bool {
+ switch r {
+ case FilePartInputTypeFile:
+ return true
+ }
+ return false
+}
+
+type FilePartSource struct {
+ Path string `json:"path,required"`
+ Text FilePartSourceText `json:"text,required"`
+ Type FilePartSourceType `json:"type,required"`
+ Kind int64 `json:"kind"`
+ Name string `json:"name"`
+ // This field can have the runtime type of [SymbolSourceRange].
+ Range interface{} `json:"range"`
+ JSON filePartSourceJSON `json:"-"`
+ union FilePartSourceUnion
+}
+
+// filePartSourceJSON contains the JSON metadata for the struct [FilePartSource]
+type filePartSourceJSON struct {
+ Path apijson.Field
+ Text apijson.Field
+ Type apijson.Field
+ Kind apijson.Field
+ Name apijson.Field
+ Range apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r filePartSourceJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *FilePartSource) UnmarshalJSON(data []byte) (err error) {
+ *r = FilePartSource{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [FilePartSourceUnion] interface which you can cast to the
+// specific types for more type safety.
+//
+// Possible runtime types of the union are [FileSource], [SymbolSource].
+func (r FilePartSource) AsUnion() FilePartSourceUnion {
+ return r.union
+}
+
+// Union satisfied by [FileSource] or [SymbolSource].
+type FilePartSourceUnion interface {
+ implementsFilePartSource()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*FilePartSourceUnion)(nil)).Elem(),
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(FileSource{}),
+ DiscriminatorValue: "file",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(SymbolSource{}),
+ DiscriminatorValue: "symbol",
+ },
+ )
+}
+
+type FilePartSourceType string
+
+const (
+ FilePartSourceTypeFile FilePartSourceType = "file"
+ FilePartSourceTypeSymbol FilePartSourceType = "symbol"
+)
+
+func (r FilePartSourceType) IsKnown() bool {
+ switch r {
+ case FilePartSourceTypeFile, FilePartSourceTypeSymbol:
+ return true
+ }
+ return false
+}
+
+type FilePartSourceParam struct {
+ Path param.Field[string] `json:"path,required"`
+ Text param.Field[FilePartSourceTextParam] `json:"text,required"`
+ Type param.Field[FilePartSourceType] `json:"type,required"`
+ Kind param.Field[int64] `json:"kind"`
+ Name param.Field[string] `json:"name"`
+ Range param.Field[interface{}] `json:"range"`
+}
+
+func (r FilePartSourceParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r FilePartSourceParam) implementsFilePartSourceUnionParam() {}
+
+// Satisfied by [FileSourceParam], [SymbolSourceParam], [FilePartSourceParam].
+type FilePartSourceUnionParam interface {
+ implementsFilePartSourceUnionParam()
+}
+
+type FilePartSourceText struct {
+ End int64 `json:"end,required"`
+ Start int64 `json:"start,required"`
+ Value string `json:"value,required"`
+ JSON filePartSourceTextJSON `json:"-"`
+}
+
+// filePartSourceTextJSON contains the JSON metadata for the struct
+// [FilePartSourceText]
+type filePartSourceTextJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ Value apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FilePartSourceText) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r filePartSourceTextJSON) RawJSON() string {
+ return r.raw
+}
+
+type FilePartSourceTextParam struct {
+ End param.Field[int64] `json:"end,required"`
+ Start param.Field[int64] `json:"start,required"`
+ Value param.Field[string] `json:"value,required"`
+}
+
+func (r FilePartSourceTextParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type FileSource struct {
+ Path string `json:"path,required"`
+ Text FilePartSourceText `json:"text,required"`
+ Type FileSourceType `json:"type,required"`
+ JSON fileSourceJSON `json:"-"`
+}
+
+// fileSourceJSON contains the JSON metadata for the struct [FileSource]
+type fileSourceJSON struct {
+ Path apijson.Field
+ Text apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *FileSource) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r fileSourceJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r FileSource) implementsFilePartSource() {}
+
+type FileSourceType string
+
+const (
+ FileSourceTypeFile FileSourceType = "file"
+)
+
+func (r FileSourceType) IsKnown() bool {
+ switch r {
+ case FileSourceTypeFile:
+ return true
+ }
+ return false
+}
+
+type FileSourceParam struct {
+ Path param.Field[string] `json:"path,required"`
+ Text param.Field[FilePartSourceTextParam] `json:"text,required"`
+ Type param.Field[FileSourceType] `json:"type,required"`
+}
+
+func (r FileSourceParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r FileSourceParam) implementsFilePartSourceUnionParam() {}
+
+type Message struct {
+ ID string `json:"id,required"`
+ Role MessageRole `json:"role,required"`
+ SessionID string `json:"sessionID,required"`
+ // This field can have the runtime type of [UserMessageTime],
+ // [AssistantMessageTime].
+ Time interface{} `json:"time,required"`
+ Cost float64 `json:"cost"`
+ // This field can have the runtime type of [AssistantMessageError].
+ Error interface{} `json:"error"`
+ Mode string `json:"mode"`
+ ModelID string `json:"modelID"`
+ // This field can have the runtime type of [AssistantMessagePath].
+ Path interface{} `json:"path"`
+ ProviderID string `json:"providerID"`
+ Summary bool `json:"summary"`
+ // This field can have the runtime type of [[]string].
+ System interface{} `json:"system"`
+ // This field can have the runtime type of [AssistantMessageTokens].
+ Tokens interface{} `json:"tokens"`
+ JSON messageJSON `json:"-"`
+ union MessageUnion
+}
+
+// messageJSON contains the JSON metadata for the struct [Message]
+type messageJSON struct {
+ ID apijson.Field
+ Role apijson.Field
+ SessionID apijson.Field
+ Time apijson.Field
+ Cost apijson.Field
+ Error apijson.Field
+ Mode apijson.Field
+ ModelID apijson.Field
+ Path apijson.Field
+ ProviderID apijson.Field
+ Summary apijson.Field
+ System apijson.Field
+ Tokens apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r messageJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *Message) UnmarshalJSON(data []byte) (err error) {
+ *r = Message{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [MessageUnion] interface which you can cast to the specific
+// types for more type safety.
+//
+// Possible runtime types of the union are [UserMessage], [AssistantMessage].
+func (r Message) AsUnion() MessageUnion {
+ return r.union
+}
+
+// Union satisfied by [UserMessage] or [AssistantMessage].
+type MessageUnion interface {
+ implementsMessage()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*MessageUnion)(nil)).Elem(),
+ "role",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(UserMessage{}),
+ DiscriminatorValue: "user",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(AssistantMessage{}),
+ DiscriminatorValue: "assistant",
+ },
+ )
+}
+
+type MessageRole string
+
+const (
+ MessageRoleUser MessageRole = "user"
+ MessageRoleAssistant MessageRole = "assistant"
+)
+
+func (r MessageRole) IsKnown() bool {
+ switch r {
+ case MessageRoleUser, MessageRoleAssistant:
+ return true
+ }
+ return false
+}
+
+type Part struct {
+ ID string `json:"id,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Type PartType `json:"type,required"`
+ CallID string `json:"callID"`
+ Cost float64 `json:"cost"`
+ Filename string `json:"filename"`
+ // This field can have the runtime type of [[]string].
+ Files interface{} `json:"files"`
+ Hash string `json:"hash"`
+ Mime string `json:"mime"`
+ Snapshot string `json:"snapshot"`
+ Source FilePartSource `json:"source"`
+ // This field can have the runtime type of [ToolPartState].
+ State interface{} `json:"state"`
+ Synthetic bool `json:"synthetic"`
+ Text string `json:"text"`
+ // This field can have the runtime type of [TextPartTime].
+ Time interface{} `json:"time"`
+ // This field can have the runtime type of [StepFinishPartTokens].
+ Tokens interface{} `json:"tokens"`
+ Tool string `json:"tool"`
+ URL string `json:"url"`
+ JSON partJSON `json:"-"`
+ union PartUnion
+}
+
+// partJSON contains the JSON metadata for the struct [Part]
+type partJSON struct {
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Type apijson.Field
+ CallID apijson.Field
+ Cost apijson.Field
+ Filename apijson.Field
+ Files apijson.Field
+ Hash apijson.Field
+ Mime apijson.Field
+ Snapshot apijson.Field
+ Source apijson.Field
+ State apijson.Field
+ Synthetic apijson.Field
+ Text apijson.Field
+ Time apijson.Field
+ Tokens apijson.Field
+ Tool apijson.Field
+ URL apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r partJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *Part) UnmarshalJSON(data []byte) (err error) {
+ *r = Part{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [PartUnion] interface which you can cast to the specific types
+// for more type safety.
+//
+// Possible runtime types of the union are [TextPart], [FilePart], [ToolPart],
+// [StepStartPart], [StepFinishPart], [SnapshotPart], [PartPatchPart].
+func (r Part) AsUnion() PartUnion {
+ return r.union
+}
+
+// Union satisfied by [TextPart], [FilePart], [ToolPart], [StepStartPart],
+// [StepFinishPart], [SnapshotPart] or [PartPatchPart].
+type PartUnion interface {
+ implementsPart()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*PartUnion)(nil)).Elem(),
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(TextPart{}),
+ DiscriminatorValue: "text",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(FilePart{}),
+ DiscriminatorValue: "file",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolPart{}),
+ DiscriminatorValue: "tool",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(StepStartPart{}),
+ DiscriminatorValue: "step-start",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(StepFinishPart{}),
+ DiscriminatorValue: "step-finish",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(SnapshotPart{}),
+ DiscriminatorValue: "snapshot",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(PartPatchPart{}),
+ DiscriminatorValue: "patch",
+ },
+ )
+}
+
+type PartPatchPart struct {
+ ID string `json:"id,required"`
+ Files []string `json:"files,required"`
+ Hash string `json:"hash,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Type PartPatchPartType `json:"type,required"`
+ JSON partPatchPartJSON `json:"-"`
+}
+
+// partPatchPartJSON contains the JSON metadata for the struct [PartPatchPart]
+type partPatchPartJSON struct {
+ ID apijson.Field
+ Files apijson.Field
+ Hash apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *PartPatchPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r partPatchPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r PartPatchPart) implementsPart() {}
+
+type PartPatchPartType string
+
+const (
+ PartPatchPartTypePatch PartPatchPartType = "patch"
+)
+
+func (r PartPatchPartType) IsKnown() bool {
+ switch r {
+ case PartPatchPartTypePatch:
+ return true
+ }
+ return false
+}
+
+type PartType string
+
+const (
+ PartTypeText PartType = "text"
+ PartTypeFile PartType = "file"
+ PartTypeTool PartType = "tool"
+ PartTypeStepStart PartType = "step-start"
+ PartTypeStepFinish PartType = "step-finish"
+ PartTypeSnapshot PartType = "snapshot"
+ PartTypePatch PartType = "patch"
+)
+
+func (r PartType) IsKnown() bool {
+ switch r {
+ case PartTypeText, PartTypeFile, PartTypeTool, PartTypeStepStart, PartTypeStepFinish, PartTypeSnapshot, PartTypePatch:
+ return true
+ }
+ return false
+}
+
+type Session struct {
+ ID string `json:"id,required"`
+ Time SessionTime `json:"time,required"`
+ Title string `json:"title,required"`
+ Version string `json:"version,required"`
+ ParentID string `json:"parentID"`
+ Revert SessionRevert `json:"revert"`
+ Share SessionShare `json:"share"`
+ JSON sessionJSON `json:"-"`
+}
+
+// sessionJSON contains the JSON metadata for the struct [Session]
+type sessionJSON struct {
+ ID apijson.Field
+ Time apijson.Field
+ Title apijson.Field
+ Version apijson.Field
+ ParentID apijson.Field
+ Revert apijson.Field
+ Share apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Session) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r sessionJSON) RawJSON() string {
+ return r.raw
+}
+
+type SessionTime struct {
+ Created float64 `json:"created,required"`
+ Updated float64 `json:"updated,required"`
+ JSON sessionTimeJSON `json:"-"`
+}
+
+// sessionTimeJSON contains the JSON metadata for the struct [SessionTime]
+type sessionTimeJSON struct {
+ Created apijson.Field
+ Updated apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SessionTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r sessionTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type SessionRevert struct {
+ MessageID string `json:"messageID,required"`
+ Diff string `json:"diff"`
+ PartID string `json:"partID"`
+ Snapshot string `json:"snapshot"`
+ JSON sessionRevertJSON `json:"-"`
+}
+
+// sessionRevertJSON contains the JSON metadata for the struct [SessionRevert]
+type sessionRevertJSON struct {
+ MessageID apijson.Field
+ Diff apijson.Field
+ PartID apijson.Field
+ Snapshot apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SessionRevert) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r sessionRevertJSON) RawJSON() string {
+ return r.raw
+}
+
+type SessionShare struct {
+ URL string `json:"url,required"`
+ JSON sessionShareJSON `json:"-"`
+}
+
+// sessionShareJSON contains the JSON metadata for the struct [SessionShare]
+type sessionShareJSON struct {
+ URL apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SessionShare) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r sessionShareJSON) RawJSON() string {
+ return r.raw
+}
+
+type SnapshotPart struct {
+ ID string `json:"id,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Snapshot string `json:"snapshot,required"`
+ Type SnapshotPartType `json:"type,required"`
+ JSON snapshotPartJSON `json:"-"`
+}
+
+// snapshotPartJSON contains the JSON metadata for the struct [SnapshotPart]
+type snapshotPartJSON struct {
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Snapshot apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SnapshotPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r snapshotPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r SnapshotPart) implementsPart() {}
+
+type SnapshotPartType string
+
+const (
+ SnapshotPartTypeSnapshot SnapshotPartType = "snapshot"
+)
+
+func (r SnapshotPartType) IsKnown() bool {
+ switch r {
+ case SnapshotPartTypeSnapshot:
+ return true
+ }
+ return false
+}
+
+type StepFinishPart struct {
+ ID string `json:"id,required"`
+ Cost float64 `json:"cost,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Tokens StepFinishPartTokens `json:"tokens,required"`
+ Type StepFinishPartType `json:"type,required"`
+ JSON stepFinishPartJSON `json:"-"`
+}
+
+// stepFinishPartJSON contains the JSON metadata for the struct [StepFinishPart]
+type stepFinishPartJSON struct {
+ ID apijson.Field
+ Cost apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Tokens apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *StepFinishPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r stepFinishPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r StepFinishPart) implementsPart() {}
+
+type StepFinishPartTokens struct {
+ Cache StepFinishPartTokensCache `json:"cache,required"`
+ Input float64 `json:"input,required"`
+ Output float64 `json:"output,required"`
+ Reasoning float64 `json:"reasoning,required"`
+ JSON stepFinishPartTokensJSON `json:"-"`
+}
+
+// stepFinishPartTokensJSON contains the JSON metadata for the struct
+// [StepFinishPartTokens]
+type stepFinishPartTokensJSON struct {
+ Cache apijson.Field
+ Input apijson.Field
+ Output apijson.Field
+ Reasoning apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *StepFinishPartTokens) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r stepFinishPartTokensJSON) RawJSON() string {
+ return r.raw
+}
+
+type StepFinishPartTokensCache struct {
+ Read float64 `json:"read,required"`
+ Write float64 `json:"write,required"`
+ JSON stepFinishPartTokensCacheJSON `json:"-"`
+}
+
+// stepFinishPartTokensCacheJSON contains the JSON metadata for the struct
+// [StepFinishPartTokensCache]
+type stepFinishPartTokensCacheJSON struct {
+ Read apijson.Field
+ Write apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *StepFinishPartTokensCache) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r stepFinishPartTokensCacheJSON) RawJSON() string {
+ return r.raw
+}
+
+type StepFinishPartType string
+
+const (
+ StepFinishPartTypeStepFinish StepFinishPartType = "step-finish"
+)
+
+func (r StepFinishPartType) IsKnown() bool {
+ switch r {
+ case StepFinishPartTypeStepFinish:
+ return true
+ }
+ return false
+}
+
+type StepStartPart struct {
+ ID string `json:"id,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Type StepStartPartType `json:"type,required"`
+ JSON stepStartPartJSON `json:"-"`
+}
+
+// stepStartPartJSON contains the JSON metadata for the struct [StepStartPart]
+type stepStartPartJSON struct {
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *StepStartPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r stepStartPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r StepStartPart) implementsPart() {}
+
+type StepStartPartType string
+
+const (
+ StepStartPartTypeStepStart StepStartPartType = "step-start"
+)
+
+func (r StepStartPartType) IsKnown() bool {
+ switch r {
+ case StepStartPartTypeStepStart:
+ return true
+ }
+ return false
+}
+
+type SymbolSource struct {
+ Kind int64 `json:"kind,required"`
+ Name string `json:"name,required"`
+ Path string `json:"path,required"`
+ Range SymbolSourceRange `json:"range,required"`
+ Text FilePartSourceText `json:"text,required"`
+ Type SymbolSourceType `json:"type,required"`
+ JSON symbolSourceJSON `json:"-"`
+}
+
+// symbolSourceJSON contains the JSON metadata for the struct [SymbolSource]
+type symbolSourceJSON struct {
+ Kind apijson.Field
+ Name apijson.Field
+ Path apijson.Field
+ Range apijson.Field
+ Text apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolSource) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolSourceJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r SymbolSource) implementsFilePartSource() {}
+
+type SymbolSourceRange struct {
+ End SymbolSourceRangeEnd `json:"end,required"`
+ Start SymbolSourceRangeStart `json:"start,required"`
+ JSON symbolSourceRangeJSON `json:"-"`
+}
+
+// symbolSourceRangeJSON contains the JSON metadata for the struct
+// [SymbolSourceRange]
+type symbolSourceRangeJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolSourceRange) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolSourceRangeJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolSourceRangeEnd struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolSourceRangeEndJSON `json:"-"`
+}
+
+// symbolSourceRangeEndJSON contains the JSON metadata for the struct
+// [SymbolSourceRangeEnd]
+type symbolSourceRangeEndJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolSourceRangeEnd) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolSourceRangeEndJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolSourceRangeStart struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolSourceRangeStartJSON `json:"-"`
+}
+
+// symbolSourceRangeStartJSON contains the JSON metadata for the struct
+// [SymbolSourceRangeStart]
+type symbolSourceRangeStartJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolSourceRangeStart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolSourceRangeStartJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolSourceType string
+
+const (
+ SymbolSourceTypeSymbol SymbolSourceType = "symbol"
+)
+
+func (r SymbolSourceType) IsKnown() bool {
+ switch r {
+ case SymbolSourceTypeSymbol:
+ return true
+ }
+ return false
+}
+
+type SymbolSourceParam struct {
+ Kind param.Field[int64] `json:"kind,required"`
+ Name param.Field[string] `json:"name,required"`
+ Path param.Field[string] `json:"path,required"`
+ Range param.Field[SymbolSourceRangeParam] `json:"range,required"`
+ Text param.Field[FilePartSourceTextParam] `json:"text,required"`
+ Type param.Field[SymbolSourceType] `json:"type,required"`
+}
+
+func (r SymbolSourceParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r SymbolSourceParam) implementsFilePartSourceUnionParam() {}
+
+type SymbolSourceRangeParam struct {
+ End param.Field[SymbolSourceRangeEndParam] `json:"end,required"`
+ Start param.Field[SymbolSourceRangeStartParam] `json:"start,required"`
+}
+
+func (r SymbolSourceRangeParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type SymbolSourceRangeEndParam struct {
+ Character param.Field[float64] `json:"character,required"`
+ Line param.Field[float64] `json:"line,required"`
+}
+
+func (r SymbolSourceRangeEndParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type SymbolSourceRangeStartParam struct {
+ Character param.Field[float64] `json:"character,required"`
+ Line param.Field[float64] `json:"line,required"`
+}
+
+func (r SymbolSourceRangeStartParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type TextPart struct {
+ ID string `json:"id,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ Text string `json:"text,required"`
+ Type TextPartType `json:"type,required"`
+ Synthetic bool `json:"synthetic"`
+ Time TextPartTime `json:"time"`
+ JSON textPartJSON `json:"-"`
+}
+
+// textPartJSON contains the JSON metadata for the struct [TextPart]
+type textPartJSON struct {
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Text apijson.Field
+ Type apijson.Field
+ Synthetic apijson.Field
+ Time apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *TextPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r textPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r TextPart) implementsPart() {}
+
+type TextPartType string
+
+const (
+ TextPartTypeText TextPartType = "text"
+)
+
+func (r TextPartType) IsKnown() bool {
+ switch r {
+ case TextPartTypeText:
+ return true
+ }
+ return false
+}
+
+type TextPartTime struct {
+ Start float64 `json:"start,required"`
+ End float64 `json:"end"`
+ JSON textPartTimeJSON `json:"-"`
+}
+
+// textPartTimeJSON contains the JSON metadata for the struct [TextPartTime]
+type textPartTimeJSON struct {
+ Start apijson.Field
+ End apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *TextPartTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r textPartTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type TextPartInputParam struct {
+ Text param.Field[string] `json:"text,required"`
+ Type param.Field[TextPartInputType] `json:"type,required"`
+ ID param.Field[string] `json:"id"`
+ Synthetic param.Field[bool] `json:"synthetic"`
+ Time param.Field[TextPartInputTimeParam] `json:"time"`
+}
+
+func (r TextPartInputParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r TextPartInputParam) implementsSessionChatParamsPartUnion() {}
+
+type TextPartInputType string
+
+const (
+ TextPartInputTypeText TextPartInputType = "text"
+)
+
+func (r TextPartInputType) IsKnown() bool {
+ switch r {
+ case TextPartInputTypeText:
+ return true
+ }
+ return false
+}
+
+type TextPartInputTimeParam struct {
+ Start param.Field[float64] `json:"start,required"`
+ End param.Field[float64] `json:"end"`
+}
+
+func (r TextPartInputTimeParam) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type ToolPart struct {
+ ID string `json:"id,required"`
+ CallID string `json:"callID,required"`
+ MessageID string `json:"messageID,required"`
+ SessionID string `json:"sessionID,required"`
+ State ToolPartState `json:"state,required"`
+ Tool string `json:"tool,required"`
+ Type ToolPartType `json:"type,required"`
+ JSON toolPartJSON `json:"-"`
+}
+
+// toolPartJSON contains the JSON metadata for the struct [ToolPart]
+type toolPartJSON struct {
+ ID apijson.Field
+ CallID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ State apijson.Field
+ Tool apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ToolPart) implementsPart() {}
+
+type ToolPartState struct {
+ Status ToolPartStateStatus `json:"status,required"`
+ Error string `json:"error"`
+ // This field can have the runtime type of [interface{}], [map[string]interface{}].
+ Input interface{} `json:"input"`
+ // This field can have the runtime type of [map[string]interface{}].
+ Metadata interface{} `json:"metadata"`
+ Output string `json:"output"`
+ // This field can have the runtime type of [ToolStateRunningTime],
+ // [ToolStateCompletedTime], [ToolStateErrorTime].
+ Time interface{} `json:"time"`
+ Title string `json:"title"`
+ JSON toolPartStateJSON `json:"-"`
+ union ToolPartStateUnion
+}
+
+// toolPartStateJSON contains the JSON metadata for the struct [ToolPartState]
+type toolPartStateJSON struct {
+ Status apijson.Field
+ Error apijson.Field
+ Input apijson.Field
+ Metadata apijson.Field
+ Output apijson.Field
+ Time apijson.Field
+ Title apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r toolPartStateJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r *ToolPartState) UnmarshalJSON(data []byte) (err error) {
+ *r = ToolPartState{}
+ err = apijson.UnmarshalRoot(data, &r.union)
+ if err != nil {
+ return err
+ }
+ return apijson.Port(r.union, &r)
+}
+
+// AsUnion returns a [ToolPartStateUnion] interface which you can cast to the
+// specific types for more type safety.
+//
+// Possible runtime types of the union are [ToolStatePending], [ToolStateRunning],
+// [ToolStateCompleted], [ToolStateError].
+func (r ToolPartState) AsUnion() ToolPartStateUnion {
+ return r.union
+}
+
+// Union satisfied by [ToolStatePending], [ToolStateRunning], [ToolStateCompleted]
+// or [ToolStateError].
+type ToolPartStateUnion interface {
+ implementsToolPartState()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*ToolPartStateUnion)(nil)).Elem(),
+ "status",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolStatePending{}),
+ DiscriminatorValue: "pending",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolStateRunning{}),
+ DiscriminatorValue: "running",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolStateCompleted{}),
+ DiscriminatorValue: "completed",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolStateError{}),
+ DiscriminatorValue: "error",
+ },
+ )
+}
+
+type ToolPartStateStatus string
+
+const (
+ ToolPartStateStatusPending ToolPartStateStatus = "pending"
+ ToolPartStateStatusRunning ToolPartStateStatus = "running"
+ ToolPartStateStatusCompleted ToolPartStateStatus = "completed"
+ ToolPartStateStatusError ToolPartStateStatus = "error"
+)
+
+func (r ToolPartStateStatus) IsKnown() bool {
+ switch r {
+ case ToolPartStateStatusPending, ToolPartStateStatusRunning, ToolPartStateStatusCompleted, ToolPartStateStatusError:
+ return true
+ }
+ return false
+}
+
+type ToolPartType string
+
+const (
+ ToolPartTypeTool ToolPartType = "tool"
+)
+
+func (r ToolPartType) IsKnown() bool {
+ switch r {
+ case ToolPartTypeTool:
+ return true
+ }
+ return false
+}
+
+type ToolStateCompleted struct {
+ Input map[string]interface{} `json:"input,required"`
+ Metadata map[string]interface{} `json:"metadata,required"`
+ Output string `json:"output,required"`
+ Status ToolStateCompletedStatus `json:"status,required"`
+ Time ToolStateCompletedTime `json:"time,required"`
+ Title string `json:"title,required"`
+ JSON toolStateCompletedJSON `json:"-"`
+}
+
+// toolStateCompletedJSON contains the JSON metadata for the struct
+// [ToolStateCompleted]
+type toolStateCompletedJSON struct {
+ Input apijson.Field
+ Metadata apijson.Field
+ Output apijson.Field
+ Status apijson.Field
+ Time apijson.Field
+ Title apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateCompleted) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateCompletedJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ToolStateCompleted) implementsToolPartState() {}
+
+type ToolStateCompletedStatus string
+
+const (
+ ToolStateCompletedStatusCompleted ToolStateCompletedStatus = "completed"
+)
+
+func (r ToolStateCompletedStatus) IsKnown() bool {
+ switch r {
+ case ToolStateCompletedStatusCompleted:
+ return true
+ }
+ return false
+}
+
+type ToolStateCompletedTime struct {
+ End float64 `json:"end,required"`
+ Start float64 `json:"start,required"`
+ JSON toolStateCompletedTimeJSON `json:"-"`
+}
+
+// toolStateCompletedTimeJSON contains the JSON metadata for the struct
+// [ToolStateCompletedTime]
+type toolStateCompletedTimeJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateCompletedTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateCompletedTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type ToolStateError struct {
+ Error string `json:"error,required"`
+ Input map[string]interface{} `json:"input,required"`
+ Status ToolStateErrorStatus `json:"status,required"`
+ Time ToolStateErrorTime `json:"time,required"`
+ JSON toolStateErrorJSON `json:"-"`
+}
+
+// toolStateErrorJSON contains the JSON metadata for the struct [ToolStateError]
+type toolStateErrorJSON struct {
+ Error apijson.Field
+ Input apijson.Field
+ Status apijson.Field
+ Time apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ToolStateError) implementsToolPartState() {}
+
+type ToolStateErrorStatus string
+
+const (
+ ToolStateErrorStatusError ToolStateErrorStatus = "error"
+)
+
+func (r ToolStateErrorStatus) IsKnown() bool {
+ switch r {
+ case ToolStateErrorStatusError:
+ return true
+ }
+ return false
+}
+
+type ToolStateErrorTime struct {
+ End float64 `json:"end,required"`
+ Start float64 `json:"start,required"`
+ JSON toolStateErrorTimeJSON `json:"-"`
+}
+
+// toolStateErrorTimeJSON contains the JSON metadata for the struct
+// [ToolStateErrorTime]
+type toolStateErrorTimeJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateErrorTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateErrorTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type ToolStatePending struct {
+ Status ToolStatePendingStatus `json:"status,required"`
+ JSON toolStatePendingJSON `json:"-"`
+}
+
+// toolStatePendingJSON contains the JSON metadata for the struct
+// [ToolStatePending]
+type toolStatePendingJSON struct {
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStatePending) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStatePendingJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ToolStatePending) implementsToolPartState() {}
+
+type ToolStatePendingStatus string
+
+const (
+ ToolStatePendingStatusPending ToolStatePendingStatus = "pending"
+)
+
+func (r ToolStatePendingStatus) IsKnown() bool {
+ switch r {
+ case ToolStatePendingStatusPending:
+ return true
+ }
+ return false
+}
+
+type ToolStateRunning struct {
+ Status ToolStateRunningStatus `json:"status,required"`
+ Time ToolStateRunningTime `json:"time,required"`
+ Input interface{} `json:"input"`
+ Metadata map[string]interface{} `json:"metadata"`
+ Title string `json:"title"`
+ JSON toolStateRunningJSON `json:"-"`
+}
+
+// toolStateRunningJSON contains the JSON metadata for the struct
+// [ToolStateRunning]
+type toolStateRunningJSON struct {
+ Status apijson.Field
+ Time apijson.Field
+ Input apijson.Field
+ Metadata apijson.Field
+ Title apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateRunning) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateRunningJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ToolStateRunning) implementsToolPartState() {}
+
+type ToolStateRunningStatus string
+
+const (
+ ToolStateRunningStatusRunning ToolStateRunningStatus = "running"
+)
+
+func (r ToolStateRunningStatus) IsKnown() bool {
+ switch r {
+ case ToolStateRunningStatusRunning:
+ return true
+ }
+ return false
+}
+
+type ToolStateRunningTime struct {
+ Start float64 `json:"start,required"`
+ JSON toolStateRunningTimeJSON `json:"-"`
+}
+
+// toolStateRunningTimeJSON contains the JSON metadata for the struct
+// [ToolStateRunningTime]
+type toolStateRunningTimeJSON struct {
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ToolStateRunningTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r toolStateRunningTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type UserMessage struct {
+ ID string `json:"id,required"`
+ Role UserMessageRole `json:"role,required"`
+ SessionID string `json:"sessionID,required"`
+ Time UserMessageTime `json:"time,required"`
+ JSON userMessageJSON `json:"-"`
+}
+
+// userMessageJSON contains the JSON metadata for the struct [UserMessage]
+type userMessageJSON struct {
+ ID apijson.Field
+ Role apijson.Field
+ SessionID apijson.Field
+ Time apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *UserMessage) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r userMessageJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r UserMessage) implementsMessage() {}
+
+type UserMessageRole string
+
+const (
+ UserMessageRoleUser UserMessageRole = "user"
+)
+
+func (r UserMessageRole) IsKnown() bool {
+ switch r {
+ case UserMessageRoleUser:
+ return true
+ }
+ return false
+}
+
+type UserMessageTime struct {
+ Created float64 `json:"created,required"`
+ JSON userMessageTimeJSON `json:"-"`
+}
+
+// userMessageTimeJSON contains the JSON metadata for the struct [UserMessageTime]
+type userMessageTimeJSON struct {
+ Created apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *UserMessageTime) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r userMessageTimeJSON) RawJSON() string {
+ return r.raw
+}
+
+type SessionMessagesResponse struct {
+ Info Message `json:"info,required"`
+ Parts []Part `json:"parts,required"`
+ JSON sessionMessagesResponseJSON `json:"-"`
+}
+
+// sessionMessagesResponseJSON contains the JSON metadata for the struct
+// [SessionMessagesResponse]
+type sessionMessagesResponseJSON struct {
+ Info apijson.Field
+ Parts apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SessionMessagesResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r sessionMessagesResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type SessionChatParams struct {
+ ModelID param.Field[string] `json:"modelID,required"`
+ Parts param.Field[[]SessionChatParamsPartUnion] `json:"parts,required"`
+ ProviderID param.Field[string] `json:"providerID,required"`
+ MessageID param.Field[string] `json:"messageID"`
+ Mode param.Field[string] `json:"mode"`
+ System param.Field[string] `json:"system"`
+ Tools param.Field[map[string]bool] `json:"tools"`
+}
+
+func (r SessionChatParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type SessionChatParamsPart struct {
+ Type param.Field[SessionChatParamsPartsType] `json:"type,required"`
+ ID param.Field[string] `json:"id"`
+ Filename param.Field[string] `json:"filename"`
+ Mime param.Field[string] `json:"mime"`
+ Source param.Field[FilePartSourceUnionParam] `json:"source"`
+ Synthetic param.Field[bool] `json:"synthetic"`
+ Text param.Field[string] `json:"text"`
+ Time param.Field[interface{}] `json:"time"`
+ URL param.Field[string] `json:"url"`
+}
+
+func (r SessionChatParamsPart) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+func (r SessionChatParamsPart) implementsSessionChatParamsPartUnion() {}
+
+// Satisfied by [TextPartInputParam], [FilePartInputParam],
+// [SessionChatParamsPart].
+type SessionChatParamsPartUnion interface {
+ implementsSessionChatParamsPartUnion()
+}
+
+type SessionChatParamsPartsType string
+
+const (
+ SessionChatParamsPartsTypeText SessionChatParamsPartsType = "text"
+ SessionChatParamsPartsTypeFile SessionChatParamsPartsType = "file"
+)
+
+func (r SessionChatParamsPartsType) IsKnown() bool {
+ switch r {
+ case SessionChatParamsPartsTypeText, SessionChatParamsPartsTypeFile:
+ return true
+ }
+ return false
+}
+
+type SessionInitParams struct {
+ MessageID param.Field[string] `json:"messageID,required"`
+ ModelID param.Field[string] `json:"modelID,required"`
+ ProviderID param.Field[string] `json:"providerID,required"`
+}
+
+func (r SessionInitParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type SessionRevertParams struct {
+ MessageID param.Field[string] `json:"messageID,required"`
+ PartID param.Field[string] `json:"partID"`
+}
+
+func (r SessionRevertParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type SessionSummarizeParams struct {
+ ModelID param.Field[string] `json:"modelID,required"`
+ ProviderID param.Field[string] `json:"providerID,required"`
+}
+
+func (r SessionSummarizeParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
diff --git a/packages/sdk/go/session_test.go b/packages/sdk/go/session_test.go
new file mode 100644
index 000000000..295e9e7ce
--- /dev/null
+++ b/packages/sdk/go/session_test.go
@@ -0,0 +1,323 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestSessionNew(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.New(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionList(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.List(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionDelete(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Delete(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionAbort(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Abort(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionChatWithOptionalParams(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Chat(
+ context.TODO(),
+ "id",
+ opencode.SessionChatParams{
+ ModelID: opencode.F("modelID"),
+ Parts: opencode.F([]opencode.SessionChatParamsPartUnion{opencode.TextPartInputParam{
+ Text: opencode.F("text"),
+ Type: opencode.F(opencode.TextPartInputTypeText),
+ ID: opencode.F("id"),
+ Synthetic: opencode.F(true),
+ Time: opencode.F(opencode.TextPartInputTimeParam{
+ Start: opencode.F(0.000000),
+ End: opencode.F(0.000000),
+ }),
+ }}),
+ ProviderID: opencode.F("providerID"),
+ MessageID: opencode.F("msg"),
+ Mode: opencode.F("mode"),
+ System: opencode.F("system"),
+ Tools: opencode.F(map[string]bool{
+ "foo": true,
+ }),
+ },
+ )
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionInit(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Init(
+ context.TODO(),
+ "id",
+ opencode.SessionInitParams{
+ MessageID: opencode.F("messageID"),
+ ModelID: opencode.F("modelID"),
+ ProviderID: opencode.F("providerID"),
+ },
+ )
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionMessages(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Messages(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionRevertWithOptionalParams(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Revert(
+ context.TODO(),
+ "id",
+ opencode.SessionRevertParams{
+ MessageID: opencode.F("msg"),
+ PartID: opencode.F("prt"),
+ },
+ )
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionShare(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Share(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionSummarize(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Summarize(
+ context.TODO(),
+ "id",
+ opencode.SessionSummarizeParams{
+ ModelID: opencode.F("modelID"),
+ ProviderID: opencode.F("providerID"),
+ },
+ )
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionUnrevert(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Unrevert(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestSessionUnshare(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Session.Unshare(context.TODO(), "id")
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/shared/shared.go b/packages/sdk/go/shared/shared.go
new file mode 100644
index 000000000..58baf3d9c
--- /dev/null
+++ b/packages/sdk/go/shared/shared.go
@@ -0,0 +1,173 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package shared
+
+import (
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+)
+
+type MessageAbortedError struct {
+ Data interface{} `json:"data,required"`
+ Name MessageAbortedErrorName `json:"name,required"`
+ JSON messageAbortedErrorJSON `json:"-"`
+}
+
+// messageAbortedErrorJSON contains the JSON metadata for the struct
+// [MessageAbortedError]
+type messageAbortedErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *MessageAbortedError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r messageAbortedErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r MessageAbortedError) ImplementsEventListResponseEventSessionErrorPropertiesError() {}
+
+func (r MessageAbortedError) ImplementsAssistantMessageError() {}
+
+type MessageAbortedErrorName string
+
+const (
+ MessageAbortedErrorNameMessageAbortedError MessageAbortedErrorName = "MessageAbortedError"
+)
+
+func (r MessageAbortedErrorName) IsKnown() bool {
+ switch r {
+ case MessageAbortedErrorNameMessageAbortedError:
+ return true
+ }
+ return false
+}
+
+type ProviderAuthError struct {
+ Data ProviderAuthErrorData `json:"data,required"`
+ Name ProviderAuthErrorName `json:"name,required"`
+ JSON providerAuthErrorJSON `json:"-"`
+}
+
+// providerAuthErrorJSON contains the JSON metadata for the struct
+// [ProviderAuthError]
+type providerAuthErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ProviderAuthError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r providerAuthErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r ProviderAuthError) ImplementsEventListResponseEventSessionErrorPropertiesError() {}
+
+func (r ProviderAuthError) ImplementsAssistantMessageError() {}
+
+type ProviderAuthErrorData struct {
+ Message string `json:"message,required"`
+ ProviderID string `json:"providerID,required"`
+ JSON providerAuthErrorDataJSON `json:"-"`
+}
+
+// providerAuthErrorDataJSON contains the JSON metadata for the struct
+// [ProviderAuthErrorData]
+type providerAuthErrorDataJSON struct {
+ Message apijson.Field
+ ProviderID apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *ProviderAuthErrorData) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r providerAuthErrorDataJSON) RawJSON() string {
+ return r.raw
+}
+
+type ProviderAuthErrorName string
+
+const (
+ ProviderAuthErrorNameProviderAuthError ProviderAuthErrorName = "ProviderAuthError"
+)
+
+func (r ProviderAuthErrorName) IsKnown() bool {
+ switch r {
+ case ProviderAuthErrorNameProviderAuthError:
+ return true
+ }
+ return false
+}
+
+type UnknownError struct {
+ Data UnknownErrorData `json:"data,required"`
+ Name UnknownErrorName `json:"name,required"`
+ JSON unknownErrorJSON `json:"-"`
+}
+
+// unknownErrorJSON contains the JSON metadata for the struct [UnknownError]
+type unknownErrorJSON struct {
+ Data apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *UnknownError) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r unknownErrorJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r UnknownError) ImplementsEventListResponseEventSessionErrorPropertiesError() {}
+
+func (r UnknownError) ImplementsAssistantMessageError() {}
+
+type UnknownErrorData struct {
+ Message string `json:"message,required"`
+ JSON unknownErrorDataJSON `json:"-"`
+}
+
+// unknownErrorDataJSON contains the JSON metadata for the struct
+// [UnknownErrorData]
+type unknownErrorDataJSON struct {
+ Message apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *UnknownErrorData) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r unknownErrorDataJSON) RawJSON() string {
+ return r.raw
+}
+
+type UnknownErrorName string
+
+const (
+ UnknownErrorNameUnknownError UnknownErrorName = "UnknownError"
+)
+
+func (r UnknownErrorName) IsKnown() bool {
+ switch r {
+ case UnknownErrorNameUnknownError:
+ return true
+ }
+ return false
+}
diff --git a/packages/sdk/go/tui.go b/packages/sdk/go/tui.go
new file mode 100644
index 000000000..d5243599f
--- /dev/null
+++ b/packages/sdk/go/tui.go
@@ -0,0 +1,56 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode
+
+import (
+ "context"
+ "net/http"
+
+ "github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/param"
+ "github.com/sst/opencode-sdk-go/internal/requestconfig"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+// TuiService contains methods and other services that help with interacting with
+// the opencode 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 [NewTuiService] method instead.
+type TuiService struct {
+ Options []option.RequestOption
+}
+
+// NewTuiService 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 NewTuiService(opts ...option.RequestOption) (r *TuiService) {
+ r = &TuiService{}
+ r.Options = opts
+ return
+}
+
+// Append prompt to the TUI
+func (r *TuiService) AppendPrompt(ctx context.Context, body TuiAppendPromptParams, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "tui/append-prompt"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
+// Open the help dialog
+func (r *TuiService) OpenHelp(ctx context.Context, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "tui/open-help"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+type TuiAppendPromptParams struct {
+ Text param.Field[string] `json:"text,required"`
+}
+
+func (r TuiAppendPromptParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
diff --git a/packages/sdk/go/tui_test.go b/packages/sdk/go/tui_test.go
new file mode 100644
index 000000000..5283f37c5
--- /dev/null
+++ b/packages/sdk/go/tui_test.go
@@ -0,0 +1,60 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestTuiAppendPrompt(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Tui.AppendPrompt(context.TODO(), opencode.TuiAppendPromptParams{
+ Text: opencode.F("text"),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestTuiOpenHelp(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 := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.Tui.OpenHelp(context.TODO())
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/sdk/go/usage_test.go b/packages/sdk/go/usage_test.go
new file mode 100644
index 000000000..ef7ce8bde
--- /dev/null
+++ b/packages/sdk/go/usage_test.go
@@ -0,0 +1,32 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package opencode_test
+
+import (
+ "context"
+ "os"
+ "testing"
+
+ "github.com/sst/opencode-sdk-go"
+ "github.com/sst/opencode-sdk-go/internal/testutil"
+ "github.com/sst/opencode-sdk-go/option"
+)
+
+func TestUsage(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ sessions, err := client.Session.List(context.TODO())
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ t.Logf("%+v\n", sessions)
+}
diff --git a/packages/sdk/jest.config.ts b/packages/sdk/jest.config.ts
deleted file mode 100644
index 5131990f8..000000000
--- a/packages/sdk/jest.config.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { JestConfigWithTsJest } from 'ts-jest';
-
-const config: JestConfigWithTsJest = {
- preset: 'ts-jest/presets/default-esm',
- testEnvironment: 'node',
- transform: {
- '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }],
- },
- moduleNameMapper: {
- '^@opencode-ai/sdk$': '<rootDir>/src/index.ts',
- '^@opencode-ai/sdk/(.*)$': '<rootDir>/src/$1',
- },
- modulePathIgnorePatterns: [
- '<rootDir>/ecosystem-tests/',
- '<rootDir>/dist/',
- '<rootDir>/deno/',
- '<rootDir>/deno_tests/',
- '<rootDir>/packages/',
- ],
- testPathIgnorePatterns: ['scripts'],
-};
-
-export default config;
diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json
new file mode 100644
index 000000000..502f2b7bb
--- /dev/null
+++ b/packages/sdk/js/package.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://json.schemastore.org/package.json",
+ "name": "@opencode-ai/sdk",
+ "version": "0.0.0",
+ "type": "module",
+ "exports": {
+ ".": "./dist/index.js"
+ },
+ "files": [
+ "dist"
+ ],
+ "devDependencies": {
+ "typescript": "catalog:",
+ "@hey-api/openapi-ts": "0.80.1",
+ "@tsconfig/node22": "catalog:"
+ }
+}
diff --git a/packages/sdk/js/script/generate.ts b/packages/sdk/js/script/generate.ts
new file mode 100755
index 000000000..3f864682e
--- /dev/null
+++ b/packages/sdk/js/script/generate.ts
@@ -0,0 +1,41 @@
+#!/usr/bin/env bun
+
+const dir = new URL("..", import.meta.url).pathname
+process.chdir(dir)
+
+import { $ } from "bun"
+import fs from "fs/promises"
+import path from "path"
+
+console.log("=== Generating JS SDK ===")
+console.log()
+
+import { createClient } from "@hey-api/openapi-ts"
+
+await fs.rm(path.join(dir, "src/gen"), { recursive: true, force: true })
+await $`bun run ../../opencode/src/index.ts generate > openapi.json`
+
+await createClient({
+ input: "./openapi.json",
+ output: "./src/gen",
+ plugins: [
+ {
+ name: "@hey-api/typescript",
+ exportFromIndex: false,
+ },
+ {
+ name: "@hey-api/sdk",
+ instance: "OpencodeClient",
+ exportFromIndex: false,
+ auth: false,
+ },
+ {
+ name: "@hey-api/client-fetch",
+ exportFromIndex: false,
+ baseUrl: "http://localhost:4096",
+ },
+ ],
+})
+
+await $`rm -rf dist`
+await $`bun tsc`
diff --git a/packages/sdk/js/script/publish.ts b/packages/sdk/js/script/publish.ts
new file mode 100644
index 000000000..39407f633
--- /dev/null
+++ b/packages/sdk/js/script/publish.ts
@@ -0,0 +1,24 @@
+#!/usr/bin/env bun
+
+const dir = new URL("..", import.meta.url).pathname
+process.chdir(dir)
+
+import { $ } from "bun"
+
+const version = process.env["OPENCODE_VERSION"]
+if (!version) {
+ throw new Error("OPENCODE_VERSION is required")
+}
+
+await import("./generate")
+
+const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true"
+
+await $`bun pm version --allow-same-version --no-git-tag-version ${version}`
+if (snapshot) {
+ await $`bun publish --tag snapshot`
+}
+if (!snapshot) {
+ await $`bun publish`
+}
+await $`bun pm version 0.0.0 --no-git-tag-version`
diff --git a/packages/sdk/js/src/gen/client.gen.ts b/packages/sdk/js/src/gen/client.gen.ts
new file mode 100644
index 000000000..3bb22b24a
--- /dev/null
+++ b/packages/sdk/js/src/gen/client.gen.ts
@@ -0,0 +1,18 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { ClientOptions } from './types.gen';
+import { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from './client';
+
+/**
+ * The `createClientConfig()` function will be called on client initialization
+ * and the returned object will become the client's initial configuration.
+ *
+ * You may want to initialize your client this way instead of calling
+ * `setConfig()`. This is useful for example if you're using Next.js
+ * to ensure your client always has the correct values.
+ */
+export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;
+
+export const client = createClient(createConfig<ClientOptions>({
+ baseUrl: 'http://localhost:4096'
+})); \ No newline at end of file
diff --git a/packages/sdk/js/src/gen/client/client.ts b/packages/sdk/js/src/gen/client/client.ts
new file mode 100644
index 000000000..89d1e3158
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/client.ts
@@ -0,0 +1,195 @@
+import type { Client, Config, RequestOptions } from './types';
+import {
+ buildUrl,
+ createConfig,
+ createInterceptors,
+ getParseAs,
+ mergeConfigs,
+ mergeHeaders,
+ setAuthParams,
+} from './utils';
+
+type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
+ body?: any;
+ headers: ReturnType<typeof mergeHeaders>;
+};
+
+export const createClient = (config: Config = {}): Client => {
+ let _config = mergeConfigs(createConfig(), config);
+
+ const getConfig = (): Config => ({ ..._config });
+
+ const setConfig = (config: Config): Config => {
+ _config = mergeConfigs(_config, config);
+ return getConfig();
+ };
+
+ const interceptors = createInterceptors<
+ Request,
+ Response,
+ unknown,
+ RequestOptions
+ >();
+
+ const request: Client['request'] = async (options) => {
+ const opts = {
+ ..._config,
+ ...options,
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
+ headers: mergeHeaders(_config.headers, options.headers),
+ };
+
+ if (opts.security) {
+ await setAuthParams({
+ ...opts,
+ security: opts.security,
+ });
+ }
+
+ if (opts.requestValidator) {
+ await opts.requestValidator(opts);
+ }
+
+ if (opts.body && opts.bodySerializer) {
+ opts.body = opts.bodySerializer(opts.body);
+ }
+
+ // remove Content-Type header if body is empty to avoid sending invalid requests
+ if (opts.body === undefined || opts.body === '') {
+ opts.headers.delete('Content-Type');
+ }
+
+ const url = buildUrl(opts);
+ const requestInit: ReqInit = {
+ redirect: 'follow',
+ ...opts,
+ };
+
+ let request = new Request(url, requestInit);
+
+ for (const fn of interceptors.request._fns) {
+ if (fn) {
+ request = await fn(request, opts);
+ }
+ }
+
+ // fetch must be assigned here, otherwise it would throw the error:
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
+ const _fetch = opts.fetch!;
+ let response = await _fetch(request);
+
+ for (const fn of interceptors.response._fns) {
+ if (fn) {
+ response = await fn(response, request, opts);
+ }
+ }
+
+ const result = {
+ request,
+ response,
+ };
+
+ if (response.ok) {
+ if (
+ response.status === 204 ||
+ response.headers.get('Content-Length') === '0'
+ ) {
+ return opts.responseStyle === 'data'
+ ? {}
+ : {
+ data: {},
+ ...result,
+ };
+ }
+
+ const parseAs =
+ (opts.parseAs === 'auto'
+ ? getParseAs(response.headers.get('Content-Type'))
+ : opts.parseAs) ?? 'json';
+
+ let data: any;
+ switch (parseAs) {
+ case 'arrayBuffer':
+ case 'blob':
+ case 'formData':
+ case 'json':
+ case 'text':
+ data = await response[parseAs]();
+ break;
+ case 'stream':
+ return opts.responseStyle === 'data'
+ ? response.body
+ : {
+ data: response.body,
+ ...result,
+ };
+ }
+
+ if (parseAs === 'json') {
+ if (opts.responseValidator) {
+ await opts.responseValidator(data);
+ }
+
+ if (opts.responseTransformer) {
+ data = await opts.responseTransformer(data);
+ }
+ }
+
+ return opts.responseStyle === 'data'
+ ? data
+ : {
+ data,
+ ...result,
+ };
+ }
+
+ const textError = await response.text();
+ let jsonError: unknown;
+
+ try {
+ jsonError = JSON.parse(textError);
+ } catch {
+ // noop
+ }
+
+ const error = jsonError ?? textError;
+ let finalError = error;
+
+ for (const fn of interceptors.error._fns) {
+ if (fn) {
+ finalError = (await fn(error, response, request, opts)) as string;
+ }
+ }
+
+ finalError = finalError || ({} as string);
+
+ if (opts.throwOnError) {
+ throw finalError;
+ }
+
+ // TODO: we probably want to return error and improve types
+ return opts.responseStyle === 'data'
+ ? undefined
+ : {
+ error: finalError,
+ ...result,
+ };
+ };
+
+ return {
+ buildUrl,
+ connect: (options) => request({ ...options, method: 'CONNECT' }),
+ delete: (options) => request({ ...options, method: 'DELETE' }),
+ get: (options) => request({ ...options, method: 'GET' }),
+ getConfig,
+ head: (options) => request({ ...options, method: 'HEAD' }),
+ interceptors,
+ options: (options) => request({ ...options, method: 'OPTIONS' }),
+ patch: (options) => request({ ...options, method: 'PATCH' }),
+ post: (options) => request({ ...options, method: 'POST' }),
+ put: (options) => request({ ...options, method: 'PUT' }),
+ request,
+ setConfig,
+ trace: (options) => request({ ...options, method: 'TRACE' }),
+ };
+};
diff --git a/packages/sdk/js/src/gen/client/index.ts b/packages/sdk/js/src/gen/client/index.ts
new file mode 100644
index 000000000..5da1f7aee
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/index.ts
@@ -0,0 +1,22 @@
+export type { Auth } from '../core/auth';
+export type { QuerySerializerOptions } from '../core/bodySerializer';
+export {
+ formDataBodySerializer,
+ jsonBodySerializer,
+ urlSearchParamsBodySerializer,
+} from '../core/bodySerializer';
+export { buildClientParams } from '../core/params';
+export { createClient } from './client';
+export type {
+ Client,
+ ClientOptions,
+ Config,
+ CreateClientConfig,
+ Options,
+ OptionsLegacyParser,
+ RequestOptions,
+ RequestResult,
+ ResponseStyle,
+ TDataShape,
+} from './types';
+export { createConfig, mergeHeaders } from './utils';
diff --git a/packages/sdk/js/src/gen/client/types.ts b/packages/sdk/js/src/gen/client/types.ts
new file mode 100644
index 000000000..85295df07
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/types.ts
@@ -0,0 +1,222 @@
+import type { Auth } from '../core/auth';
+import type {
+ Client as CoreClient,
+ Config as CoreConfig,
+} from '../core/types';
+import type { Middleware } from './utils';
+
+export type ResponseStyle = 'data' | 'fields';
+
+export interface Config<T extends ClientOptions = ClientOptions>
+ extends Omit<RequestInit, 'body' | 'headers' | 'method'>,
+ CoreConfig {
+ /**
+ * Base URL for all requests made by this client.
+ */
+ baseUrl?: T['baseUrl'];
+ /**
+ * Fetch API implementation. You can use this option to provide a custom
+ * fetch instance.
+ *
+ * @default globalThis.fetch
+ */
+ fetch?: (request: Request) => ReturnType<typeof fetch>;
+ /**
+ * Please don't use the Fetch client for Next.js applications. The `next`
+ * options won't have any effect.
+ *
+ * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
+ */
+ next?: never;
+ /**
+ * Return the response data parsed in a specified format. By default, `auto`
+ * will infer the appropriate method from the `Content-Type` response header.
+ * You can override this behavior with any of the {@link Body} methods.
+ * Select `stream` if you don't want to parse response data at all.
+ *
+ * @default 'auto'
+ */
+ parseAs?:
+ | 'arrayBuffer'
+ | 'auto'
+ | 'blob'
+ | 'formData'
+ | 'json'
+ | 'stream'
+ | 'text';
+ /**
+ * Should we return only data or multiple fields (data, error, response, etc.)?
+ *
+ * @default 'fields'
+ */
+ responseStyle?: ResponseStyle;
+ /**
+ * Throw an error instead of returning it in the response?
+ *
+ * @default false
+ */
+ throwOnError?: T['throwOnError'];
+}
+
+export interface RequestOptions<
+ TResponseStyle extends ResponseStyle = 'fields',
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+> extends Config<{
+ responseStyle: TResponseStyle;
+ throwOnError: ThrowOnError;
+ }> {
+ /**
+ * Any body that you want to add to your request.
+ *
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
+ */
+ body?: unknown;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ /**
+ * Security mechanism(s) to use for the request.
+ */
+ security?: ReadonlyArray<Auth>;
+ url: Url;
+}
+
+export type RequestResult<
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = ThrowOnError extends true
+ ? Promise<
+ TResponseStyle extends 'data'
+ ? TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData
+ : {
+ data: TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData;
+ request: Request;
+ response: Response;
+ }
+ >
+ : Promise<
+ TResponseStyle extends 'data'
+ ?
+ | (TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData)
+ | undefined
+ : (
+ | {
+ data: TData extends Record<string, unknown>
+ ? TData[keyof TData]
+ : TData;
+ error: undefined;
+ }
+ | {
+ data: undefined;
+ error: TError extends Record<string, unknown>
+ ? TError[keyof TError]
+ : TError;
+ }
+ ) & {
+ request: Request;
+ response: Response;
+ }
+ >;
+
+export interface ClientOptions {
+ baseUrl?: string;
+ responseStyle?: ResponseStyle;
+ throwOnError?: boolean;
+}
+
+type MethodFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'>,
+) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
+
+type RequestFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> &
+ Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, 'method'>,
+) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
+
+type BuildUrlFn = <
+ TData extends {
+ body?: unknown;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ url: string;
+ },
+>(
+ options: Pick<TData, 'url'> & Options<TData>,
+) => string;
+
+export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
+ interceptors: Middleware<Request, Response, unknown, RequestOptions>;
+};
+
+/**
+ * The `createClientConfig()` function will be called on client initialization
+ * and the returned object will become the client's initial configuration.
+ *
+ * You may want to initialize your client this way instead of calling
+ * `setConfig()`. This is useful for example if you're using Next.js
+ * to ensure your client always has the correct values.
+ */
+export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
+ override?: Config<ClientOptions & T>,
+) => Config<Required<ClientOptions> & T>;
+
+export interface TDataShape {
+ body?: unknown;
+ headers?: unknown;
+ path?: unknown;
+ query?: unknown;
+ url: string;
+}
+
+type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
+
+export type Options<
+ TData extends TDataShape = TDataShape,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'body' | 'path' | 'query' | 'url'
+> &
+ Omit<TData, 'url'>;
+
+export type OptionsLegacyParser<
+ TData = unknown,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = TData extends { body?: any }
+ ? TData extends { headers?: any }
+ ? OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'body' | 'headers' | 'url'
+ > &
+ TData
+ : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'url'> &
+ TData &
+ Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'headers'>
+ : TData extends { headers?: any }
+ ? OmitKeys<
+ RequestOptions<TResponseStyle, ThrowOnError>,
+ 'headers' | 'url'
+ > &
+ TData &
+ Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'body'>
+ : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'url'> & TData;
diff --git a/packages/sdk/js/src/gen/client/utils.ts b/packages/sdk/js/src/gen/client/utils.ts
new file mode 100644
index 000000000..a52e67292
--- /dev/null
+++ b/packages/sdk/js/src/gen/client/utils.ts
@@ -0,0 +1,417 @@
+import { getAuthToken } from '../core/auth';
+import type {
+ QuerySerializer,
+ QuerySerializerOptions,
+} from '../core/bodySerializer';
+import { jsonBodySerializer } from '../core/bodySerializer';
+import {
+ serializeArrayParam,
+ serializeObjectParam,
+ serializePrimitiveParam,
+} from '../core/pathSerializer';
+import type { Client, ClientOptions, Config, RequestOptions } from './types';
+
+interface PathSerializer {
+ path: Record<string, unknown>;
+ url: string;
+}
+
+const PATH_PARAM_RE = /\{[^{}]+\}/g;
+
+type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
+type MatrixStyle = 'label' | 'matrix' | 'simple';
+type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
+
+const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
+ let url = _url;
+ const matches = _url.match(PATH_PARAM_RE);
+ if (matches) {
+ for (const match of matches) {
+ let explode = false;
+ let name = match.substring(1, match.length - 1);
+ let style: ArraySeparatorStyle = 'simple';
+
+ if (name.endsWith('*')) {
+ explode = true;
+ name = name.substring(0, name.length - 1);
+ }
+
+ if (name.startsWith('.')) {
+ name = name.substring(1);
+ style = 'label';
+ } else if (name.startsWith(';')) {
+ name = name.substring(1);
+ style = 'matrix';
+ }
+
+ const value = path[name];
+
+ if (value === undefined || value === null) {
+ continue;
+ }
+
+ if (Array.isArray(value)) {
+ url = url.replace(
+ match,
+ serializeArrayParam({ explode, name, style, value }),
+ );
+ continue;
+ }
+
+ if (typeof value === 'object') {
+ url = url.replace(
+ match,
+ serializeObjectParam({
+ explode,
+ name,
+ style,
+ value: value as Record<string, unknown>,
+ valueOnly: true,
+ }),
+ );
+ continue;
+ }
+
+ if (style === 'matrix') {
+ url = url.replace(
+ match,
+ `;${serializePrimitiveParam({
+ name,
+ value: value as string,
+ })}`,
+ );
+ continue;
+ }
+
+ const replaceValue = encodeURIComponent(
+ style === 'label' ? `.${value as string}` : (value as string),
+ );
+ url = url.replace(match, replaceValue);
+ }
+ }
+ return url;
+};
+
+export const createQuerySerializer = <T = unknown>({
+ allowReserved,
+ array,
+ object,
+}: QuerySerializerOptions = {}) => {
+ const querySerializer = (queryParams: T) => {
+ const search: string[] = [];
+ if (queryParams && typeof queryParams === 'object') {
+ for (const name in queryParams) {
+ const value = queryParams[name];
+
+ if (value === undefined || value === null) {
+ continue;
+ }
+
+ if (Array.isArray(value)) {
+ const serializedArray = serializeArrayParam({
+ allowReserved,
+ explode: true,
+ name,
+ style: 'form',
+ value,
+ ...array,
+ });
+ if (serializedArray) search.push(serializedArray);
+ } else if (typeof value === 'object') {
+ const serializedObject = serializeObjectParam({
+ allowReserved,
+ explode: true,
+ name,
+ style: 'deepObject',
+ value: value as Record<string, unknown>,
+ ...object,
+ });
+ if (serializedObject) search.push(serializedObject);
+ } else {
+ const serializedPrimitive = serializePrimitiveParam({
+ allowReserved,
+ name,
+ value: value as string,
+ });
+ if (serializedPrimitive) search.push(serializedPrimitive);
+ }
+ }
+ }
+ return search.join('&');
+ };
+ return querySerializer;
+};
+
+/**
+ * Infers parseAs value from provided Content-Type header.
+ */
+export const getParseAs = (
+ contentType: string | null,
+): Exclude<Config['parseAs'], 'auto'> => {
+ if (!contentType) {
+ // If no Content-Type header is provided, the best we can do is return the raw response body,
+ // which is effectively the same as the 'stream' option.
+ return 'stream';
+ }
+
+ const cleanContent = contentType.split(';')[0]?.trim();
+
+ if (!cleanContent) {
+ return;
+ }
+
+ if (
+ cleanContent.startsWith('application/json') ||
+ cleanContent.endsWith('+json')
+ ) {
+ return 'json';
+ }
+
+ if (cleanContent === 'multipart/form-data') {
+ return 'formData';
+ }
+
+ if (
+ ['application/', 'audio/', 'image/', 'video/'].some((type) =>
+ cleanContent.startsWith(type),
+ )
+ ) {
+ return 'blob';
+ }
+
+ if (cleanContent.startsWith('text/')) {
+ return 'text';
+ }
+
+ return;
+};
+
+export const setAuthParams = async ({
+ security,
+ ...options
+}: Pick<Required<RequestOptions>, 'security'> &
+ Pick<RequestOptions, 'auth' | 'query'> & {
+ headers: Headers;
+ }) => {
+ for (const auth of security) {
+ const token = await getAuthToken(auth, options.auth);
+
+ if (!token) {
+ continue;
+ }
+
+ const name = auth.name ?? 'Authorization';
+
+ switch (auth.in) {
+ case 'query':
+ if (!options.query) {
+ options.query = {};
+ }
+ options.query[name] = token;
+ break;
+ case 'cookie':
+ options.headers.append('Cookie', `${name}=${token}`);
+ break;
+ case 'header':
+ default:
+ options.headers.set(name, token);
+ break;
+ }
+
+ return;
+ }
+};
+
+export const buildUrl: Client['buildUrl'] = (options) => {
+ const url = getUrl({
+ baseUrl: options.baseUrl as string,
+ path: options.path,
+ query: options.query,
+ querySerializer:
+ typeof options.querySerializer === 'function'
+ ? options.querySerializer
+ : createQuerySerializer(options.querySerializer),
+ url: options.url,
+ });
+ return url;
+};
+
+export const getUrl = ({
+ baseUrl,
+ path,
+ query,
+ querySerializer,
+ url: _url,
+}: {
+ baseUrl?: string;
+ path?: Record<string, unknown>;
+ query?: Record<string, unknown>;
+ querySerializer: QuerySerializer;
+ url: string;
+}) => {
+ const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
+ let url = (baseUrl ?? '') + pathUrl;
+ if (path) {
+ url = defaultPathSerializer({ path, url });
+ }
+ let search = query ? querySerializer(query) : '';
+ if (search.startsWith('?')) {
+ search = search.substring(1);
+ }
+ if (search) {
+ url += `?${search}`;
+ }
+ return url;
+};
+
+export const mergeConfigs = (a: Config, b: Config): Config => {
+ const config = { ...a, ...b };
+ if (config.baseUrl?.endsWith('/')) {
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
+ }
+ config.headers = mergeHeaders(a.headers, b.headers);
+ return config;
+};
+
+export const mergeHeaders = (
+ ...headers: Array<Required<Config>['headers'] | undefined>
+): Headers => {
+ const mergedHeaders = new Headers();
+ for (const header of headers) {
+ if (!header || typeof header !== 'object') {
+ continue;
+ }
+
+ const iterator =
+ header instanceof Headers ? header.entries() : Object.entries(header);
+
+ for (const [key, value] of iterator) {
+ if (value === null) {
+ mergedHeaders.delete(key);
+ } else if (Array.isArray(value)) {
+ for (const v of value) {
+ mergedHeaders.append(key, v as string);
+ }
+ } else if (value !== undefined) {
+ // assume object headers are meant to be JSON stringified, i.e. their
+ // content value in OpenAPI specification is 'application/json'
+ mergedHeaders.set(
+ key,
+ typeof value === 'object' ? JSON.stringify(value) : (value as string),
+ );
+ }
+ }
+ }
+ return mergedHeaders;
+};
+
+type ErrInterceptor<Err, Res, Req, Options> = (
+ error: Err,
+ response: Res,
+ request: Req,
+ options: Options,
+) => Err | Promise<Err>;
+
+type ReqInterceptor<Req, Options> = (
+ request: Req,
+ options: Options,
+) => Req | Promise<Req>;
+
+type ResInterceptor<Res, Req, Options> = (
+ response: Res,
+ request: Req,
+ options: Options,
+) => Res | Promise<Res>;
+
+class Interceptors<Interceptor> {
+ _fns: (Interceptor | null)[];
+
+ constructor() {
+ this._fns = [];
+ }
+
+ clear() {
+ this._fns = [];
+ }
+
+ getInterceptorIndex(id: number | Interceptor): number {
+ if (typeof id === 'number') {
+ return this._fns[id] ? id : -1;
+ } else {
+ return this._fns.indexOf(id);
+ }
+ }
+ exists(id: number | Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ return !!this._fns[index];
+ }
+
+ eject(id: number | Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ if (this._fns[index]) {
+ this._fns[index] = null;
+ }
+ }
+
+ update(id: number | Interceptor, fn: Interceptor) {
+ const index = this.getInterceptorIndex(id);
+ if (this._fns[index]) {
+ this._fns[index] = fn;
+ return id;
+ } else {
+ return false;
+ }
+ }
+
+ use(fn: Interceptor) {
+ this._fns = [...this._fns, fn];
+ return this._fns.length - 1;
+ }
+}
+
+// `createInterceptors()` response, meant for external use as it does not
+// expose internals
+export interface Middleware<Req, Res, Err, Options> {
+ error: Pick<
+ Interceptors<ErrInterceptor<Err, Res, Req, Options>>,
+ 'eject' | 'use'
+ >;
+ request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;
+ response: Pick<
+ Interceptors<ResInterceptor<Res, Req, Options>>,
+ 'eject' | 'use'
+ >;
+}
+
+// do not add `Middleware` as return type so we can use _fns internally
+export const createInterceptors = <Req, Res, Err, Options>() => ({
+ error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),
+ request: new Interceptors<ReqInterceptor<Req, Options>>(),
+ response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
+});
+
+const defaultQuerySerializer = createQuerySerializer({
+ allowReserved: false,
+ array: {
+ explode: true,
+ style: 'form',
+ },
+ object: {
+ explode: true,
+ style: 'deepObject',
+ },
+});
+
+const defaultHeaders = {
+ 'Content-Type': 'application/json',
+};
+
+export const createConfig = <T extends ClientOptions = ClientOptions>(
+ override: Config<Omit<ClientOptions, keyof T> & T> = {},
+): Config<Omit<ClientOptions, keyof T> & T> => ({
+ ...jsonBodySerializer,
+ headers: defaultHeaders,
+ parseAs: 'auto',
+ querySerializer: defaultQuerySerializer,
+ ...override,
+});
diff --git a/packages/sdk/js/src/gen/core/auth.ts b/packages/sdk/js/src/gen/core/auth.ts
new file mode 100644
index 000000000..451c7f30f
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/auth.ts
@@ -0,0 +1,40 @@
+export type AuthToken = string | undefined;
+
+export interface Auth {
+ /**
+ * Which part of the request do we use to send the auth?
+ *
+ * @default 'header'
+ */
+ in?: 'header' | 'query' | 'cookie';
+ /**
+ * Header or query parameter name.
+ *
+ * @default 'Authorization'
+ */
+ name?: string;
+ scheme?: 'basic' | 'bearer';
+ type: 'apiKey' | 'http';
+}
+
+export const getAuthToken = async (
+ auth: Auth,
+ callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
+): Promise<string | undefined> => {
+ const token =
+ typeof callback === 'function' ? await callback(auth) : callback;
+
+ if (!token) {
+ return;
+ }
+
+ if (auth.scheme === 'bearer') {
+ return `Bearer ${token}`;
+ }
+
+ if (auth.scheme === 'basic') {
+ return `Basic ${btoa(token)}`;
+ }
+
+ return token;
+};
diff --git a/packages/sdk/js/src/gen/core/bodySerializer.ts b/packages/sdk/js/src/gen/core/bodySerializer.ts
new file mode 100644
index 000000000..98ce7791f
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/bodySerializer.ts
@@ -0,0 +1,88 @@
+import type {
+ ArrayStyle,
+ ObjectStyle,
+ SerializerOptions,
+} from './pathSerializer';
+
+export type QuerySerializer = (query: Record<string, unknown>) => string;
+
+export type BodySerializer = (body: any) => any;
+
+export interface QuerySerializerOptions {
+ allowReserved?: boolean;
+ array?: SerializerOptions<ArrayStyle>;
+ object?: SerializerOptions<ObjectStyle>;
+}
+
+const serializeFormDataPair = (
+ data: FormData,
+ key: string,
+ value: unknown,
+): void => {
+ if (typeof value === 'string' || value instanceof Blob) {
+ data.append(key, value);
+ } else {
+ data.append(key, JSON.stringify(value));
+ }
+};
+
+const serializeUrlSearchParamsPair = (
+ data: URLSearchParams,
+ key: string,
+ value: unknown,
+): void => {
+ if (typeof value === 'string') {
+ data.append(key, value);
+ } else {
+ data.append(key, JSON.stringify(value));
+ }
+};
+
+export const formDataBodySerializer = {
+ bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
+ body: T,
+ ): FormData => {
+ const data = new FormData();
+
+ Object.entries(body).forEach(([key, value]) => {
+ if (value === undefined || value === null) {
+ return;
+ }
+ if (Array.isArray(value)) {
+ value.forEach((v) => serializeFormDataPair(data, key, v));
+ } else {
+ serializeFormDataPair(data, key, value);
+ }
+ });
+
+ return data;
+ },
+};
+
+export const jsonBodySerializer = {
+ bodySerializer: <T>(body: T): string =>
+ JSON.stringify(body, (_key, value) =>
+ typeof value === 'bigint' ? value.toString() : value,
+ ),
+};
+
+export const urlSearchParamsBodySerializer = {
+ bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
+ body: T,
+ ): string => {
+ const data = new URLSearchParams();
+
+ Object.entries(body).forEach(([key, value]) => {
+ if (value === undefined || value === null) {
+ return;
+ }
+ if (Array.isArray(value)) {
+ value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));
+ } else {
+ serializeUrlSearchParamsPair(data, key, value);
+ }
+ });
+
+ return data.toString();
+ },
+};
diff --git a/packages/sdk/js/src/gen/core/params.ts b/packages/sdk/js/src/gen/core/params.ts
new file mode 100644
index 000000000..ba35263d8
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/params.ts
@@ -0,0 +1,151 @@
+type Slot = 'body' | 'headers' | 'path' | 'query';
+
+export type Field =
+ | {
+ in: Exclude<Slot, 'body'>;
+ /**
+ * Field name. This is the name we want the user to see and use.
+ */
+ key: string;
+ /**
+ * Field mapped name. This is the name we want to use in the request.
+ * If omitted, we use the same value as `key`.
+ */
+ map?: string;
+ }
+ | {
+ in: Extract<Slot, 'body'>;
+ /**
+ * Key isn't required for bodies.
+ */
+ key?: string;
+ map?: string;
+ };
+
+export interface Fields {
+ allowExtra?: Partial<Record<Slot, boolean>>;
+ args?: ReadonlyArray<Field>;
+}
+
+export type FieldsConfig = ReadonlyArray<Field | Fields>;
+
+const extraPrefixesMap: Record<string, Slot> = {
+ $body_: 'body',
+ $headers_: 'headers',
+ $path_: 'path',
+ $query_: 'query',
+};
+const extraPrefixes = Object.entries(extraPrefixesMap);
+
+type KeyMap = Map<
+ string,
+ {
+ in: Slot;
+ map?: string;
+ }
+>;
+
+const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
+ if (!map) {
+ map = new Map();
+ }
+
+ for (const config of fields) {
+ if ('in' in config) {
+ if (config.key) {
+ map.set(config.key, {
+ in: config.in,
+ map: config.map,
+ });
+ }
+ } else if (config.args) {
+ buildKeyMap(config.args, map);
+ }
+ }
+
+ return map;
+};
+
+interface Params {
+ body: unknown;
+ headers: Record<string, unknown>;
+ path: Record<string, unknown>;
+ query: Record<string, unknown>;
+}
+
+const stripEmptySlots = (params: Params) => {
+ for (const [slot, value] of Object.entries(params)) {
+ if (value && typeof value === 'object' && !Object.keys(value).length) {
+ delete params[slot as Slot];
+ }
+ }
+};
+
+export const buildClientParams = (
+ args: ReadonlyArray<unknown>,
+ fields: FieldsConfig,
+) => {
+ const params: Params = {
+ body: {},
+ headers: {},
+ path: {},
+ query: {},
+ };
+
+ const map = buildKeyMap(fields);
+
+ let config: FieldsConfig[number] | undefined;
+
+ for (const [index, arg] of args.entries()) {
+ if (fields[index]) {
+ config = fields[index];
+ }
+
+ if (!config) {
+ continue;
+ }
+
+ if ('in' in config) {
+ if (config.key) {
+ const field = map.get(config.key)!;
+ const name = field.map || config.key;
+ (params[field.in] as Record<string, unknown>)[name] = arg;
+ } else {
+ params.body = arg;
+ }
+ } else {
+ for (const [key, value] of Object.entries(arg ?? {})) {
+ const field = map.get(key);
+
+ if (field) {
+ const name = field.map || key;
+ (params[field.in] as Record<string, unknown>)[name] = value;
+ } else {
+ const extra = extraPrefixes.find(([prefix]) =>
+ key.startsWith(prefix),
+ );
+
+ if (extra) {
+ const [prefix, slot] = extra;
+ (params[slot] as Record<string, unknown>)[
+ key.slice(prefix.length)
+ ] = value;
+ } else {
+ for (const [slot, allowed] of Object.entries(
+ config.allowExtra ?? {},
+ )) {
+ if (allowed) {
+ (params[slot as Slot] as Record<string, unknown>)[key] = value;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ stripEmptySlots(params);
+
+ return params;
+};
diff --git a/packages/sdk/js/src/gen/core/pathSerializer.ts b/packages/sdk/js/src/gen/core/pathSerializer.ts
new file mode 100644
index 000000000..d692cf0a3
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/pathSerializer.ts
@@ -0,0 +1,179 @@
+interface SerializeOptions<T>
+ extends SerializePrimitiveOptions,
+ SerializerOptions<T> {}
+
+interface SerializePrimitiveOptions {
+ allowReserved?: boolean;
+ name: string;
+}
+
+export interface SerializerOptions<T> {
+ /**
+ * @default true
+ */
+ explode: boolean;
+ style: T;
+}
+
+export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
+export type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
+type MatrixStyle = 'label' | 'matrix' | 'simple';
+export type ObjectStyle = 'form' | 'deepObject';
+type ObjectSeparatorStyle = ObjectStyle | MatrixStyle;
+
+interface SerializePrimitiveParam extends SerializePrimitiveOptions {
+ value: string;
+}
+
+export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
+ switch (style) {
+ case 'label':
+ return '.';
+ case 'matrix':
+ return ';';
+ case 'simple':
+ return ',';
+ default:
+ return '&';
+ }
+};
+
+export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
+ switch (style) {
+ case 'form':
+ return ',';
+ case 'pipeDelimited':
+ return '|';
+ case 'spaceDelimited':
+ return '%20';
+ default:
+ return ',';
+ }
+};
+
+export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
+ switch (style) {
+ case 'label':
+ return '.';
+ case 'matrix':
+ return ';';
+ case 'simple':
+ return ',';
+ default:
+ return '&';
+ }
+};
+
+export const serializeArrayParam = ({
+ allowReserved,
+ explode,
+ name,
+ style,
+ value,
+}: SerializeOptions<ArraySeparatorStyle> & {
+ value: unknown[];
+}) => {
+ if (!explode) {
+ const joinedValues = (
+ allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
+ ).join(separatorArrayNoExplode(style));
+ switch (style) {
+ case 'label':
+ return `.${joinedValues}`;
+ case 'matrix':
+ return `;${name}=${joinedValues}`;
+ case 'simple':
+ return joinedValues;
+ default:
+ return `${name}=${joinedValues}`;
+ }
+ }
+
+ const separator = separatorArrayExplode(style);
+ const joinedValues = value
+ .map((v) => {
+ if (style === 'label' || style === 'simple') {
+ return allowReserved ? v : encodeURIComponent(v as string);
+ }
+
+ return serializePrimitiveParam({
+ allowReserved,
+ name,
+ value: v as string,
+ });
+ })
+ .join(separator);
+ return style === 'label' || style === 'matrix'
+ ? separator + joinedValues
+ : joinedValues;
+};
+
+export const serializePrimitiveParam = ({
+ allowReserved,
+ name,
+ value,
+}: SerializePrimitiveParam) => {
+ if (value === undefined || value === null) {
+ return '';
+ }
+
+ if (typeof value === 'object') {
+ throw new Error(
+ 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',
+ );
+ }
+
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
+};
+
+export const serializeObjectParam = ({
+ allowReserved,
+ explode,
+ name,
+ style,
+ value,
+ valueOnly,
+}: SerializeOptions<ObjectSeparatorStyle> & {
+ value: Record<string, unknown> | Date;
+ valueOnly?: boolean;
+}) => {
+ if (value instanceof Date) {
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
+ }
+
+ if (style !== 'deepObject' && !explode) {
+ let values: string[] = [];
+ Object.entries(value).forEach(([key, v]) => {
+ values = [
+ ...values,
+ key,
+ allowReserved ? (v as string) : encodeURIComponent(v as string),
+ ];
+ });
+ const joinedValues = values.join(',');
+ switch (style) {
+ case 'form':
+ return `${name}=${joinedValues}`;
+ case 'label':
+ return `.${joinedValues}`;
+ case 'matrix':
+ return `;${name}=${joinedValues}`;
+ default:
+ return joinedValues;
+ }
+ }
+
+ const separator = separatorObjectExplode(style);
+ const joinedValues = Object.entries(value)
+ .map(([key, v]) =>
+ serializePrimitiveParam({
+ allowReserved,
+ name: style === 'deepObject' ? `${name}[${key}]` : key,
+ value: v as string,
+ }),
+ )
+ .join(separator);
+ return style === 'label' || style === 'matrix'
+ ? separator + joinedValues
+ : joinedValues;
+};
diff --git a/packages/sdk/js/src/gen/core/types.ts b/packages/sdk/js/src/gen/core/types.ts
new file mode 100644
index 000000000..2dd4106fb
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/types.ts
@@ -0,0 +1,118 @@
+import type { Auth, AuthToken } from './auth';
+import type {
+ BodySerializer,
+ QuerySerializer,
+ QuerySerializerOptions,
+} from './bodySerializer';
+
+export interface Client<
+ RequestFn = never,
+ Config = unknown,
+ MethodFn = never,
+ BuildUrlFn = never,
+> {
+ /**
+ * Returns the final request URL.
+ */
+ buildUrl: BuildUrlFn;
+ connect: MethodFn;
+ delete: MethodFn;
+ get: MethodFn;
+ getConfig: () => Config;
+ head: MethodFn;
+ options: MethodFn;
+ patch: MethodFn;
+ post: MethodFn;
+ put: MethodFn;
+ request: RequestFn;
+ setConfig: (config: Config) => Config;
+ trace: MethodFn;
+}
+
+export interface Config {
+ /**
+ * Auth token or a function returning auth token. The resolved value will be
+ * added to the request payload as defined by its `security` array.
+ */
+ auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
+ /**
+ * A function for serializing request body parameter. By default,
+ * {@link JSON.stringify()} will be used.
+ */
+ bodySerializer?: BodySerializer | null;
+ /**
+ * An object containing any HTTP headers that you want to pre-populate your
+ * `Headers` object with.
+ *
+ * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
+ */
+ headers?:
+ | RequestInit['headers']
+ | Record<
+ string,
+ | string
+ | number
+ | boolean
+ | (string | number | boolean)[]
+ | null
+ | undefined
+ | unknown
+ >;
+ /**
+ * The request method.
+ *
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
+ */
+ method?:
+ | 'CONNECT'
+ | 'DELETE'
+ | 'GET'
+ | 'HEAD'
+ | 'OPTIONS'
+ | 'PATCH'
+ | 'POST'
+ | 'PUT'
+ | 'TRACE';
+ /**
+ * A function for serializing request query parameters. By default, arrays
+ * will be exploded in form style, objects will be exploded in deepObject
+ * style, and reserved characters are percent-encoded.
+ *
+ * This method will have no effect if the native `paramsSerializer()` Axios
+ * API function is used.
+ *
+ * {@link https://swagger.io/docs/specification/serialization/#query View examples}
+ */
+ querySerializer?: QuerySerializer | QuerySerializerOptions;
+ /**
+ * A function validating request data. This is useful if you want to ensure
+ * the request conforms to the desired shape, so it can be safely sent to
+ * the server.
+ */
+ requestValidator?: (data: unknown) => Promise<unknown>;
+ /**
+ * A function transforming response data before it's returned. This is useful
+ * for post-processing data, e.g. converting ISO strings into Date objects.
+ */
+ responseTransformer?: (data: unknown) => Promise<unknown>;
+ /**
+ * A function validating response data. This is useful if you want to ensure
+ * the response conforms to the desired shape, so it can be safely passed to
+ * the transformers and returned to the user.
+ */
+ responseValidator?: (data: unknown) => Promise<unknown>;
+}
+
+type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never]
+ ? true
+ : [T] extends [never | undefined]
+ ? [undefined] extends [T]
+ ? false
+ : true
+ : false;
+
+export type OmitNever<T extends Record<string, unknown>> = {
+ [K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true
+ ? never
+ : K]: T[K];
+};
diff --git a/packages/sdk/js/src/gen/sdk.gen.ts b/packages/sdk/js/src/gen/sdk.gen.ts
new file mode 100644
index 000000000..312084856
--- /dev/null
+++ b/packages/sdk/js/src/gen/sdk.gen.ts
@@ -0,0 +1,339 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { Options as ClientOptions, TDataShape, Client } from './client';
+import type { EventSubscribeData, EventSubscribeResponses, AppGetData, AppGetResponses, AppInitData, AppInitResponses, ConfigGetData, ConfigGetResponses, SessionListData, SessionListResponses, SessionCreateData, SessionCreateResponses, SessionCreateErrors, SessionDeleteData, SessionDeleteResponses, SessionInitData, SessionInitResponses, SessionAbortData, SessionAbortResponses, SessionUnshareData, SessionUnshareResponses, SessionShareData, SessionShareResponses, SessionSummarizeData, SessionSummarizeResponses, SessionMessagesData, SessionMessagesResponses, SessionChatData, SessionChatResponses, SessionRevertData, SessionRevertResponses, SessionUnrevertData, SessionUnrevertResponses, ConfigProvidersData, ConfigProvidersResponses, FindTextData, FindTextResponses, FindFilesData, FindFilesResponses, FindSymbolsData, FindSymbolsResponses, FileReadData, FileReadResponses, FileStatusData, FileStatusResponses, AppLogData, AppLogResponses, AppModesData, AppModesResponses, TuiAppendPromptData, TuiAppendPromptResponses, TuiOpenHelpData, TuiOpenHelpResponses } from './types.gen';
+import { client as _heyApiClient } from './client.gen';
+
+export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
+ /**
+ * You can provide a client instance returned by `createClient()` instead of
+ * individual options. This might be also useful if you want to implement a
+ * custom client.
+ */
+ client?: Client;
+ /**
+ * You can pass arbitrary values through the `meta` object. This can be
+ * used to access values that aren't defined as part of the SDK function.
+ */
+ meta?: Record<string, unknown>;
+};
+
+class _HeyApiClient {
+ protected _client: Client = _heyApiClient;
+
+ constructor(args?: {
+ client?: Client;
+ }) {
+ if (args?.client) {
+ this._client = args.client;
+ }
+ }
+}
+
+class Event extends _HeyApiClient {
+ /**
+ * Get events
+ */
+ public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<EventSubscribeResponses, unknown, ThrowOnError>({
+ url: '/event',
+ ...options
+ });
+ }
+}
+
+class App extends _HeyApiClient {
+ /**
+ * Get app info
+ */
+ public get<ThrowOnError extends boolean = false>(options?: Options<AppGetData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<AppGetResponses, unknown, ThrowOnError>({
+ url: '/app',
+ ...options
+ });
+ }
+
+ /**
+ * Initialize the app
+ */
+ public init<ThrowOnError extends boolean = false>(options?: Options<AppInitData, ThrowOnError>) {
+ return (options?.client ?? this._client).post<AppInitResponses, unknown, ThrowOnError>({
+ url: '/app/init',
+ ...options
+ });
+ }
+
+ /**
+ * Write a log entry to the server logs
+ */
+ public log<ThrowOnError extends boolean = false>(options?: Options<AppLogData, ThrowOnError>) {
+ return (options?.client ?? this._client).post<AppLogResponses, unknown, ThrowOnError>({
+ url: '/log',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options?.headers
+ }
+ });
+ }
+
+ /**
+ * List all modes
+ */
+ public modes<ThrowOnError extends boolean = false>(options?: Options<AppModesData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<AppModesResponses, unknown, ThrowOnError>({
+ url: '/mode',
+ ...options
+ });
+ }
+}
+
+class Config extends _HeyApiClient {
+ /**
+ * Get config info
+ */
+ public get<ThrowOnError extends boolean = false>(options?: Options<ConfigGetData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<ConfigGetResponses, unknown, ThrowOnError>({
+ url: '/config',
+ ...options
+ });
+ }
+
+ /**
+ * List all providers
+ */
+ public providers<ThrowOnError extends boolean = false>(options?: Options<ConfigProvidersData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<ConfigProvidersResponses, unknown, ThrowOnError>({
+ url: '/config/providers',
+ ...options
+ });
+ }
+}
+
+class Session extends _HeyApiClient {
+ /**
+ * List all sessions
+ */
+ public list<ThrowOnError extends boolean = false>(options?: Options<SessionListData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<SessionListResponses, unknown, ThrowOnError>({
+ url: '/session',
+ ...options
+ });
+ }
+
+ /**
+ * Create a new session
+ */
+ public create<ThrowOnError extends boolean = false>(options?: Options<SessionCreateData, ThrowOnError>) {
+ return (options?.client ?? this._client).post<SessionCreateResponses, SessionCreateErrors, ThrowOnError>({
+ url: '/session',
+ ...options
+ });
+ }
+
+ /**
+ * Delete a session and all its data
+ */
+ public delete<ThrowOnError extends boolean = false>(options: Options<SessionDeleteData, ThrowOnError>) {
+ return (options.client ?? this._client).delete<SessionDeleteResponses, unknown, ThrowOnError>({
+ url: '/session/{id}',
+ ...options
+ });
+ }
+
+ /**
+ * Analyze the app and create an AGENTS.md file
+ */
+ public init<ThrowOnError extends boolean = false>(options: Options<SessionInitData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionInitResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/init',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+ });
+ }
+
+ /**
+ * Abort a session
+ */
+ public abort<ThrowOnError extends boolean = false>(options: Options<SessionAbortData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionAbortResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/abort',
+ ...options
+ });
+ }
+
+ /**
+ * Unshare the session
+ */
+ public unshare<ThrowOnError extends boolean = false>(options: Options<SessionUnshareData, ThrowOnError>) {
+ return (options.client ?? this._client).delete<SessionUnshareResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/share',
+ ...options
+ });
+ }
+
+ /**
+ * Share a session
+ */
+ public share<ThrowOnError extends boolean = false>(options: Options<SessionShareData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionShareResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/share',
+ ...options
+ });
+ }
+
+ /**
+ * Summarize the session
+ */
+ public summarize<ThrowOnError extends boolean = false>(options: Options<SessionSummarizeData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionSummarizeResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/summarize',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+ });
+ }
+
+ /**
+ * List messages for a session
+ */
+ public messages<ThrowOnError extends boolean = false>(options: Options<SessionMessagesData, ThrowOnError>) {
+ return (options.client ?? this._client).get<SessionMessagesResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/message',
+ ...options
+ });
+ }
+
+ /**
+ * Create and send a new message to a session
+ */
+ public chat<ThrowOnError extends boolean = false>(options: Options<SessionChatData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionChatResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/message',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+ });
+ }
+
+ /**
+ * Revert a message
+ */
+ public revert<ThrowOnError extends boolean = false>(options: Options<SessionRevertData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionRevertResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/revert',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+ });
+ }
+
+ /**
+ * Restore all reverted messages
+ */
+ public unrevert<ThrowOnError extends boolean = false>(options: Options<SessionUnrevertData, ThrowOnError>) {
+ return (options.client ?? this._client).post<SessionUnrevertResponses, unknown, ThrowOnError>({
+ url: '/session/{id}/unrevert',
+ ...options
+ });
+ }
+}
+
+class Find extends _HeyApiClient {
+ /**
+ * Find text in files
+ */
+ public text<ThrowOnError extends boolean = false>(options: Options<FindTextData, ThrowOnError>) {
+ return (options.client ?? this._client).get<FindTextResponses, unknown, ThrowOnError>({
+ url: '/find',
+ ...options
+ });
+ }
+
+ /**
+ * Find files
+ */
+ public files<ThrowOnError extends boolean = false>(options: Options<FindFilesData, ThrowOnError>) {
+ return (options.client ?? this._client).get<FindFilesResponses, unknown, ThrowOnError>({
+ url: '/find/file',
+ ...options
+ });
+ }
+
+ /**
+ * Find workspace symbols
+ */
+ public symbols<ThrowOnError extends boolean = false>(options: Options<FindSymbolsData, ThrowOnError>) {
+ return (options.client ?? this._client).get<FindSymbolsResponses, unknown, ThrowOnError>({
+ url: '/find/symbol',
+ ...options
+ });
+ }
+}
+
+class File extends _HeyApiClient {
+ /**
+ * Read a file
+ */
+ public read<ThrowOnError extends boolean = false>(options: Options<FileReadData, ThrowOnError>) {
+ return (options.client ?? this._client).get<FileReadResponses, unknown, ThrowOnError>({
+ url: '/file',
+ ...options
+ });
+ }
+
+ /**
+ * Get file status
+ */
+ public status<ThrowOnError extends boolean = false>(options?: Options<FileStatusData, ThrowOnError>) {
+ return (options?.client ?? this._client).get<FileStatusResponses, unknown, ThrowOnError>({
+ url: '/file/status',
+ ...options
+ });
+ }
+}
+
+class Tui extends _HeyApiClient {
+ /**
+ * Append prompt to the TUI
+ */
+ public appendPrompt<ThrowOnError extends boolean = false>(options?: Options<TuiAppendPromptData, ThrowOnError>) {
+ return (options?.client ?? this._client).post<TuiAppendPromptResponses, unknown, ThrowOnError>({
+ url: '/tui/append-prompt',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options?.headers
+ }
+ });
+ }
+
+ /**
+ * Open the help dialog
+ */
+ public openHelp<ThrowOnError extends boolean = false>(options?: Options<TuiOpenHelpData, ThrowOnError>) {
+ return (options?.client ?? this._client).post<TuiOpenHelpResponses, unknown, ThrowOnError>({
+ url: '/tui/open-help',
+ ...options
+ });
+ }
+}
+
+export class OpencodeClient extends _HeyApiClient {
+ event = new Event({ client: this._client });
+ app = new App({ client: this._client });
+ config = new Config({ client: this._client });
+ session = new Session({ client: this._client });
+ find = new Find({ client: this._client });
+ file = new File({ client: this._client });
+ tui = new Tui({ client: this._client });
+} \ No newline at end of file
diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts
new file mode 100644
index 000000000..6fcd1c415
--- /dev/null
+++ b/packages/sdk/js/src/gen/types.gen.ts
@@ -0,0 +1,1450 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+export type Event = ({
+ type: 'installation.updated';
+} & EventInstallationUpdated) | ({
+ type: 'lsp.client.diagnostics';
+} & EventLspClientDiagnostics) | ({
+ type: 'message.updated';
+} & EventMessageUpdated) | ({
+ type: 'message.removed';
+} & EventMessageRemoved) | ({
+ type: 'message.part.updated';
+} & EventMessagePartUpdated) | ({
+ type: 'message.part.removed';
+} & EventMessagePartRemoved) | ({
+ type: 'storage.write';
+} & EventStorageWrite) | ({
+ type: 'permission.updated';
+} & EventPermissionUpdated) | ({
+ type: 'file.edited';
+} & EventFileEdited) | ({
+ type: 'session.updated';
+} & EventSessionUpdated) | ({
+ type: 'session.deleted';
+} & EventSessionDeleted) | ({
+ type: 'session.idle';
+} & EventSessionIdle) | ({
+ type: 'session.error';
+} & EventSessionError) | ({
+ type: 'server.connected';
+} & EventServerConnected) | ({
+ type: 'file.watcher.updated';
+} & EventFileWatcherUpdated) | ({
+ type: 'ide.installed';
+} & EventIdeInstalled);
+
+export type EventInstallationUpdated = {
+ type: string;
+ properties: {
+ version: string;
+ };
+};
+
+export type EventLspClientDiagnostics = {
+ type: string;
+ properties: {
+ serverID: string;
+ path: string;
+ };
+};
+
+export type EventMessageUpdated = {
+ type: string;
+ properties: {
+ info: Message;
+ };
+};
+
+export type Message = ({
+ role: 'user';
+} & UserMessage) | ({
+ role: 'assistant';
+} & AssistantMessage);
+
+export type UserMessage = {
+ id: string;
+ sessionID: string;
+ role: string;
+ time: {
+ created: number;
+ };
+};
+
+export type AssistantMessage = {
+ id: string;
+ sessionID: string;
+ role: string;
+ time: {
+ created: number;
+ completed?: number;
+ };
+ error?: ({
+ name: 'ProviderAuthError';
+ } & ProviderAuthError) | ({
+ name: 'UnknownError';
+ } & UnknownError) | ({
+ name: 'MessageOutputLengthError';
+ } & MessageOutputLengthError) | ({
+ name: 'MessageAbortedError';
+ } & MessageAbortedError);
+ system: Array<string>;
+ modelID: string;
+ providerID: string;
+ mode: string;
+ path: {
+ cwd: string;
+ root: string;
+ };
+ summary?: boolean;
+ cost: number;
+ tokens: {
+ input: number;
+ output: number;
+ reasoning: number;
+ cache: {
+ read: number;
+ write: number;
+ };
+ };
+};
+
+export type ProviderAuthError = {
+ name: string;
+ data: {
+ providerID: string;
+ message: string;
+ };
+};
+
+export type UnknownError = {
+ name: string;
+ data: {
+ message: string;
+ };
+};
+
+export type MessageOutputLengthError = {
+ name: string;
+ data: {
+ [key: string]: unknown;
+ };
+};
+
+export type MessageAbortedError = {
+ name: string;
+ data: {
+ [key: string]: unknown;
+ };
+};
+
+export type EventMessageRemoved = {
+ type: string;
+ properties: {
+ sessionID: string;
+ messageID: string;
+ };
+};
+
+export type EventMessagePartUpdated = {
+ type: string;
+ properties: {
+ part: Part;
+ };
+};
+
+export type Part = ({
+ type: 'text';
+} & TextPart) | ({
+ type: 'file';
+} & FilePart) | ({
+ type: 'tool';
+} & ToolPart) | ({
+ type: 'step-start';
+} & StepStartPart) | ({
+ type: 'step-finish';
+} & StepFinishPart) | ({
+ type: 'snapshot';
+} & SnapshotPart) | ({
+ type: 'patch';
+} & PatchPart);
+
+export type TextPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ text: string;
+ synthetic?: boolean;
+ time?: {
+ start: number;
+ end?: number;
+ };
+};
+
+export type FilePart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ mime: string;
+ filename?: string;
+ url: string;
+ source?: FilePartSource;
+};
+
+export type FilePartSource = ({
+ type: 'file';
+} & FileSource) | ({
+ type: 'symbol';
+} & SymbolSource);
+
+export type FileSource = {
+ text: FilePartSourceText;
+ type: string;
+ path: string;
+};
+
+export type FilePartSourceText = {
+ value: string;
+ start: number;
+ end: number;
+};
+
+export type SymbolSource = {
+ text: FilePartSourceText;
+ type: string;
+ path: string;
+ range: Range;
+ name: string;
+ kind: number;
+};
+
+export type Range = {
+ start: {
+ line: number;
+ character: number;
+ };
+ end: {
+ line: number;
+ character: number;
+ };
+};
+
+export type ToolPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ callID: string;
+ tool: string;
+ state: ToolState;
+};
+
+export type ToolState = ({
+ status: 'pending';
+} & ToolStatePending) | ({
+ status: 'running';
+} & ToolStateRunning) | ({
+ status: 'completed';
+} & ToolStateCompleted) | ({
+ status: 'error';
+} & ToolStateError);
+
+export type ToolStatePending = {
+ status: string;
+};
+
+export type ToolStateRunning = {
+ status: string;
+ input?: unknown;
+ title?: string;
+ metadata?: {
+ [key: string]: unknown;
+ };
+ time: {
+ start: number;
+ };
+};
+
+export type ToolStateCompleted = {
+ status: string;
+ input: {
+ [key: string]: unknown;
+ };
+ output: string;
+ title: string;
+ metadata: {
+ [key: string]: unknown;
+ };
+ time: {
+ start: number;
+ end: number;
+ };
+};
+
+export type ToolStateError = {
+ status: string;
+ input: {
+ [key: string]: unknown;
+ };
+ error: string;
+ time: {
+ start: number;
+ end: number;
+ };
+};
+
+export type StepStartPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+};
+
+export type StepFinishPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ cost: number;
+ tokens: {
+ input: number;
+ output: number;
+ reasoning: number;
+ cache: {
+ read: number;
+ write: number;
+ };
+ };
+};
+
+export type SnapshotPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ snapshot: string;
+};
+
+export type PatchPart = {
+ id: string;
+ sessionID: string;
+ messageID: string;
+ type: string;
+ hash: string;
+ files: Array<string>;
+};
+
+export type EventMessagePartRemoved = {
+ type: string;
+ properties: {
+ sessionID: string;
+ messageID: string;
+ partID: string;
+ };
+};
+
+export type EventStorageWrite = {
+ type: string;
+ properties: {
+ key: string;
+ content?: unknown;
+ };
+};
+
+export type EventPermissionUpdated = {
+ type: string;
+ properties: PermissionInfo;
+};
+
+export type PermissionInfo = {
+ id: string;
+ sessionID: string;
+ title: string;
+ metadata: {
+ [key: string]: unknown;
+ };
+ time: {
+ created: number;
+ };
+};
+
+export type EventFileEdited = {
+ type: string;
+ properties: {
+ file: string;
+ };
+};
+
+export type EventSessionUpdated = {
+ type: string;
+ properties: {
+ info: Session;
+ };
+};
+
+export type Session = {
+ id: string;
+ parentID?: string;
+ share?: {
+ url: string;
+ };
+ title: string;
+ version: string;
+ time: {
+ created: number;
+ updated: number;
+ };
+ revert?: {
+ messageID: string;
+ partID?: string;
+ snapshot?: string;
+ diff?: string;
+ };
+};
+
+export type EventSessionDeleted = {
+ type: string;
+ properties: {
+ info: Session;
+ };
+};
+
+export type EventSessionIdle = {
+ type: string;
+ properties: {
+ sessionID: string;
+ };
+};
+
+export type EventSessionError = {
+ type: string;
+ properties: {
+ sessionID?: string;
+ error?: ({
+ name: 'ProviderAuthError';
+ } & ProviderAuthError) | ({
+ name: 'UnknownError';
+ } & UnknownError) | ({
+ name: 'MessageOutputLengthError';
+ } & MessageOutputLengthError) | ({
+ name: 'MessageAbortedError';
+ } & MessageAbortedError);
+ };
+};
+
+export type EventServerConnected = {
+ type: string;
+ properties: {
+ [key: string]: unknown;
+ };
+};
+
+export type EventFileWatcherUpdated = {
+ type: string;
+ properties: {
+ file: string;
+ event: string;
+ };
+};
+
+export type EventIdeInstalled = {
+ type: string;
+ properties: {
+ ide: string;
+ };
+};
+
+export type App = {
+ hostname: string;
+ git: boolean;
+ path: {
+ config: string;
+ data: string;
+ root: string;
+ cwd: string;
+ state: string;
+ };
+ time: {
+ initialized?: number;
+ };
+};
+
+export type Config = {
+ /**
+ * JSON schema reference for configuration validation
+ */
+ $schema?: string;
+ /**
+ * Theme name to use for the interface
+ */
+ theme?: string;
+ keybinds?: KeybindsConfig;
+ /**
+ * Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing
+ */
+ share?: 'manual' | 'auto' | 'disabled';
+ /**
+ * @deprecated Use 'share' field instead. Share newly created sessions automatically
+ */
+ autoshare?: boolean;
+ /**
+ * Automatically update to the latest version
+ */
+ autoupdate?: boolean;
+ /**
+ * Disable providers that are loaded automatically
+ */
+ disabled_providers?: Array<string>;
+ /**
+ * Model to use in the format of provider/model, eg anthropic/claude-2
+ */
+ model?: string;
+ /**
+ * Small model to use for tasks like summarization and title generation in the format of provider/model
+ */
+ small_model?: string;
+ /**
+ * Custom username to display in conversations instead of system username
+ */
+ username?: string;
+ /**
+ * Modes configuration, see https://opencode.ai/docs/modes
+ */
+ mode?: {
+ build?: ModeConfig;
+ plan?: ModeConfig;
+ [key: string]: ModeConfig | undefined;
+ };
+ /**
+ * Modes configuration, see https://opencode.ai/docs/modes
+ */
+ agent?: {
+ general?: AgentConfig;
+ [key: string]: AgentConfig | undefined;
+ };
+ /**
+ * Custom provider configurations and model overrides
+ */
+ provider?: {
+ [key: string]: {
+ api?: string;
+ name?: string;
+ env?: Array<string>;
+ id?: string;
+ npm?: string;
+ models: {
+ [key: string]: {
+ id?: string;
+ name?: string;
+ release_date?: string;
+ attachment?: boolean;
+ reasoning?: boolean;
+ temperature?: boolean;
+ tool_call?: boolean;
+ cost?: {
+ input: number;
+ output: number;
+ cache_read?: number;
+ cache_write?: number;
+ };
+ limit?: {
+ context: number;
+ output: number;
+ };
+ options?: {
+ [key: string]: unknown;
+ };
+ };
+ };
+ options?: {
+ apiKey?: string;
+ baseURL?: string;
+ [key: string]: unknown | string | undefined;
+ };
+ };
+ };
+ /**
+ * MCP (Model Context Protocol) server configurations
+ */
+ mcp?: {
+ [key: string]: ({
+ type: 'local';
+ } & McpLocalConfig) | ({
+ type: 'remote';
+ } & McpRemoteConfig);
+ };
+ /**
+ * Additional instruction files or patterns to include
+ */
+ instructions?: Array<string>;
+ layout?: LayoutConfig;
+ permission?: {
+ edit?: string;
+ bash?: string | {
+ [key: string]: string;
+ };
+ };
+ experimental?: {
+ hook?: {
+ file_edited?: {
+ [key: string]: Array<{
+ command: Array<string>;
+ environment?: {
+ [key: string]: string;
+ };
+ }>;
+ };
+ session_completed?: Array<{
+ command: Array<string>;
+ environment?: {
+ [key: string]: string;
+ };
+ }>;
+ };
+ };
+};
+
+export type KeybindsConfig = {
+ /**
+ * Leader key for keybind combinations
+ */
+ leader: string;
+ /**
+ * Show help dialog
+ */
+ app_help: string;
+ /**
+ * Next mode
+ */
+ switch_mode: string;
+ /**
+ * Previous Mode
+ */
+ switch_mode_reverse: string;
+ /**
+ * Open external editor
+ */
+ editor_open: string;
+ /**
+ * Export session to editor
+ */
+ session_export: string;
+ /**
+ * Create a new session
+ */
+ session_new: string;
+ /**
+ * List all sessions
+ */
+ session_list: string;
+ /**
+ * Share current session
+ */
+ session_share: string;
+ /**
+ * Unshare current session
+ */
+ session_unshare: string;
+ /**
+ * Interrupt current session
+ */
+ session_interrupt: string;
+ /**
+ * Compact the session
+ */
+ session_compact: string;
+ /**
+ * Toggle tool details
+ */
+ tool_details: string;
+ /**
+ * List available models
+ */
+ model_list: string;
+ /**
+ * List available themes
+ */
+ theme_list: string;
+ /**
+ * List files
+ */
+ file_list: string;
+ /**
+ * Close file
+ */
+ file_close: string;
+ /**
+ * Search file
+ */
+ file_search: string;
+ /**
+ * Split/unified diff
+ */
+ file_diff_toggle: string;
+ /**
+ * Create/update AGENTS.md
+ */
+ project_init: string;
+ /**
+ * Clear input field
+ */
+ input_clear: string;
+ /**
+ * Paste from clipboard
+ */
+ input_paste: string;
+ /**
+ * Submit input
+ */
+ input_submit: string;
+ /**
+ * Insert newline in input
+ */
+ input_newline: string;
+ /**
+ * Scroll messages up by one page
+ */
+ messages_page_up: string;
+ /**
+ * Scroll messages down by one page
+ */
+ messages_page_down: string;
+ /**
+ * Scroll messages up by half page
+ */
+ messages_half_page_up: string;
+ /**
+ * Scroll messages down by half page
+ */
+ messages_half_page_down: string;
+ /**
+ * Navigate to previous message
+ */
+ messages_previous: string;
+ /**
+ * Navigate to next message
+ */
+ messages_next: string;
+ /**
+ * Navigate to first message
+ */
+ messages_first: string;
+ /**
+ * Navigate to last message
+ */
+ messages_last: string;
+ /**
+ * Toggle layout
+ */
+ messages_layout_toggle: string;
+ /**
+ * Copy message
+ */
+ messages_copy: string;
+ /**
+ * @deprecated use messages_undo. Revert message
+ */
+ messages_revert: string;
+ /**
+ * Undo message
+ */
+ messages_undo: string;
+ /**
+ * Redo message
+ */
+ messages_redo: string;
+ /**
+ * Exit the application
+ */
+ app_exit: string;
+};
+
+export type ModeConfig = {
+ model?: string;
+ temperature?: number;
+ prompt?: string;
+ tools?: {
+ [key: string]: boolean;
+ };
+ disable?: boolean;
+};
+
+export type AgentConfig = ModeConfig & {
+ description: string;
+};
+
+export type Provider = {
+ api?: string;
+ name: string;
+ env: Array<string>;
+ id: string;
+ npm?: string;
+ models: {
+ [key: string]: Model;
+ };
+};
+
+export type Model = {
+ id: string;
+ name: string;
+ release_date: string;
+ attachment: boolean;
+ reasoning: boolean;
+ temperature: boolean;
+ tool_call: boolean;
+ cost: {
+ input: number;
+ output: number;
+ cache_read?: number;
+ cache_write?: number;
+ };
+ limit: {
+ context: number;
+ output: number;
+ };
+ options: {
+ [key: string]: unknown;
+ };
+};
+
+export type McpLocalConfig = {
+ /**
+ * Type of MCP server connection
+ */
+ type: string;
+ /**
+ * Command and arguments to run the MCP server
+ */
+ command: Array<string>;
+ /**
+ * Environment variables to set when running the MCP server
+ */
+ environment?: {
+ [key: string]: string;
+ };
+ /**
+ * Enable or disable the MCP server on startup
+ */
+ enabled?: boolean;
+};
+
+export type McpRemoteConfig = {
+ /**
+ * Type of MCP server connection
+ */
+ type: string;
+ /**
+ * URL of the remote MCP server
+ */
+ url: string;
+ /**
+ * Enable or disable the MCP server on startup
+ */
+ enabled?: boolean;
+ /**
+ * Headers to send with the request
+ */
+ headers?: {
+ [key: string]: string;
+ };
+};
+
+export type LayoutConfig = 'auto' | 'stretch';
+
+export type _Error = {
+ data: {
+ [key: string]: unknown;
+ };
+};
+
+export type TextPartInput = {
+ id?: string;
+ type: string;
+ text: string;
+ synthetic?: boolean;
+ time?: {
+ start: number;
+ end?: number;
+ };
+};
+
+export type FilePartInput = {
+ id?: string;
+ type: string;
+ mime: string;
+ filename?: string;
+ url: string;
+ source?: FilePartSource;
+};
+
+export type Symbol = {
+ name: string;
+ kind: number;
+ location: {
+ uri: string;
+ range: Range;
+ };
+};
+
+export type File = {
+ path: string;
+ added: number;
+ removed: number;
+ status: 'added' | 'deleted' | 'modified';
+};
+
+export type Mode = {
+ name: string;
+ temperature?: number;
+ model?: {
+ modelID: string;
+ providerID: string;
+ };
+ prompt?: string;
+ tools: {
+ [key: string]: boolean;
+ };
+};
+
+export type EventSubscribeData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/event';
+};
+
+export type EventSubscribeResponses = {
+ /**
+ * Event stream
+ */
+ 200: Event;
+};
+
+export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses];
+
+export type AppGetData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/app';
+};
+
+export type AppGetResponses = {
+ /**
+ * 200
+ */
+ 200: App;
+};
+
+export type AppGetResponse = AppGetResponses[keyof AppGetResponses];
+
+export type AppInitData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/app/init';
+};
+
+export type AppInitResponses = {
+ /**
+ * Initialize the app
+ */
+ 200: boolean;
+};
+
+export type AppInitResponse = AppInitResponses[keyof AppInitResponses];
+
+export type ConfigGetData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/config';
+};
+
+export type ConfigGetResponses = {
+ /**
+ * Get config info
+ */
+ 200: Config;
+};
+
+export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses];
+
+export type SessionListData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/session';
+};
+
+export type SessionListResponses = {
+ /**
+ * List of sessions
+ */
+ 200: Array<Session>;
+};
+
+export type SessionListResponse = SessionListResponses[keyof SessionListResponses];
+
+export type SessionCreateData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/session';
+};
+
+export type SessionCreateErrors = {
+ /**
+ * Bad request
+ */
+ 400: _Error;
+};
+
+export type SessionCreateError = SessionCreateErrors[keyof SessionCreateErrors];
+
+export type SessionCreateResponses = {
+ /**
+ * Successfully created session
+ */
+ 200: Session;
+};
+
+export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses];
+
+export type SessionDeleteData = {
+ body?: never;
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}';
+};
+
+export type SessionDeleteResponses = {
+ /**
+ * Successfully deleted session
+ */
+ 200: boolean;
+};
+
+export type SessionDeleteResponse = SessionDeleteResponses[keyof SessionDeleteResponses];
+
+export type SessionInitData = {
+ body?: {
+ messageID: string;
+ providerID: string;
+ modelID: string;
+ };
+ path: {
+ /**
+ * Session ID
+ */
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/init';
+};
+
+export type SessionInitResponses = {
+ /**
+ * 200
+ */
+ 200: boolean;
+};
+
+export type SessionInitResponse = SessionInitResponses[keyof SessionInitResponses];
+
+export type SessionAbortData = {
+ body?: never;
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/abort';
+};
+
+export type SessionAbortResponses = {
+ /**
+ * Aborted session
+ */
+ 200: boolean;
+};
+
+export type SessionAbortResponse = SessionAbortResponses[keyof SessionAbortResponses];
+
+export type SessionUnshareData = {
+ body?: never;
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/share';
+};
+
+export type SessionUnshareResponses = {
+ /**
+ * Successfully unshared session
+ */
+ 200: Session;
+};
+
+export type SessionUnshareResponse = SessionUnshareResponses[keyof SessionUnshareResponses];
+
+export type SessionShareData = {
+ body?: never;
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/share';
+};
+
+export type SessionShareResponses = {
+ /**
+ * Successfully shared session
+ */
+ 200: Session;
+};
+
+export type SessionShareResponse = SessionShareResponses[keyof SessionShareResponses];
+
+export type SessionSummarizeData = {
+ body?: {
+ providerID: string;
+ modelID: string;
+ };
+ path: {
+ /**
+ * Session ID
+ */
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/summarize';
+};
+
+export type SessionSummarizeResponses = {
+ /**
+ * Summarized session
+ */
+ 200: boolean;
+};
+
+export type SessionSummarizeResponse = SessionSummarizeResponses[keyof SessionSummarizeResponses];
+
+export type SessionMessagesData = {
+ body?: never;
+ path: {
+ /**
+ * Session ID
+ */
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/message';
+};
+
+export type SessionMessagesResponses = {
+ /**
+ * List of messages
+ */
+ 200: Array<{
+ info: Message;
+ parts: Array<Part>;
+ }>;
+};
+
+export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses];
+
+export type SessionChatData = {
+ body?: {
+ messageID?: string;
+ providerID: string;
+ modelID: string;
+ mode?: string;
+ system?: string;
+ tools?: {
+ [key: string]: boolean;
+ };
+ parts: Array<({
+ type: 'text';
+ } & TextPartInput) | ({
+ type: 'file';
+ } & FilePartInput)>;
+ };
+ path: {
+ /**
+ * Session ID
+ */
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/message';
+};
+
+export type SessionChatResponses = {
+ /**
+ * Created message
+ */
+ 200: AssistantMessage;
+};
+
+export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses];
+
+export type SessionRevertData = {
+ body?: {
+ messageID: string;
+ partID?: string;
+ };
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/revert';
+};
+
+export type SessionRevertResponses = {
+ /**
+ * Updated session
+ */
+ 200: Session;
+};
+
+export type SessionRevertResponse = SessionRevertResponses[keyof SessionRevertResponses];
+
+export type SessionUnrevertData = {
+ body?: never;
+ path: {
+ id: string;
+ };
+ query?: never;
+ url: '/session/{id}/unrevert';
+};
+
+export type SessionUnrevertResponses = {
+ /**
+ * Updated session
+ */
+ 200: Session;
+};
+
+export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses];
+
+export type ConfigProvidersData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/config/providers';
+};
+
+export type ConfigProvidersResponses = {
+ /**
+ * List of providers
+ */
+ 200: {
+ providers: Array<Provider>;
+ default: {
+ [key: string]: string;
+ };
+ };
+};
+
+export type ConfigProvidersResponse = ConfigProvidersResponses[keyof ConfigProvidersResponses];
+
+export type FindTextData = {
+ body?: never;
+ path?: never;
+ query: {
+ pattern: string;
+ };
+ url: '/find';
+};
+
+export type FindTextResponses = {
+ /**
+ * Matches
+ */
+ 200: Array<{
+ path: {
+ text: string;
+ };
+ lines: {
+ text: string;
+ };
+ line_number: number;
+ absolute_offset: number;
+ submatches: Array<{
+ match: {
+ text: string;
+ };
+ start: number;
+ end: number;
+ }>;
+ }>;
+};
+
+export type FindTextResponse = FindTextResponses[keyof FindTextResponses];
+
+export type FindFilesData = {
+ body?: never;
+ path?: never;
+ query: {
+ query: string;
+ };
+ url: '/find/file';
+};
+
+export type FindFilesResponses = {
+ /**
+ * File paths
+ */
+ 200: Array<string>;
+};
+
+export type FindFilesResponse = FindFilesResponses[keyof FindFilesResponses];
+
+export type FindSymbolsData = {
+ body?: never;
+ path?: never;
+ query: {
+ query: string;
+ };
+ url: '/find/symbol';
+};
+
+export type FindSymbolsResponses = {
+ /**
+ * Symbols
+ */
+ 200: Array<Symbol>;
+};
+
+export type FindSymbolsResponse = FindSymbolsResponses[keyof FindSymbolsResponses];
+
+export type FileReadData = {
+ body?: never;
+ path?: never;
+ query: {
+ path: string;
+ };
+ url: '/file';
+};
+
+export type FileReadResponses = {
+ /**
+ * File content
+ */
+ 200: {
+ type: 'raw' | 'patch';
+ content: string;
+ };
+};
+
+export type FileReadResponse = FileReadResponses[keyof FileReadResponses];
+
+export type FileStatusData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/file/status';
+};
+
+export type FileStatusResponses = {
+ /**
+ * File status
+ */
+ 200: Array<File>;
+};
+
+export type FileStatusResponse = FileStatusResponses[keyof FileStatusResponses];
+
+export type AppLogData = {
+ body?: {
+ /**
+ * Service name for the log entry
+ */
+ service: string;
+ /**
+ * Log level
+ */
+ level: 'debug' | 'info' | 'error' | 'warn';
+ /**
+ * Log message
+ */
+ message: string;
+ /**
+ * Additional metadata for the log entry
+ */
+ extra?: {
+ [key: string]: unknown;
+ };
+ };
+ path?: never;
+ query?: never;
+ url: '/log';
+};
+
+export type AppLogResponses = {
+ /**
+ * Log entry written successfully
+ */
+ 200: boolean;
+};
+
+export type AppLogResponse = AppLogResponses[keyof AppLogResponses];
+
+export type AppModesData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/mode';
+};
+
+export type AppModesResponses = {
+ /**
+ * List of modes
+ */
+ 200: Array<Mode>;
+};
+
+export type AppModesResponse = AppModesResponses[keyof AppModesResponses];
+
+export type TuiAppendPromptData = {
+ body?: {
+ text: string;
+ };
+ path?: never;
+ query?: never;
+ url: '/tui/append-prompt';
+};
+
+export type TuiAppendPromptResponses = {
+ /**
+ * Prompt processed successfully
+ */
+ 200: boolean;
+};
+
+export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPromptResponses];
+
+export type TuiOpenHelpData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/tui/open-help';
+};
+
+export type TuiOpenHelpResponses = {
+ /**
+ * Help dialog opened successfully
+ */
+ 200: boolean;
+};
+
+export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponses];
+
+export type ClientOptions = {
+ baseUrl: `${string}://${string}` | (string & {});
+}; \ No newline at end of file
diff --git a/packages/sdk/js/src/index.ts b/packages/sdk/js/src/index.ts
new file mode 100644
index 000000000..bdabf5f43
--- /dev/null
+++ b/packages/sdk/js/src/index.ts
@@ -0,0 +1,8 @@
+import { createClient } from "./gen/client/client"
+import { type Config } from "./gen/client/types"
+import { OpencodeClient } from "./gen/sdk.gen"
+
+export function createOpencodeClient(config?: Config) {
+ const client = createClient(config)
+ return new OpencodeClient({ client })
+}
diff --git a/packages/sdk/js/tsconfig.json b/packages/sdk/js/tsconfig.json
new file mode 100644
index 000000000..dbd7732e5
--- /dev/null
+++ b/packages/sdk/js/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig.json",
+ "extends": "@tsconfig/node22/tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "module": "preserve",
+ "declaration": true,
+ "moduleResolution": "bundler"
+ },
+ "include": [
+ "src"
+ ]
+}
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
deleted file mode 100644
index 12f57b1d3..000000000
--- a/packages/sdk/package.json
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "name": "@opencode-ai/sdk",
- "version": "0.1.0-alpha.20",
- "description": "The official TypeScript library for the Opencode API",
- "author": "Opencode <[email protected]>",
- "types": "dist/index.d.ts",
- "main": "dist/index.js",
- "type": "commonjs",
- "repository": "github:sst/opencode-sdk-js",
- "license": "MIT",
- "packageManager": "[email protected]",
- "files": [
- "**/*"
- ],
- "private": false,
- "scripts": {
- "test": "./scripts/test",
- "build": "./scripts/build",
- "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1",
- "format": "./scripts/format",
- "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi",
- "tsn": "ts-node -r tsconfig-paths/register",
- "lint": "./scripts/lint",
- "fix": "./scripts/format"
- },
- "dependencies": {},
- "devDependencies": {
- "@arethetypeswrong/cli": "^0.17.0",
- "@swc/core": "^1.3.102",
- "@swc/jest": "^0.2.29",
- "@types/jest": "^29.4.0",
- "@types/node": "^20.17.6",
- "@typescript-eslint/eslint-plugin": "8.31.1",
- "@typescript-eslint/parser": "8.31.1",
- "eslint": "^9.20.1",
- "eslint-plugin-prettier": "^5.4.1",
- "eslint-plugin-unused-imports": "^4.1.4",
- "iconv-lite": "^0.6.3",
- "jest": "^29.4.0",
- "prettier": "^3.0.0",
- "publint": "^0.2.12",
- "ts-jest": "^29.1.0",
- "ts-node": "^10.5.0",
- "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz",
- "tsconfig-paths": "^4.0.0",
- "typescript": "catalog:",
- "typescript-eslint": "8.31.1"
- },
- "imports": {
- "@opencode-ai/sdk": ".",
- "@opencode-ai/sdk/*": "./src/*"
- },
- "exports": {
- ".": {
- "import": "./dist/index.mjs",
- "require": "./dist/index.js"
- },
- "./*.mjs": {
- "default": "./dist/*.mjs"
- },
- "./*.js": {
- "default": "./dist/*.js"
- },
- "./*": {
- "import": "./dist/*.mjs",
- "require": "./dist/*.js"
- }
- }
-}
diff --git a/packages/sdk/scripts/build b/packages/sdk/scripts/build
deleted file mode 100755
index c65e0faec..000000000
--- a/packages/sdk/scripts/build
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env bash
-
-set -exuo pipefail
-
-cd "$(dirname "$0")/.."
-
-node scripts/utils/check-version.cjs
-
-# Build into dist and will publish the package from there,
-# so that src/resources/foo.ts becomes <package root>/resources/foo.js
-# This way importing from `"@opencode-ai/sdk/resources/foo"` works
-# even with `"moduleResolution": "node"`
-
-rm -rf dist; mkdir dist
-# Copy src to dist/src and build from dist/src into dist, so that
-# the source map for index.js.map will refer to ./src/index.ts etc
-cp -rp src README.md dist
-for file in LICENSE CHANGELOG.md; do
- if [ -e "${file}" ]; then cp "${file}" dist; fi
-done
-if [ -e "bin/cli" ]; then
- mkdir -p dist/bin
- cp -p "bin/cli" dist/bin/;
-fi
-if [ -e "bin/migration-config.json" ]; then
- mkdir -p dist/bin
- cp -p "bin/migration-config.json" dist/bin/;
-fi
-# this converts the export map paths for the dist directory
-# and does a few other minor things
-node scripts/utils/make-dist-package-json.cjs > dist/package.json
-
-# build to .js/.mjs/.d.ts files
-./node_modules/.bin/tsc-multi
-# we need to patch index.js so that `new module.exports()` works for cjs backwards
-# compat. No way to get that from index.ts because it would cause compile errors
-# when building .mjs
-node scripts/utils/fix-index-exports.cjs
-cp tsconfig.dist-src.json dist/src/tsconfig.json
-
-node scripts/utils/postprocess-files.cjs
-
-# make sure that nothing crashes when we require the output CJS or
-# import the output ESM
-(cd dist && node -e 'require("@opencode-ai/sdk")')
-(cd dist && node -e 'import("@opencode-ai/sdk")' --input-type=module)
-
-if [ -e ./scripts/build-deno ]
-then
- ./scripts/build-deno
-fi
diff --git a/packages/sdk/scripts/format b/packages/sdk/scripts/format
deleted file mode 100755
index 7a7564019..000000000
--- a/packages/sdk/scripts/format
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-cd "$(dirname "$0")/.."
-
-echo "==> Running eslint --fix"
-./node_modules/.bin/eslint --fix .
-
-echo "==> Running prettier --write"
-# format things eslint didn't
-./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs'
diff --git a/packages/sdk/scripts/lint b/packages/sdk/scripts/lint
deleted file mode 100755
index 3ffb78a64..000000000
--- a/packages/sdk/scripts/lint
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-cd "$(dirname "$0")/.."
-
-echo "==> Running eslint"
-./node_modules/.bin/eslint .
-
-echo "==> Building"
-./scripts/build
-
-echo "==> Checking types"
-./node_modules/typescript/bin/tsc
-
-echo "==> Running Are The Types Wrong?"
-./node_modules/.bin/attw --pack dist -f json >.attw.json || true
-node scripts/utils/attw-report.cjs
-
-echo "==> Running publint"
-./node_modules/.bin/publint dist
diff --git a/packages/sdk/scripts/utils/attw-report.cjs b/packages/sdk/scripts/utils/attw-report.cjs
deleted file mode 100644
index b3477c0ef..000000000
--- a/packages/sdk/scripts/utils/attw-report.cjs
+++ /dev/null
@@ -1,24 +0,0 @@
-const fs = require('fs');
-const problems = Object.values(JSON.parse(fs.readFileSync('.attw.json', 'utf-8')).problems)
- .flat()
- .filter(
- (problem) =>
- !(
- // This is intentional, if the user specifies .mjs they get ESM.
- (
- (problem.kind === 'CJSResolvesToESM' && problem.entrypoint.endsWith('.mjs')) ||
- // This is intentional for backwards compat reasons.
- (problem.kind === 'MissingExportEquals' && problem.implementationFileName.endsWith('/index.js')) ||
- // this is intentional, we deliberately attempt to import types that may not exist from parent node_modules
- // folders to better support various runtimes without triggering automatic type acquisition.
- (problem.kind === 'InternalResolutionError' && problem.moduleSpecifier.includes('node_modules'))
- )
- ),
- );
-fs.unlinkSync('.attw.json');
-if (problems.length) {
- process.stdout.write('The types are wrong!\n' + JSON.stringify(problems, null, 2) + '\n');
- process.exitCode = 1;
-} else {
- process.stdout.write('Types ok!\n');
-}
diff --git a/packages/sdk/scripts/utils/check-is-in-git-install.sh b/packages/sdk/scripts/utils/check-is-in-git-install.sh
deleted file mode 100755
index 1354eb432..000000000
--- a/packages/sdk/scripts/utils/check-is-in-git-install.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-# Check if you happen to call prepare for a repository that's already in node_modules.
-[ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] ||
-# The name of the containing directory that 'npm` uses, which looks like
-# $HOME/.npm/_cacache/git-cloneXXXXXX
-[ "$(basename "$(dirname "$PWD")")" = 'tmp' ] ||
-# The name of the containing directory that 'yarn` uses, which looks like
-# $(yarn cache dir)/.tmp/XXXXX
-[ "$(basename "$(dirname "$PWD")")" = '.tmp' ]
diff --git a/packages/sdk/scripts/utils/check-version.cjs b/packages/sdk/scripts/utils/check-version.cjs
deleted file mode 100644
index 86c56dfd3..000000000
--- a/packages/sdk/scripts/utils/check-version.cjs
+++ /dev/null
@@ -1,20 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-
-const main = () => {
- const pkg = require('../../package.json');
- const version = pkg['version'];
- if (!version) throw 'The version property is not set in the package.json file';
- if (typeof version !== 'string') {
- throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`;
- }
-
- const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts');
- const contents = fs.readFileSync(versionFile, 'utf8');
- const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`);
- fs.writeFileSync(versionFile, output);
-};
-
-if (require.main === module) {
- main();
-}
diff --git a/packages/sdk/scripts/utils/fix-index-exports.cjs b/packages/sdk/scripts/utils/fix-index-exports.cjs
deleted file mode 100644
index e5e10b3e7..000000000
--- a/packages/sdk/scripts/utils/fix-index-exports.cjs
+++ /dev/null
@@ -1,17 +0,0 @@
-const fs = require('fs');
-const path = require('path');
-
-const indexJs =
- process.env['DIST_PATH'] ?
- path.resolve(process.env['DIST_PATH'], 'index.js')
- : path.resolve(__dirname, '..', '..', 'dist', 'index.js');
-
-let before = fs.readFileSync(indexJs, 'utf8');
-let after = before.replace(
- /^(\s*Object\.defineProperty\s*\(exports,\s*["']__esModule["'].+)$/m,
- `exports = module.exports = function (...args) {
- return new exports.default(...args)
- }
- $1`.replace(/^ /gm, ''),
-);
-fs.writeFileSync(indexJs, after, 'utf8');
diff --git a/packages/sdk/scripts/utils/git-swap.sh b/packages/sdk/scripts/utils/git-swap.sh
deleted file mode 100755
index 79d1888eb..000000000
--- a/packages/sdk/scripts/utils/git-swap.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-set -exuo pipefail
-# the package is published to NPM from ./dist
-# we want the final file structure for git installs to match the npm installs, so we
-
-# delete everything except ./dist and ./node_modules
-find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' +
-
-# move everything from ./dist to .
-mv dist/* .
-
-# delete the now-empty ./dist
-rmdir dist
diff --git a/packages/sdk/scripts/utils/make-dist-package-json.cjs b/packages/sdk/scripts/utils/make-dist-package-json.cjs
deleted file mode 100644
index 7c24f56e2..000000000
--- a/packages/sdk/scripts/utils/make-dist-package-json.cjs
+++ /dev/null
@@ -1,21 +0,0 @@
-const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json');
-
-function processExportMap(m) {
- for (const key in m) {
- const value = m[key];
- if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './');
- else processExportMap(value);
- }
-}
-processExportMap(pkgJson.exports);
-
-for (const key of ['types', 'main', 'module']) {
- if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './');
-}
-
-delete pkgJson.devDependencies;
-delete pkgJson.scripts.prepack;
-delete pkgJson.scripts.prepublishOnly;
-delete pkgJson.scripts.prepare;
-
-console.log(JSON.stringify(pkgJson, null, 2));
diff --git a/packages/sdk/scripts/utils/postprocess-files.cjs b/packages/sdk/scripts/utils/postprocess-files.cjs
deleted file mode 100644
index deae575e3..000000000
--- a/packages/sdk/scripts/utils/postprocess-files.cjs
+++ /dev/null
@@ -1,94 +0,0 @@
-// @ts-check
-const fs = require('fs');
-const path = require('path');
-
-const distDir =
- process.env['DIST_PATH'] ?
- path.resolve(process.env['DIST_PATH'])
- : path.resolve(__dirname, '..', '..', 'dist');
-
-async function* walk(dir) {
- for await (const d of await fs.promises.opendir(dir)) {
- const entry = path.join(dir, d.name);
- if (d.isDirectory()) yield* walk(entry);
- else if (d.isFile()) yield entry;
- }
-}
-
-async function postprocess() {
- for await (const file of walk(distDir)) {
- if (!/(\.d)?[cm]?ts$/.test(file)) continue;
-
- const code = await fs.promises.readFile(file, 'utf8');
-
- // strip out lib="dom", types="node", and types="react" references; these
- // are needed at build time, but would pollute the user's TS environment
- const transformed = code.replace(
- /^ *\/\/\/ *<reference +(lib="dom"|types="(node|react)").*?\n/gm,
- // replace with same number of characters to avoid breaking source maps
- (match) => ' '.repeat(match.length - 1) + '\n',
- );
-
- if (transformed !== code) {
- console.error(`wrote ${path.relative(process.cwd(), file)}`);
- await fs.promises.writeFile(file, transformed, 'utf8');
- }
- }
-
- const newExports = {
- '.': {
- require: {
- types: './index.d.ts',
- default: './index.js',
- },
- types: './index.d.mts',
- default: './index.mjs',
- },
- };
-
- for (const entry of await fs.promises.readdir(distDir, { withFileTypes: true })) {
- if (entry.isDirectory() && entry.name !== 'src' && entry.name !== 'internal' && entry.name !== 'bin') {
- const subpath = './' + entry.name;
- newExports[subpath + '/*.mjs'] = {
- default: subpath + '/*.mjs',
- };
- newExports[subpath + '/*.js'] = {
- default: subpath + '/*.js',
- };
- newExports[subpath + '/*'] = {
- import: subpath + '/*.mjs',
- require: subpath + '/*.js',
- };
- } else if (entry.isFile() && /\.[cm]?js$/.test(entry.name)) {
- const { name, ext } = path.parse(entry.name);
- const subpathWithoutExt = './' + name;
- const subpath = './' + entry.name;
- newExports[subpathWithoutExt] ||= { import: undefined, require: undefined };
- const isModule = ext[1] === 'm';
- if (isModule) {
- newExports[subpathWithoutExt].import = subpath;
- } else {
- newExports[subpathWithoutExt].require = subpath;
- }
- newExports[subpath] = {
- default: subpath,
- };
- }
- }
- await fs.promises.writeFile(
- 'dist/package.json',
- JSON.stringify(
- Object.assign(
- /** @type {Record<String, unknown>} */ (
- JSON.parse(await fs.promises.readFile('dist/package.json', 'utf-8'))
- ),
- {
- exports: newExports,
- },
- ),
- null,
- 2,
- ),
- );
-}
-postprocess();
diff --git a/packages/sdk/scripts/utils/upload-artifact.sh b/packages/sdk/scripts/utils/upload-artifact.sh
deleted file mode 100755
index ac113aac2..000000000
--- a/packages/sdk/scripts/utils/upload-artifact.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-set -exuo pipefail
-
-RESPONSE=$(curl -X POST "$URL" \
- -H "Authorization: Bearer $AUTH" \
- -H "Content-Type: application/json")
-
-SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url')
-
-if [[ "$SIGNED_URL" == "null" ]]; then
- echo -e "\033[31mFailed to get signed URL.\033[0m"
- exit 1
-fi
-
-UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \
- -H "Content-Type: application/gzip" \
- --data-binary @- "$SIGNED_URL" 2>&1)
-
-if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then
- echo -e "\033[32mUploaded build to Stainless storage.\033[0m"
- echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/opencode-typescript/$SHA'\033[0m"
-else
- echo -e "\033[31mFailed to upload artifact.\033[0m"
- exit 1
-fi
diff --git a/packages/sdk/src/api-promise.ts b/packages/sdk/src/api-promise.ts
deleted file mode 100644
index 8c775ee69..000000000
--- a/packages/sdk/src/api-promise.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/** @deprecated Import from ./core/api-promise instead */
-export * from './core/api-promise';
diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts
deleted file mode 100644
index 9241bd582..000000000
--- a/packages/sdk/src/client.ts
+++ /dev/null
@@ -1,862 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import type { RequestInit, RequestInfo, BodyInit } from './internal/builtin-types';
-import type { HTTPMethod, PromiseOrValue, MergedRequestInit, FinalizedRequestInit } from './internal/types';
-import { uuid4 } from './internal/utils/uuid';
-import { validatePositiveInteger, isAbsoluteURL, safeJSON } from './internal/utils/values';
-import { sleep } from './internal/utils/sleep';
-export type { Logger, LogLevel } from './internal/utils/log';
-import { castToError, isAbortError } from './internal/errors';
-import type { APIResponseProps } from './internal/parse';
-import { getPlatformHeaders } from './internal/detect-platform';
-import * as Shims from './internal/shims';
-import * as Opts from './internal/request-options';
-import { VERSION } from './version';
-import * as Errors from './core/error';
-import * as Uploads from './core/uploads';
-import * as API from './resources/index';
-import { APIPromise } from './core/api-promise';
-import {
- App,
- AppInitResponse,
- AppLogParams,
- AppLogResponse,
- AppModesResponse,
- AppProvidersResponse,
- AppResource,
- Mode,
- Model,
- Provider,
-} from './resources/app';
-import {
- Config,
- ConfigResource,
- KeybindsConfig,
- McpLocalConfig,
- McpRemoteConfig,
- ModeConfig,
-} from './resources/config';
-import { Event, EventListResponse } from './resources/event';
-import { File, FileReadParams, FileReadResponse, FileResource, FileStatusResponse } from './resources/file';
-import {
- Find,
- FindFilesParams,
- FindFilesResponse,
- FindSymbolsParams,
- FindSymbolsResponse,
- FindTextParams,
- FindTextResponse,
- Symbol,
-} from './resources/find';
-import {
- AssistantMessage,
- FilePart,
- FilePartInput,
- FilePartSource,
- FilePartSourceText,
- FileSource,
- Message,
- Part,
- Session,
- SessionAbortResponse,
- SessionChatParams,
- SessionDeleteResponse,
- SessionInitParams,
- SessionInitResponse,
- SessionListResponse,
- SessionMessagesResponse,
- SessionResource,
- SessionRevertParams,
- SessionSummarizeParams,
- SessionSummarizeResponse,
- SnapshotPart,
- StepFinishPart,
- StepStartPart,
- SymbolSource,
- TextPart,
- TextPartInput,
- ToolPart,
- ToolStateCompleted,
- ToolStateError,
- ToolStatePending,
- ToolStateRunning,
- UserMessage,
-} from './resources/session';
-import { Tui, TuiAppendPromptParams, TuiAppendPromptResponse, TuiOpenHelpResponse } from './resources/tui';
-import { type Fetch } from './internal/builtin-types';
-import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers';
-import { FinalRequestOptions, RequestOptions } from './internal/request-options';
-import { readEnv } from './internal/utils/env';
-import {
- type LogLevel,
- type Logger,
- formatRequestDetails,
- loggerFor,
- parseLogLevel,
-} from './internal/utils/log';
-import { isEmptyObj } from './internal/utils/values';
-
-export interface ClientOptions {
- /**
- * Override the default base URL for the API, e.g., "https://api.example.com/v2/"
- *
- * Defaults to process.env['OPENCODE_BASE_URL'].
- */
- baseURL?: string | null | undefined;
-
- /**
- * The maximum amount of time (in milliseconds) that the client should wait for a response
- * from the server before timing out a single request.
- *
- * Note that request timeouts are retried by default, so in a worst-case scenario you may wait
- * much longer than this timeout before the promise succeeds or fails.
- *
- * @unit milliseconds
- */
- timeout?: number | undefined;
- /**
- * Additional `RequestInit` options to be passed to `fetch` calls.
- * Properties will be overridden by per-request `fetchOptions`.
- */
- fetchOptions?: MergedRequestInit | undefined;
-
- /**
- * Specify a custom `fetch` function implementation.
- *
- * If not provided, we expect that `fetch` is defined globally.
- */
- fetch?: Fetch | undefined;
-
- /**
- * The maximum number of times that the client will retry a request in case of a
- * temporary failure, like a network error or a 5XX error from the server.
- *
- * @default 2
- */
- maxRetries?: number | undefined;
-
- /**
- * Default headers to include with every request to the API.
- *
- * These can be removed in individual requests by explicitly setting the
- * header to `null` in request options.
- */
- defaultHeaders?: HeadersLike | undefined;
-
- /**
- * Default query parameters to include with every request to the API.
- *
- * These can be removed in individual requests by explicitly setting the
- * param to `undefined` in request options.
- */
- defaultQuery?: Record<string, string | undefined> | undefined;
-
- /**
- * Set the log level.
- *
- * Defaults to process.env['OPENCODE_LOG'] or 'warn' if it isn't set.
- */
- logLevel?: LogLevel | undefined;
-
- /**
- * Set the logger.
- *
- * Defaults to globalThis.console.
- */
- logger?: Logger | undefined;
-}
-
-/**
- * API Client for interfacing with the Opencode API.
- */
-export class Opencode {
- baseURL: string;
- maxRetries: number;
- timeout: number;
- logger: Logger | undefined;
- logLevel: LogLevel | undefined;
- fetchOptions: MergedRequestInit | undefined;
-
- private fetch: Fetch;
- #encoder: Opts.RequestEncoder;
- protected idempotencyHeader?: string;
- private _options: ClientOptions;
-
- /**
- * API Client for interfacing with the Opencode API.
- *
- * @param {string} [opts.baseURL=process.env['OPENCODE_BASE_URL'] ?? http://localhost:54321] - Override the default base URL for the API.
- * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
- * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
- * @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
- * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
- * @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
- * @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
- */
- constructor({ baseURL = readEnv('OPENCODE_BASE_URL'), ...opts }: ClientOptions = {}) {
- const options: ClientOptions = {
- ...opts,
- baseURL: baseURL || `http://localhost:54321`,
- };
-
- this.baseURL = options.baseURL!;
- this.timeout = options.timeout ?? Opencode.DEFAULT_TIMEOUT /* 1 minute */;
- this.logger = options.logger ?? console;
- const defaultLogLevel = 'warn';
- // Set default logLevel early so that we can log a warning in parseLogLevel.
- this.logLevel = defaultLogLevel;
- this.logLevel =
- parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
- parseLogLevel(readEnv('OPENCODE_LOG'), "process.env['OPENCODE_LOG']", this) ??
- defaultLogLevel;
- this.fetchOptions = options.fetchOptions;
- this.maxRetries = options.maxRetries ?? 2;
- this.fetch = options.fetch ?? Shims.getDefaultFetch();
- this.#encoder = Opts.FallbackEncoder;
-
- this._options = options;
- }
-
- /**
- * Create a new client instance re-using the same options given to the current client with optional overriding.
- */
- withOptions(options: Partial<ClientOptions>): this {
- const client = new (this.constructor as any as new (props: ClientOptions) => typeof this)({
- ...this._options,
- baseURL: this.baseURL,
- maxRetries: this.maxRetries,
- timeout: this.timeout,
- logger: this.logger,
- logLevel: this.logLevel,
- fetch: this.fetch,
- fetchOptions: this.fetchOptions,
- ...options,
- });
- return client;
- }
-
- /**
- * Check whether the base URL is set to its default.
- */
- #baseURLOverridden(): boolean {
- return this.baseURL !== 'http://localhost:54321';
- }
-
- protected defaultQuery(): Record<string, string | undefined> | undefined {
- return this._options.defaultQuery;
- }
-
- protected validateHeaders({ values, nulls }: NullableHeaders) {
- return;
- }
-
- /**
- * Basic re-implementation of `qs.stringify` for primitive types.
- */
- protected stringifyQuery(query: Record<string, unknown>): string {
- return Object.entries(query)
- .filter(([_, value]) => typeof value !== 'undefined')
- .map(([key, value]) => {
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
- return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
- }
- if (value === null) {
- return `${encodeURIComponent(key)}=`;
- }
- throw new Errors.OpencodeError(
- `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
- );
- })
- .join('&');
- }
-
- private getUserAgent(): string {
- return `${this.constructor.name}/JS ${VERSION}`;
- }
-
- protected defaultIdempotencyKey(): string {
- return `stainless-node-retry-${uuid4()}`;
- }
-
- protected makeStatusError(
- status: number,
- error: Object,
- message: string | undefined,
- headers: Headers,
- ): Errors.APIError {
- return Errors.APIError.generate(status, error, message, headers);
- }
-
- buildURL(
- path: string,
- query: Record<string, unknown> | null | undefined,
- defaultBaseURL?: string | undefined,
- ): string {
- const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL;
- const url =
- isAbsoluteURL(path) ?
- new URL(path)
- : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
-
- const defaultQuery = this.defaultQuery();
- if (!isEmptyObj(defaultQuery)) {
- query = { ...defaultQuery, ...query };
- }
-
- if (typeof query === 'object' && query && !Array.isArray(query)) {
- url.search = this.stringifyQuery(query as Record<string, unknown>);
- }
-
- return url.toString();
- }
-
- /**
- * Used as a callback for mutating the given `FinalRequestOptions` object.
- */
- protected async prepareOptions(options: FinalRequestOptions): Promise<void> {}
-
- /**
- * Used as a callback for mutating the given `RequestInit` object.
- *
- * This is useful for cases where you want to add certain headers based off of
- * the request properties, e.g. `method` or `url`.
- */
- protected async prepareRequest(
- request: RequestInit,
- { url, options }: { url: string; options: FinalRequestOptions },
- ): Promise<void> {}
-
- get<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {
- return this.methodRequest('get', path, opts);
- }
-
- post<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {
- return this.methodRequest('post', path, opts);
- }
-
- patch<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {
- return this.methodRequest('patch', path, opts);
- }
-
- put<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {
- return this.methodRequest('put', path, opts);
- }
-
- delete<Rsp>(path: string, opts?: PromiseOrValue<RequestOptions>): APIPromise<Rsp> {
- return this.methodRequest('delete', path, opts);
- }
-
- private methodRequest<Rsp>(
- method: HTTPMethod,
- path: string,
- opts?: PromiseOrValue<RequestOptions>,
- ): APIPromise<Rsp> {
- return this.request(
- Promise.resolve(opts).then((opts) => {
- return { method, path, ...opts };
- }),
- );
- }
-
- request<Rsp>(
- options: PromiseOrValue<FinalRequestOptions>,
- remainingRetries: number | null = null,
- ): APIPromise<Rsp> {
- return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
- }
-
- private async makeRequest(
- optionsInput: PromiseOrValue<FinalRequestOptions>,
- retriesRemaining: number | null,
- retryOfRequestLogID: string | undefined,
- ): Promise<APIResponseProps> {
- const options = await optionsInput;
- const maxRetries = options.maxRetries ?? this.maxRetries;
- if (retriesRemaining == null) {
- retriesRemaining = maxRetries;
- }
-
- await this.prepareOptions(options);
-
- const { req, url, timeout } = await this.buildRequest(options, {
- retryCount: maxRetries - retriesRemaining,
- });
-
- await this.prepareRequest(req, { url, options });
-
- /** Not an API request ID, just for correlating local log entries. */
- const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
- const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
- const startTime = Date.now();
-
- loggerFor(this).debug(
- `[${requestLogID}] sending request`,
- formatRequestDetails({
- retryOfRequestLogID,
- method: options.method,
- url,
- options,
- headers: req.headers,
- }),
- );
-
- if (options.signal?.aborted) {
- throw new Errors.APIUserAbortError();
- }
-
- const controller = new AbortController();
- const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
- const headersTime = Date.now();
-
- if (response instanceof Error) {
- const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
- if (options.signal?.aborted) {
- throw new Errors.APIUserAbortError();
- }
- // detect native connection timeout errors
- // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
- // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
- // others do not provide enough information to distinguish timeouts from other connection errors
- const isTimeout =
- isAbortError(response) ||
- /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
- if (retriesRemaining) {
- loggerFor(this).info(
- `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`,
- );
- loggerFor(this).debug(
- `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`,
- formatRequestDetails({
- retryOfRequestLogID,
- url,
- durationMs: headersTime - startTime,
- message: response.message,
- }),
- );
- return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
- }
- loggerFor(this).info(
- `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`,
- );
- loggerFor(this).debug(
- `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`,
- formatRequestDetails({
- retryOfRequestLogID,
- url,
- durationMs: headersTime - startTime,
- message: response.message,
- }),
- );
- if (isTimeout) {
- throw new Errors.APIConnectionTimeoutError();
- }
- throw new Errors.APIConnectionError({ cause: response });
- }
-
- const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${
- response.ok ? 'succeeded' : 'failed'
- } with status ${response.status} in ${headersTime - startTime}ms`;
-
- if (!response.ok) {
- const shouldRetry = await this.shouldRetry(response);
- if (retriesRemaining && shouldRetry) {
- const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
-
- // We don't need the body of this response.
- await Shims.CancelReadableStream(response.body);
- loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
- loggerFor(this).debug(
- `[${requestLogID}] response error (${retryMessage})`,
- formatRequestDetails({
- retryOfRequestLogID,
- url: response.url,
- status: response.status,
- headers: response.headers,
- durationMs: headersTime - startTime,
- }),
- );
- return this.retryRequest(
- options,
- retriesRemaining,
- retryOfRequestLogID ?? requestLogID,
- response.headers,
- );
- }
-
- const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
-
- loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
-
- const errText = await response.text().catch((err: any) => castToError(err).message);
- const errJSON = safeJSON(errText);
- const errMessage = errJSON ? undefined : errText;
-
- loggerFor(this).debug(
- `[${requestLogID}] response error (${retryMessage})`,
- formatRequestDetails({
- retryOfRequestLogID,
- url: response.url,
- status: response.status,
- headers: response.headers,
- message: errMessage,
- durationMs: Date.now() - startTime,
- }),
- );
-
- const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
- throw err;
- }
-
- loggerFor(this).info(responseInfo);
- loggerFor(this).debug(
- `[${requestLogID}] response start`,
- formatRequestDetails({
- retryOfRequestLogID,
- url: response.url,
- status: response.status,
- headers: response.headers,
- durationMs: headersTime - startTime,
- }),
- );
-
- return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
- }
-
- async fetchWithTimeout(
- url: RequestInfo,
- init: RequestInit | undefined,
- ms: number,
- controller: AbortController,
- ): Promise<Response> {
- const { signal, method, ...options } = init || {};
- if (signal) signal.addEventListener('abort', () => controller.abort());
-
- const timeout = setTimeout(() => controller.abort(), ms);
-
- const isReadableBody =
- ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
- (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
-
- const fetchOptions: RequestInit = {
- signal: controller.signal as any,
- ...(isReadableBody ? { duplex: 'half' } : {}),
- method: 'GET',
- ...options,
- };
- if (method) {
- // Custom methods like 'patch' need to be uppercased
- // See https://github.com/nodejs/undici/issues/2294
- fetchOptions.method = method.toUpperCase();
- }
-
- try {
- // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
- return await this.fetch.call(undefined, url, fetchOptions);
- } finally {
- clearTimeout(timeout);
- }
- }
-
- private async shouldRetry(response: Response): Promise<boolean> {
- // Note this is not a standard header.
- const shouldRetryHeader = response.headers.get('x-should-retry');
-
- // If the server explicitly says whether or not to retry, obey.
- if (shouldRetryHeader === 'true') return true;
- if (shouldRetryHeader === 'false') return false;
-
- // Retry on request timeouts.
- if (response.status === 408) return true;
-
- // Retry on lock timeouts.
- if (response.status === 409) return true;
-
- // Retry on rate limits.
- if (response.status === 429) return true;
-
- // Retry internal errors.
- if (response.status >= 500) return true;
-
- return false;
- }
-
- private async retryRequest(
- options: FinalRequestOptions,
- retriesRemaining: number,
- requestLogID: string,
- responseHeaders?: Headers | undefined,
- ): Promise<APIResponseProps> {
- let timeoutMillis: number | undefined;
-
- // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.
- const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');
- if (retryAfterMillisHeader) {
- const timeoutMs = parseFloat(retryAfterMillisHeader);
- if (!Number.isNaN(timeoutMs)) {
- timeoutMillis = timeoutMs;
- }
- }
-
- // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
- const retryAfterHeader = responseHeaders?.get('retry-after');
- if (retryAfterHeader && !timeoutMillis) {
- const timeoutSeconds = parseFloat(retryAfterHeader);
- if (!Number.isNaN(timeoutSeconds)) {
- timeoutMillis = timeoutSeconds * 1000;
- } else {
- timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
- }
- }
-
- // If the API asks us to wait a certain amount of time (and it's a reasonable amount),
- // just do what it says, but otherwise calculate a default
- if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
- const maxRetries = options.maxRetries ?? this.maxRetries;
- timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
- }
- await sleep(timeoutMillis);
-
- return this.makeRequest(options, retriesRemaining - 1, requestLogID);
- }
-
- private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number {
- const initialRetryDelay = 0.5;
- const maxRetryDelay = 8.0;
-
- const numRetries = maxRetries - retriesRemaining;
-
- // Apply exponential backoff, but not more than the max.
- const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
-
- // Apply some jitter, take up to at most 25 percent of the retry time.
- const jitter = 1 - Math.random() * 0.25;
-
- return sleepSeconds * jitter * 1000;
- }
-
- async buildRequest(
- inputOptions: FinalRequestOptions,
- { retryCount = 0 }: { retryCount?: number } = {},
- ): Promise<{ req: FinalizedRequestInit; url: string; timeout: number }> {
- const options = { ...inputOptions };
- const { method, path, query, defaultBaseURL } = options;
-
- const url = this.buildURL(path!, query as Record<string, unknown>, defaultBaseURL);
- if ('timeout' in options) validatePositiveInteger('timeout', options.timeout);
- options.timeout = options.timeout ?? this.timeout;
- const { bodyHeaders, body } = this.buildBody({ options });
- const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
-
- const req: FinalizedRequestInit = {
- method,
- headers: reqHeaders,
- ...(options.signal && { signal: options.signal }),
- ...((globalThis as any).ReadableStream &&
- body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }),
- ...(body && { body }),
- ...((this.fetchOptions as any) ?? {}),
- ...((options.fetchOptions as any) ?? {}),
- };
-
- return { req, url, timeout: options.timeout };
- }
-
- private async buildHeaders({
- options,
- method,
- bodyHeaders,
- retryCount,
- }: {
- options: FinalRequestOptions;
- method: HTTPMethod;
- bodyHeaders: HeadersLike;
- retryCount: number;
- }): Promise<Headers> {
- let idempotencyHeaders: HeadersLike = {};
- if (this.idempotencyHeader && method !== 'get') {
- if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey();
- idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
- }
-
- const headers = buildHeaders([
- idempotencyHeaders,
- {
- Accept: 'application/json',
- 'User-Agent': this.getUserAgent(),
- 'X-Stainless-Retry-Count': String(retryCount),
- ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
- ...getPlatformHeaders(),
- },
- this._options.defaultHeaders,
- bodyHeaders,
- options.headers,
- ]);
-
- this.validateHeaders(headers);
-
- return headers.values;
- }
-
- private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
- bodyHeaders: HeadersLike;
- body: BodyInit | undefined;
- } {
- if (!body) {
- return { bodyHeaders: undefined, body: undefined };
- }
- const headers = buildHeaders([rawHeaders]);
- if (
- // Pass raw type verbatim
- ArrayBuffer.isView(body) ||
- body instanceof ArrayBuffer ||
- body instanceof DataView ||
- (typeof body === 'string' &&
- // Preserve legacy string encoding behavior for now
- headers.values.has('content-type')) ||
- // `Blob` is superset of `File`
- body instanceof Blob ||
- // `FormData` -> `multipart/form-data`
- body instanceof FormData ||
- // `URLSearchParams` -> `application/x-www-form-urlencoded`
- body instanceof URLSearchParams ||
- // Send chunked stream (each chunk has own `length`)
- ((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream)
- ) {
- return { bodyHeaders: undefined, body: body as BodyInit };
- } else if (
- typeof body === 'object' &&
- (Symbol.asyncIterator in body ||
- (Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))
- ) {
- return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body as AsyncIterable<Uint8Array>) };
- } else {
- return this.#encoder({ body, headers });
- }
- }
-
- static Opencode = this;
- static DEFAULT_TIMEOUT = 60000; // 1 minute
-
- static OpencodeError = Errors.OpencodeError;
- static APIError = Errors.APIError;
- static APIConnectionError = Errors.APIConnectionError;
- static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;
- static APIUserAbortError = Errors.APIUserAbortError;
- static NotFoundError = Errors.NotFoundError;
- static ConflictError = Errors.ConflictError;
- static RateLimitError = Errors.RateLimitError;
- static BadRequestError = Errors.BadRequestError;
- static AuthenticationError = Errors.AuthenticationError;
- static InternalServerError = Errors.InternalServerError;
- static PermissionDeniedError = Errors.PermissionDeniedError;
- static UnprocessableEntityError = Errors.UnprocessableEntityError;
-
- static toFile = Uploads.toFile;
-
- event: API.Event = new API.Event(this);
- app: API.AppResource = new API.AppResource(this);
- find: API.Find = new API.Find(this);
- file: API.FileResource = new API.FileResource(this);
- config: API.ConfigResource = new API.ConfigResource(this);
- session: API.SessionResource = new API.SessionResource(this);
- tui: API.Tui = new API.Tui(this);
-}
-Opencode.Event = Event;
-Opencode.AppResource = AppResource;
-Opencode.Find = Find;
-Opencode.FileResource = FileResource;
-Opencode.ConfigResource = ConfigResource;
-Opencode.SessionResource = SessionResource;
-Opencode.Tui = Tui;
-export declare namespace Opencode {
- export type RequestOptions = Opts.RequestOptions;
-
- export { Event as Event, type EventListResponse as EventListResponse };
-
- export {
- AppResource as AppResource,
- type App as App,
- type Mode as Mode,
- type Model as Model,
- type Provider as Provider,
- type AppInitResponse as AppInitResponse,
- type AppLogResponse as AppLogResponse,
- type AppModesResponse as AppModesResponse,
- type AppProvidersResponse as AppProvidersResponse,
- type AppLogParams as AppLogParams,
- };
-
- export {
- Find as Find,
- type Symbol as Symbol,
- type FindFilesResponse as FindFilesResponse,
- type FindSymbolsResponse as FindSymbolsResponse,
- type FindTextResponse as FindTextResponse,
- type FindFilesParams as FindFilesParams,
- type FindSymbolsParams as FindSymbolsParams,
- type FindTextParams as FindTextParams,
- };
-
- export {
- FileResource as FileResource,
- type File as File,
- type FileReadResponse as FileReadResponse,
- type FileStatusResponse as FileStatusResponse,
- type FileReadParams as FileReadParams,
- };
-
- export {
- ConfigResource as ConfigResource,
- type Config as Config,
- type KeybindsConfig as KeybindsConfig,
- type McpLocalConfig as McpLocalConfig,
- type McpRemoteConfig as McpRemoteConfig,
- type ModeConfig as ModeConfig,
- };
-
- export {
- SessionResource as SessionResource,
- type AssistantMessage as AssistantMessage,
- type FilePart as FilePart,
- type FilePartInput as FilePartInput,
- type FilePartSource as FilePartSource,
- type FilePartSourceText as FilePartSourceText,
- type FileSource as FileSource,
- type Message as Message,
- type Part as Part,
- type Session as Session,
- type SnapshotPart as SnapshotPart,
- type StepFinishPart as StepFinishPart,
- type StepStartPart as StepStartPart,
- type SymbolSource as SymbolSource,
- type TextPart as TextPart,
- type TextPartInput as TextPartInput,
- type ToolPart as ToolPart,
- type ToolStateCompleted as ToolStateCompleted,
- type ToolStateError as ToolStateError,
- type ToolStatePending as ToolStatePending,
- type ToolStateRunning as ToolStateRunning,
- type UserMessage as UserMessage,
- type SessionListResponse as SessionListResponse,
- type SessionDeleteResponse as SessionDeleteResponse,
- type SessionAbortResponse as SessionAbortResponse,
- type SessionInitResponse as SessionInitResponse,
- type SessionMessagesResponse as SessionMessagesResponse,
- type SessionSummarizeResponse as SessionSummarizeResponse,
- type SessionChatParams as SessionChatParams,
- type SessionInitParams as SessionInitParams,
- type SessionRevertParams as SessionRevertParams,
- type SessionSummarizeParams as SessionSummarizeParams,
- };
-
- export {
- Tui as Tui,
- type TuiAppendPromptResponse as TuiAppendPromptResponse,
- type TuiOpenHelpResponse as TuiOpenHelpResponse,
- type TuiAppendPromptParams as TuiAppendPromptParams,
- };
-
- export type MessageAbortedError = API.MessageAbortedError;
- export type ProviderAuthError = API.ProviderAuthError;
- export type UnknownError = API.UnknownError;
-}
diff --git a/packages/sdk/src/core/README.md b/packages/sdk/src/core/README.md
deleted file mode 100644
index 485fce861..000000000
--- a/packages/sdk/src/core/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# `core`
-
-This directory holds public modules implementing non-resource-specific SDK functionality.
diff --git a/packages/sdk/src/core/api-promise.ts b/packages/sdk/src/core/api-promise.ts
deleted file mode 100644
index fc1c6dd76..000000000
--- a/packages/sdk/src/core/api-promise.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { type Opencode } from '../client';
-
-import { type PromiseOrValue } from '../internal/types';
-import { APIResponseProps, defaultParseResponse } from '../internal/parse';
-
-/**
- * A subclass of `Promise` providing additional helper methods
- * for interacting with the SDK.
- */
-export class APIPromise<T> extends Promise<T> {
- private parsedPromise: Promise<T> | undefined;
- #client: Opencode;
-
- constructor(
- client: Opencode,
- private responsePromise: Promise<APIResponseProps>,
- private parseResponse: (
- client: Opencode,
- props: APIResponseProps,
- ) => PromiseOrValue<T> = defaultParseResponse,
- ) {
- super((resolve) => {
- // this is maybe a bit weird but this has to be a no-op to not implicitly
- // parse the response body; instead .then, .catch, .finally are overridden
- // to parse the response
- resolve(null as any);
- });
- this.#client = client;
- }
-
- _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {
- return new APIPromise(this.#client, this.responsePromise, async (client, props) =>
- transform(await this.parseResponse(client, props), props),
- );
- }
-
- /**
- * Gets the raw `Response` instance instead of parsing the response
- * data.
- *
- * If you want to parse the response body but still get the `Response`
- * instance, you can use {@link withResponse()}.
- *
- * 👋 Getting the wrong TypeScript type for `Response`?
- * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
- * to your `tsconfig.json`.
- */
- asResponse(): Promise<Response> {
- return this.responsePromise.then((p) => p.response);
- }
-
- /**
- * Gets the parsed response data and the raw `Response` instance.
- *
- * If you just want to get the raw `Response` instance without parsing it,
- * you can use {@link asResponse()}.
- *
- * 👋 Getting the wrong TypeScript type for `Response`?
- * Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
- * to your `tsconfig.json`.
- */
- async withResponse(): Promise<{ data: T; response: Response }> {
- const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
- return { data, response };
- }
-
- private parse(): Promise<T> {
- if (!this.parsedPromise) {
- this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(this.#client, data));
- }
- return this.parsedPromise;
- }
-
- override then<TResult1 = T, TResult2 = never>(
- onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
- onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,
- ): Promise<TResult1 | TResult2> {
- return this.parse().then(onfulfilled, onrejected);
- }
-
- override catch<TResult = never>(
- onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,
- ): Promise<T | TResult> {
- return this.parse().catch(onrejected);
- }
-
- override finally(onfinally?: (() => void) | undefined | null): Promise<T> {
- return this.parse().finally(onfinally);
- }
-}
diff --git a/packages/sdk/src/core/error.ts b/packages/sdk/src/core/error.ts
deleted file mode 100644
index 44698c739..000000000
--- a/packages/sdk/src/core/error.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { castToError } from '../internal/errors';
-
-export class OpencodeError extends Error {}
-
-export class APIError<
- TStatus extends number | undefined = number | undefined,
- THeaders extends Headers | undefined = Headers | undefined,
- TError extends Object | undefined = Object | undefined,
-> extends OpencodeError {
- /** HTTP status for the response that caused the error */
- readonly status: TStatus;
- /** HTTP headers for the response that caused the error */
- readonly headers: THeaders;
- /** JSON body of the response that caused the error */
- readonly error: TError;
-
- constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {
- super(`${APIError.makeMessage(status, error, message)}`);
- this.status = status;
- this.headers = headers;
- this.error = error;
- }
-
- private static makeMessage(status: number | undefined, error: any, message: string | undefined) {
- const msg =
- error?.message ?
- typeof error.message === 'string' ?
- error.message
- : JSON.stringify(error.message)
- : error ? JSON.stringify(error)
- : message;
-
- if (status && msg) {
- return `${status} ${msg}`;
- }
- if (status) {
- return `${status} status code (no body)`;
- }
- if (msg) {
- return msg;
- }
- return '(no status code or body)';
- }
-
- static generate(
- status: number | undefined,
- errorResponse: Object | undefined,
- message: string | undefined,
- headers: Headers | undefined,
- ): APIError {
- if (!status || !headers) {
- return new APIConnectionError({ message, cause: castToError(errorResponse) });
- }
-
- const error = errorResponse as Record<string, any>;
-
- if (status === 400) {
- return new BadRequestError(status, error, message, headers);
- }
-
- if (status === 401) {
- return new AuthenticationError(status, error, message, headers);
- }
-
- if (status === 403) {
- return new PermissionDeniedError(status, error, message, headers);
- }
-
- if (status === 404) {
- return new NotFoundError(status, error, message, headers);
- }
-
- if (status === 409) {
- return new ConflictError(status, error, message, headers);
- }
-
- if (status === 422) {
- return new UnprocessableEntityError(status, error, message, headers);
- }
-
- if (status === 429) {
- return new RateLimitError(status, error, message, headers);
- }
-
- if (status >= 500) {
- return new InternalServerError(status, error, message, headers);
- }
-
- return new APIError(status, error, message, headers);
- }
-}
-
-export class APIUserAbortError extends APIError<undefined, undefined, undefined> {
- constructor({ message }: { message?: string } = {}) {
- super(undefined, undefined, message || 'Request was aborted.', undefined);
- }
-}
-
-export class APIConnectionError extends APIError<undefined, undefined, undefined> {
- constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) {
- super(undefined, undefined, message || 'Connection error.', undefined);
- // in some environments the 'cause' property is already declared
- // @ts-ignore
- if (cause) this.cause = cause;
- }
-}
-
-export class APIConnectionTimeoutError extends APIConnectionError {
- constructor({ message }: { message?: string } = {}) {
- super({ message: message ?? 'Request timed out.' });
- }
-}
-
-export class BadRequestError extends APIError<400, Headers> {}
-
-export class AuthenticationError extends APIError<401, Headers> {}
-
-export class PermissionDeniedError extends APIError<403, Headers> {}
-
-export class NotFoundError extends APIError<404, Headers> {}
-
-export class ConflictError extends APIError<409, Headers> {}
-
-export class UnprocessableEntityError extends APIError<422, Headers> {}
-
-export class RateLimitError extends APIError<429, Headers> {}
-
-export class InternalServerError extends APIError<number, Headers> {}
diff --git a/packages/sdk/src/core/resource.ts b/packages/sdk/src/core/resource.ts
deleted file mode 100644
index ccf9032e4..000000000
--- a/packages/sdk/src/core/resource.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import type { Opencode } from '../client';
-
-export abstract class APIResource {
- protected _client: Opencode;
-
- constructor(client: Opencode) {
- this._client = client;
- }
-}
diff --git a/packages/sdk/src/core/streaming.ts b/packages/sdk/src/core/streaming.ts
deleted file mode 100644
index 33dcfd126..000000000
--- a/packages/sdk/src/core/streaming.ts
+++ /dev/null
@@ -1,315 +0,0 @@
-import { OpencodeError } from './error';
-import { type ReadableStream } from '../internal/shim-types';
-import { makeReadableStream } from '../internal/shims';
-import { findDoubleNewlineIndex, LineDecoder } from '../internal/decoders/line';
-import { ReadableStreamToAsyncIterable } from '../internal/shims';
-import { isAbortError } from '../internal/errors';
-import { encodeUTF8 } from '../internal/utils/bytes';
-import { loggerFor } from '../internal/utils/log';
-import type { Opencode } from '../client';
-
-type Bytes = string | ArrayBuffer | Uint8Array | null | undefined;
-
-export type ServerSentEvent = {
- event: string | null;
- data: string;
- raw: string[];
-};
-
-export class Stream<Item> implements AsyncIterable<Item> {
- controller: AbortController;
- #client: Opencode | undefined;
-
- constructor(
- private iterator: () => AsyncIterator<Item>,
- controller: AbortController,
- client?: Opencode,
- ) {
- this.controller = controller;
- this.#client = client;
- }
-
- static fromSSEResponse<Item>(
- response: Response,
- controller: AbortController,
- client?: Opencode,
- ): Stream<Item> {
- let consumed = false;
- const logger = client ? loggerFor(client) : console;
-
- async function* iterator(): AsyncIterator<Item, any, undefined> {
- if (consumed) {
- throw new OpencodeError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
- }
- consumed = true;
- let done = false;
- try {
- for await (const sse of _iterSSEMessages(response, controller)) {
- try {
- yield JSON.parse(sse.data);
- } catch (e) {
- logger.error(`Could not parse message into JSON:`, sse.data);
- logger.error(`From chunk:`, sse.raw);
- throw e;
- }
- }
- done = true;
- } catch (e) {
- // If the user calls `stream.controller.abort()`, we should exit without throwing.
- if (isAbortError(e)) return;
- throw e;
- } finally {
- // If the user `break`s, abort the ongoing request.
- if (!done) controller.abort();
- }
- }
-
- return new Stream(iterator, controller, client);
- }
-
- /**
- * Generates a Stream from a newline-separated ReadableStream
- * where each item is a JSON value.
- */
- static fromReadableStream<Item>(
- readableStream: ReadableStream,
- controller: AbortController,
- client?: Opencode,
- ): Stream<Item> {
- let consumed = false;
-
- async function* iterLines(): AsyncGenerator<string, void, unknown> {
- const lineDecoder = new LineDecoder();
-
- const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);
- for await (const chunk of iter) {
- for (const line of lineDecoder.decode(chunk)) {
- yield line;
- }
- }
-
- for (const line of lineDecoder.flush()) {
- yield line;
- }
- }
-
- async function* iterator(): AsyncIterator<Item, any, undefined> {
- if (consumed) {
- throw new OpencodeError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
- }
- consumed = true;
- let done = false;
- try {
- for await (const line of iterLines()) {
- if (done) continue;
- if (line) yield JSON.parse(line);
- }
- done = true;
- } catch (e) {
- // If the user calls `stream.controller.abort()`, we should exit without throwing.
- if (isAbortError(e)) return;
- throw e;
- } finally {
- // If the user `break`s, abort the ongoing request.
- if (!done) controller.abort();
- }
- }
-
- return new Stream(iterator, controller, client);
- }
-
- [Symbol.asyncIterator](): AsyncIterator<Item> {
- return this.iterator();
- }
-
- /**
- * Splits the stream into two streams which can be
- * independently read from at different speeds.
- */
- tee(): [Stream<Item>, Stream<Item>] {
- const left: Array<Promise<IteratorResult<Item>>> = [];
- const right: Array<Promise<IteratorResult<Item>>> = [];
- const iterator = this.iterator();
-
- const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {
- return {
- next: () => {
- if (queue.length === 0) {
- const result = iterator.next();
- left.push(result);
- right.push(result);
- }
- return queue.shift()!;
- },
- };
- };
-
- return [
- new Stream(() => teeIterator(left), this.controller, this.#client),
- new Stream(() => teeIterator(right), this.controller, this.#client),
- ];
- }
-
- /**
- * Converts this stream to a newline-separated ReadableStream of
- * JSON stringified values in the stream
- * which can be turned back into a Stream with `Stream.fromReadableStream()`.
- */
- toReadableStream(): ReadableStream {
- const self = this;
- let iter: AsyncIterator<Item>;
-
- return makeReadableStream({
- async start() {
- iter = self[Symbol.asyncIterator]();
- },
- async pull(ctrl: any) {
- try {
- const { value, done } = await iter.next();
- if (done) return ctrl.close();
-
- const bytes = encodeUTF8(JSON.stringify(value) + '\n');
-
- ctrl.enqueue(bytes);
- } catch (err) {
- ctrl.error(err);
- }
- },
- async cancel() {
- await iter.return?.();
- },
- });
- }
-}
-
-export async function* _iterSSEMessages(
- response: Response,
- controller: AbortController,
-): AsyncGenerator<ServerSentEvent, void, unknown> {
- if (!response.body) {
- controller.abort();
- if (
- typeof (globalThis as any).navigator !== 'undefined' &&
- (globalThis as any).navigator.product === 'ReactNative'
- ) {
- throw new OpencodeError(
- `The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`,
- );
- }
- throw new OpencodeError(`Attempted to iterate over a response with no body`);
- }
-
- const sseDecoder = new SSEDecoder();
- const lineDecoder = new LineDecoder();
-
- const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);
- for await (const sseChunk of iterSSEChunks(iter)) {
- for (const line of lineDecoder.decode(sseChunk)) {
- const sse = sseDecoder.decode(line);
- if (sse) yield sse;
- }
- }
-
- for (const line of lineDecoder.flush()) {
- const sse = sseDecoder.decode(line);
- if (sse) yield sse;
- }
-}
-
-/**
- * Given an async iterable iterator, iterates over it and yields full
- * SSE chunks, i.e. yields when a double new-line is encountered.
- */
-async function* iterSSEChunks(iterator: AsyncIterableIterator<Bytes>): AsyncGenerator<Uint8Array> {
- let data = new Uint8Array();
-
- for await (const chunk of iterator) {
- if (chunk == null) {
- continue;
- }
-
- const binaryChunk =
- chunk instanceof ArrayBuffer ? new Uint8Array(chunk)
- : typeof chunk === 'string' ? encodeUTF8(chunk)
- : chunk;
-
- let newData = new Uint8Array(data.length + binaryChunk.length);
- newData.set(data);
- newData.set(binaryChunk, data.length);
- data = newData;
-
- let patternIndex;
- while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {
- yield data.slice(0, patternIndex);
- data = data.slice(patternIndex);
- }
- }
-
- if (data.length > 0) {
- yield data;
- }
-}
-
-class SSEDecoder {
- private data: string[];
- private event: string | null;
- private chunks: string[];
-
- constructor() {
- this.event = null;
- this.data = [];
- this.chunks = [];
- }
-
- decode(line: string) {
- if (line.endsWith('\r')) {
- line = line.substring(0, line.length - 1);
- }
-
- if (!line) {
- // empty line and we didn't previously encounter any messages
- if (!this.event && !this.data.length) return null;
-
- const sse: ServerSentEvent = {
- event: this.event,
- data: this.data.join('\n'),
- raw: this.chunks,
- };
-
- this.event = null;
- this.data = [];
- this.chunks = [];
-
- return sse;
- }
-
- this.chunks.push(line);
-
- if (line.startsWith(':')) {
- return null;
- }
-
- let [fieldname, _, value] = partition(line, ':');
-
- if (value.startsWith(' ')) {
- value = value.substring(1);
- }
-
- if (fieldname === 'event') {
- this.event = value;
- } else if (fieldname === 'data') {
- this.data.push(value);
- }
-
- return null;
- }
-}
-
-function partition(str: string, delimiter: string): [string, string, string] {
- const index = str.indexOf(delimiter);
- if (index !== -1) {
- return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];
- }
-
- return [str, '', ''];
-}
diff --git a/packages/sdk/src/core/uploads.ts b/packages/sdk/src/core/uploads.ts
deleted file mode 100644
index 2882ca6d1..000000000
--- a/packages/sdk/src/core/uploads.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { type Uploadable } from '../internal/uploads';
-export { toFile, type ToFileInput } from '../internal/to-file';
diff --git a/packages/sdk/src/error.ts b/packages/sdk/src/error.ts
deleted file mode 100644
index fc55f46c0..000000000
--- a/packages/sdk/src/error.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/** @deprecated Import from ./core/error instead */
-export * from './core/error';
diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts
deleted file mode 100644
index 43d2f6363..000000000
--- a/packages/sdk/src/index.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export { Opencode as default } from './client';
-
-export { type Uploadable, toFile } from './core/uploads';
-export { APIPromise } from './core/api-promise';
-export { Opencode, type ClientOptions } from './client';
-export {
- OpencodeError,
- APIError,
- APIConnectionError,
- APIConnectionTimeoutError,
- APIUserAbortError,
- NotFoundError,
- ConflictError,
- RateLimitError,
- BadRequestError,
- AuthenticationError,
- InternalServerError,
- PermissionDeniedError,
- UnprocessableEntityError,
-} from './core/error';
diff --git a/packages/sdk/src/internal/README.md b/packages/sdk/src/internal/README.md
deleted file mode 100644
index 3ef5a25ba..000000000
--- a/packages/sdk/src/internal/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# `internal`
-
-The modules in this directory are not importable outside this package and will change between releases.
diff --git a/packages/sdk/src/internal/builtin-types.ts b/packages/sdk/src/internal/builtin-types.ts
deleted file mode 100644
index c23d3bded..000000000
--- a/packages/sdk/src/internal/builtin-types.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
-
-/**
- * An alias to the builtin `RequestInit` type so we can
- * easily alias it in import statements if there are name clashes.
- *
- * https://developer.mozilla.org/docs/Web/API/RequestInit
- */
-type _RequestInit = RequestInit;
-
-/**
- * An alias to the builtin `Response` type so we can
- * easily alias it in import statements if there are name clashes.
- *
- * https://developer.mozilla.org/docs/Web/API/Response
- */
-type _Response = Response;
-
-/**
- * The type for the first argument to `fetch`.
- *
- * https://developer.mozilla.org/docs/Web/API/Window/fetch#resource
- */
-type _RequestInfo = Request | URL | string;
-
-/**
- * The type for constructing `RequestInit` Headers.
- *
- * https://developer.mozilla.org/docs/Web/API/RequestInit#setting_headers
- */
-type _HeadersInit = RequestInit['headers'];
-
-/**
- * The type for constructing `RequestInit` body.
- *
- * https://developer.mozilla.org/docs/Web/API/RequestInit#body
- */
-type _BodyInit = RequestInit['body'];
-
-/**
- * An alias to the builtin `Array<T>` type so we can
- * easily alias it in import statements if there are name clashes.
- */
-type _Array<T> = Array<T>;
-
-/**
- * An alias to the builtin `Record<K, T>` type so we can
- * easily alias it in import statements if there are name clashes.
- */
-type _Record<K extends keyof any, T> = Record<K, T>;
-
-export type {
- _Array as Array,
- _BodyInit as BodyInit,
- _HeadersInit as HeadersInit,
- _Record as Record,
- _RequestInfo as RequestInfo,
- _RequestInit as RequestInit,
- _Response as Response,
-};
-
-/**
- * A copy of the builtin `EndingType` type as it isn't fully supported in certain
- * environments and attempting to reference the global version will error.
- *
- * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L27941
- */
-type EndingType = 'native' | 'transparent';
-
-/**
- * A copy of the builtin `BlobPropertyBag` type as it isn't fully supported in certain
- * environments and attempting to reference the global version will error.
- *
- * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L154
- * https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#options
- */
-export interface BlobPropertyBag {
- endings?: EndingType;
- type?: string;
-}
-
-/**
- * A copy of the builtin `FilePropertyBag` type as it isn't fully supported in certain
- * environments and attempting to reference the global version will error.
- *
- * https://github.com/microsoft/TypeScript/blob/49ad1a3917a0ea57f5ff248159256e12bb1cb705/src/lib/dom.generated.d.ts#L503
- * https://developer.mozilla.org/en-US/docs/Web/API/File/File#options
- */
-export interface FilePropertyBag extends BlobPropertyBag {
- lastModified?: number;
-}
diff --git a/packages/sdk/src/internal/decoders/line.ts b/packages/sdk/src/internal/decoders/line.ts
deleted file mode 100644
index b3bfa97cd..000000000
--- a/packages/sdk/src/internal/decoders/line.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import { concatBytes, decodeUTF8, encodeUTF8 } from '../utils/bytes';
-
-export type Bytes = string | ArrayBuffer | Uint8Array | null | undefined;
-
-/**
- * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
- * reading lines from text.
- *
- * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
- */
-export class LineDecoder {
- // prettier-ignore
- static NEWLINE_CHARS = new Set(['\n', '\r']);
- static NEWLINE_REGEXP = /\r\n|[\n\r]/g;
-
- #buffer: Uint8Array;
- #carriageReturnIndex: number | null;
-
- constructor() {
- this.#buffer = new Uint8Array();
- this.#carriageReturnIndex = null;
- }
-
- decode(chunk: Bytes): string[] {
- if (chunk == null) {
- return [];
- }
-
- const binaryChunk =
- chunk instanceof ArrayBuffer ? new Uint8Array(chunk)
- : typeof chunk === 'string' ? encodeUTF8(chunk)
- : chunk;
-
- this.#buffer = concatBytes([this.#buffer, binaryChunk]);
-
- const lines: string[] = [];
- let patternIndex;
- while ((patternIndex = findNewlineIndex(this.#buffer, this.#carriageReturnIndex)) != null) {
- if (patternIndex.carriage && this.#carriageReturnIndex == null) {
- // skip until we either get a corresponding `\n`, a new `\r` or nothing
- this.#carriageReturnIndex = patternIndex.index;
- continue;
- }
-
- // we got double \r or \rtext\n
- if (
- this.#carriageReturnIndex != null &&
- (patternIndex.index !== this.#carriageReturnIndex + 1 || patternIndex.carriage)
- ) {
- lines.push(decodeUTF8(this.#buffer.subarray(0, this.#carriageReturnIndex - 1)));
- this.#buffer = this.#buffer.subarray(this.#carriageReturnIndex);
- this.#carriageReturnIndex = null;
- continue;
- }
-
- const endIndex =
- this.#carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding;
-
- const line = decodeUTF8(this.#buffer.subarray(0, endIndex));
- lines.push(line);
-
- this.#buffer = this.#buffer.subarray(patternIndex.index);
- this.#carriageReturnIndex = null;
- }
-
- return lines;
- }
-
- flush(): string[] {
- if (!this.#buffer.length) {
- return [];
- }
- return this.decode('\n');
- }
-}
-
-/**
- * This function searches the buffer for the end patterns, (\r or \n)
- * and returns an object with the index preceding the matched newline and the
- * index after the newline char. `null` is returned if no new line is found.
- *
- * ```ts
- * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 }
- * ```
- */
-function findNewlineIndex(
- buffer: Uint8Array,
- startIndex: number | null,
-): { preceding: number; index: number; carriage: boolean } | null {
- const newline = 0x0a; // \n
- const carriage = 0x0d; // \r
-
- for (let i = startIndex ?? 0; i < buffer.length; i++) {
- if (buffer[i] === newline) {
- return { preceding: i, index: i + 1, carriage: false };
- }
-
- if (buffer[i] === carriage) {
- return { preceding: i, index: i + 1, carriage: true };
- }
- }
-
- return null;
-}
-
-export function findDoubleNewlineIndex(buffer: Uint8Array): number {
- // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n)
- // and returns the index right after the first occurrence of any pattern,
- // or -1 if none of the patterns are found.
- const newline = 0x0a; // \n
- const carriage = 0x0d; // \r
-
- for (let i = 0; i < buffer.length - 1; i++) {
- if (buffer[i] === newline && buffer[i + 1] === newline) {
- // \n\n
- return i + 2;
- }
- if (buffer[i] === carriage && buffer[i + 1] === carriage) {
- // \r\r
- return i + 2;
- }
- if (
- buffer[i] === carriage &&
- buffer[i + 1] === newline &&
- i + 3 < buffer.length &&
- buffer[i + 2] === carriage &&
- buffer[i + 3] === newline
- ) {
- // \r\n\r\n
- return i + 4;
- }
- }
-
- return -1;
-}
diff --git a/packages/sdk/src/internal/detect-platform.ts b/packages/sdk/src/internal/detect-platform.ts
deleted file mode 100644
index e82d95c92..000000000
--- a/packages/sdk/src/internal/detect-platform.ts
+++ /dev/null
@@ -1,196 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { VERSION } from '../version';
-
-export const isRunningInBrowser = () => {
- return (
- // @ts-ignore
- typeof window !== 'undefined' &&
- // @ts-ignore
- typeof window.document !== 'undefined' &&
- // @ts-ignore
- typeof navigator !== 'undefined'
- );
-};
-
-type DetectedPlatform = 'deno' | 'node' | 'edge' | 'unknown';
-
-/**
- * Note this does not detect 'browser'; for that, use getBrowserInfo().
- */
-function getDetectedPlatform(): DetectedPlatform {
- if (typeof Deno !== 'undefined' && Deno.build != null) {
- return 'deno';
- }
- if (typeof EdgeRuntime !== 'undefined') {
- return 'edge';
- }
- if (
- Object.prototype.toString.call(
- typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0,
- ) === '[object process]'
- ) {
- return 'node';
- }
- return 'unknown';
-}
-
-declare const Deno: any;
-declare const EdgeRuntime: any;
-type Arch = 'x32' | 'x64' | 'arm' | 'arm64' | `other:${string}` | 'unknown';
-type PlatformName =
- | 'MacOS'
- | 'Linux'
- | 'Windows'
- | 'FreeBSD'
- | 'OpenBSD'
- | 'iOS'
- | 'Android'
- | `Other:${string}`
- | 'Unknown';
-type Browser = 'ie' | 'edge' | 'chrome' | 'firefox' | 'safari';
-type PlatformProperties = {
- 'X-Stainless-Lang': 'js';
- 'X-Stainless-Package-Version': string;
- 'X-Stainless-OS': PlatformName;
- 'X-Stainless-Arch': Arch;
- 'X-Stainless-Runtime': 'node' | 'deno' | 'edge' | `browser:${Browser}` | 'unknown';
- 'X-Stainless-Runtime-Version': string;
-};
-const getPlatformProperties = (): PlatformProperties => {
- const detectedPlatform = getDetectedPlatform();
- if (detectedPlatform === 'deno') {
- return {
- 'X-Stainless-Lang': 'js',
- 'X-Stainless-Package-Version': VERSION,
- 'X-Stainless-OS': normalizePlatform(Deno.build.os),
- 'X-Stainless-Arch': normalizeArch(Deno.build.arch),
- 'X-Stainless-Runtime': 'deno',
- 'X-Stainless-Runtime-Version':
- typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown',
- };
- }
- if (typeof EdgeRuntime !== 'undefined') {
- return {
- 'X-Stainless-Lang': 'js',
- 'X-Stainless-Package-Version': VERSION,
- 'X-Stainless-OS': 'Unknown',
- 'X-Stainless-Arch': `other:${EdgeRuntime}`,
- 'X-Stainless-Runtime': 'edge',
- 'X-Stainless-Runtime-Version': (globalThis as any).process.version,
- };
- }
- // Check if Node.js
- if (detectedPlatform === 'node') {
- return {
- 'X-Stainless-Lang': 'js',
- 'X-Stainless-Package-Version': VERSION,
- 'X-Stainless-OS': normalizePlatform((globalThis as any).process.platform ?? 'unknown'),
- 'X-Stainless-Arch': normalizeArch((globalThis as any).process.arch ?? 'unknown'),
- 'X-Stainless-Runtime': 'node',
- 'X-Stainless-Runtime-Version': (globalThis as any).process.version ?? 'unknown',
- };
- }
-
- const browserInfo = getBrowserInfo();
- if (browserInfo) {
- return {
- 'X-Stainless-Lang': 'js',
- 'X-Stainless-Package-Version': VERSION,
- 'X-Stainless-OS': 'Unknown',
- 'X-Stainless-Arch': 'unknown',
- 'X-Stainless-Runtime': `browser:${browserInfo.browser}`,
- 'X-Stainless-Runtime-Version': browserInfo.version,
- };
- }
-
- // TODO add support for Cloudflare workers, etc.
- return {
- 'X-Stainless-Lang': 'js',
- 'X-Stainless-Package-Version': VERSION,
- 'X-Stainless-OS': 'Unknown',
- 'X-Stainless-Arch': 'unknown',
- 'X-Stainless-Runtime': 'unknown',
- 'X-Stainless-Runtime-Version': 'unknown',
- };
-};
-
-type BrowserInfo = {
- browser: Browser;
- version: string;
-};
-
-declare const navigator: { userAgent: string } | undefined;
-
-// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts
-function getBrowserInfo(): BrowserInfo | null {
- if (typeof navigator === 'undefined' || !navigator) {
- return null;
- }
-
- // NOTE: The order matters here!
- const browserPatterns = [
- { key: 'edge' as const, pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
- { key: 'ie' as const, pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
- { key: 'ie' as const, pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
- { key: 'chrome' as const, pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
- { key: 'firefox' as const, pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
- { key: 'safari' as const, pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ },
- ];
-
- // Find the FIRST matching browser
- for (const { key, pattern } of browserPatterns) {
- const match = pattern.exec(navigator.userAgent);
- if (match) {
- const major = match[1] || 0;
- const minor = match[2] || 0;
- const patch = match[3] || 0;
-
- return { browser: key, version: `${major}.${minor}.${patch}` };
- }
- }
-
- return null;
-}
-
-const normalizeArch = (arch: string): Arch => {
- // Node docs:
- // - https://nodejs.org/api/process.html#processarch
- // Deno docs:
- // - https://doc.deno.land/deno/stable/~/Deno.build
- if (arch === 'x32') return 'x32';
- if (arch === 'x86_64' || arch === 'x64') return 'x64';
- if (arch === 'arm') return 'arm';
- if (arch === 'aarch64' || arch === 'arm64') return 'arm64';
- if (arch) return `other:${arch}`;
- return 'unknown';
-};
-
-const normalizePlatform = (platform: string): PlatformName => {
- // Node platforms:
- // - https://nodejs.org/api/process.html#processplatform
- // Deno platforms:
- // - https://doc.deno.land/deno/stable/~/Deno.build
- // - https://github.com/denoland/deno/issues/14799
-
- platform = platform.toLowerCase();
-
- // NOTE: this iOS check is untested and may not work
- // Node does not work natively on IOS, there is a fork at
- // https://github.com/nodejs-mobile/nodejs-mobile
- // however it is unknown at the time of writing how to detect if it is running
- if (platform.includes('ios')) return 'iOS';
- if (platform === 'android') return 'Android';
- if (platform === 'darwin') return 'MacOS';
- if (platform === 'win32') return 'Windows';
- if (platform === 'freebsd') return 'FreeBSD';
- if (platform === 'openbsd') return 'OpenBSD';
- if (platform === 'linux') return 'Linux';
- if (platform) return `Other:${platform}`;
- return 'Unknown';
-};
-
-let _platformHeaders: PlatformProperties;
-export const getPlatformHeaders = () => {
- return (_platformHeaders ??= getPlatformProperties());
-};
diff --git a/packages/sdk/src/internal/errors.ts b/packages/sdk/src/internal/errors.ts
deleted file mode 100644
index 82c7b14d5..000000000
--- a/packages/sdk/src/internal/errors.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export function isAbortError(err: unknown) {
- return (
- typeof err === 'object' &&
- err !== null &&
- // Spec-compliant fetch implementations
- (('name' in err && (err as any).name === 'AbortError') ||
- // Expo fetch
- ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')))
- );
-}
-
-export const castToError = (err: any): Error => {
- if (err instanceof Error) return err;
- if (typeof err === 'object' && err !== null) {
- try {
- if (Object.prototype.toString.call(err) === '[object Error]') {
- // @ts-ignore - not all envs have native support for cause yet
- const error = new Error(err.message, err.cause ? { cause: err.cause } : {});
- if (err.stack) error.stack = err.stack;
- // @ts-ignore - not all envs have native support for cause yet
- if (err.cause && !error.cause) error.cause = err.cause;
- if (err.name) error.name = err.name;
- return error;
- }
- } catch {}
- try {
- return new Error(JSON.stringify(err));
- } catch {}
- }
- return new Error(err);
-};
diff --git a/packages/sdk/src/internal/headers.ts b/packages/sdk/src/internal/headers.ts
deleted file mode 100644
index c724a9d22..000000000
--- a/packages/sdk/src/internal/headers.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { isReadonlyArray } from './utils/values';
-
-type HeaderValue = string | undefined | null;
-export type HeadersLike =
- | Headers
- | readonly HeaderValue[][]
- | Record<string, HeaderValue | readonly HeaderValue[]>
- | undefined
- | null
- | NullableHeaders;
-
-const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('brand.privateNullableHeaders');
-
-/**
- * @internal
- * Users can pass explicit nulls to unset default headers. When we parse them
- * into a standard headers type we need to preserve that information.
- */
-export type NullableHeaders = {
- /** Brand check, prevent users from creating a NullableHeaders. */
- [brand_privateNullableHeaders]: true;
- /** Parsed headers. */
- values: Headers;
- /** Set of lowercase header names explicitly set to null. */
- nulls: Set<string>;
-};
-
-function* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {
- if (!headers) return;
-
- if (brand_privateNullableHeaders in headers) {
- const { values, nulls } = headers;
- yield* values.entries();
- for (const name of nulls) {
- yield [name, null];
- }
- return;
- }
-
- let shouldClear = false;
- let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;
- if (headers instanceof Headers) {
- iter = headers.entries();
- } else if (isReadonlyArray(headers)) {
- iter = headers;
- } else {
- shouldClear = true;
- iter = Object.entries(headers ?? {});
- }
- for (let row of iter) {
- const name = row[0];
- if (typeof name !== 'string') throw new TypeError('expected header name to be a string');
- const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
- let didClear = false;
- for (const value of values) {
- if (value === undefined) continue;
-
- // Objects keys always overwrite older headers, they never append.
- // Yield a null to clear the header before adding the new values.
- if (shouldClear && !didClear) {
- didClear = true;
- yield [name, null];
- }
- yield [name, value];
- }
- }
-}
-
-export const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {
- const targetHeaders = new Headers();
- const nullHeaders = new Set<string>();
- for (const headers of newHeaders) {
- const seenHeaders = new Set<string>();
- for (const [name, value] of iterateHeaders(headers)) {
- const lowerName = name.toLowerCase();
- if (!seenHeaders.has(lowerName)) {
- targetHeaders.delete(name);
- seenHeaders.add(lowerName);
- }
- if (value === null) {
- targetHeaders.delete(name);
- nullHeaders.add(lowerName);
- } else {
- targetHeaders.append(name, value);
- nullHeaders.delete(lowerName);
- }
- }
- }
- return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
-};
-
-export const isEmptyHeaders = (headers: HeadersLike) => {
- for (const _ of iterateHeaders(headers)) return false;
- return true;
-};
diff --git a/packages/sdk/src/internal/parse.ts b/packages/sdk/src/internal/parse.ts
deleted file mode 100644
index dcb4026e3..000000000
--- a/packages/sdk/src/internal/parse.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import type { FinalRequestOptions } from './request-options';
-import { Stream } from '../core/streaming';
-import { type Opencode } from '../client';
-import { formatRequestDetails, loggerFor } from './utils/log';
-
-export type APIResponseProps = {
- response: Response;
- options: FinalRequestOptions;
- controller: AbortController;
- requestLogID: string;
- retryOfRequestLogID: string | undefined;
- startTime: number;
-};
-
-export async function defaultParseResponse<T>(client: Opencode, props: APIResponseProps): Promise<T> {
- const { response, requestLogID, retryOfRequestLogID, startTime } = props;
- const body = await (async () => {
- if (props.options.stream) {
- loggerFor(client).debug('response', response.status, response.url, response.headers, response.body);
-
- // Note: there is an invariant here that isn't represented in the type system
- // that if you set `stream: true` the response type must also be `Stream<T>`
-
- if (props.options.__streamClass) {
- return props.options.__streamClass.fromSSEResponse(response, props.controller, client) as any;
- }
-
- return Stream.fromSSEResponse(response, props.controller, client) as any;
- }
-
- // fetch refuses to read the body when the status code is 204.
- if (response.status === 204) {
- return null as T;
- }
-
- if (props.options.__binaryResponse) {
- return response as unknown as T;
- }
-
- const contentType = response.headers.get('content-type');
- const mediaType = contentType?.split(';')[0]?.trim();
- const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');
- if (isJSON) {
- const json = await response.json();
- return json as T;
- }
-
- const text = await response.text();
- return text as unknown as T;
- })();
- loggerFor(client).debug(
- `[${requestLogID}] response parsed`,
- formatRequestDetails({
- retryOfRequestLogID,
- url: response.url,
- status: response.status,
- body,
- durationMs: Date.now() - startTime,
- }),
- );
- return body;
-}
diff --git a/packages/sdk/src/internal/request-options.ts b/packages/sdk/src/internal/request-options.ts
deleted file mode 100644
index 56765e5aa..000000000
--- a/packages/sdk/src/internal/request-options.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { NullableHeaders } from './headers';
-
-import type { BodyInit } from './builtin-types';
-import { Stream } from '../core/streaming';
-import type { HTTPMethod, MergedRequestInit } from './types';
-import { type HeadersLike } from './headers';
-
-export type FinalRequestOptions = RequestOptions & { method: HTTPMethod; path: string };
-
-export type RequestOptions = {
- /**
- * The HTTP method for the request (e.g., 'get', 'post', 'put', 'delete').
- */
- method?: HTTPMethod;
-
- /**
- * The URL path for the request.
- *
- * @example "/v1/foo"
- */
- path?: string;
-
- /**
- * Query parameters to include in the request URL.
- */
- query?: object | undefined | null;
-
- /**
- * The request body. Can be a string, JSON object, FormData, or other supported types.
- */
- body?: unknown;
-
- /**
- * HTTP headers to include with the request. Can be a Headers object, plain object, or array of tuples.
- */
- headers?: HeadersLike;
-
- /**
- * The maximum number of times that the client will retry a request in case of a
- * temporary failure, like a network error or a 5XX error from the server.
- *
- * @default 2
- */
- maxRetries?: number;
-
- stream?: boolean | undefined;
-
- /**
- * The maximum amount of time (in milliseconds) that the client should wait for a response
- * from the server before timing out a single request.
- *
- * @unit milliseconds
- */
- timeout?: number;
-
- /**
- * Additional `RequestInit` options to be passed to the underlying `fetch` call.
- * These options will be merged with the client's default fetch options.
- */
- fetchOptions?: MergedRequestInit;
-
- /**
- * An AbortSignal that can be used to cancel the request.
- */
- signal?: AbortSignal | undefined | null;
-
- /**
- * A unique key for this request to enable idempotency.
- */
- idempotencyKey?: string;
-
- /**
- * Override the default base URL for this specific request.
- */
- defaultBaseURL?: string | undefined;
-
- __binaryResponse?: boolean | undefined;
- __streamClass?: typeof Stream;
-};
-
-export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit };
-export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent;
-
-export const FallbackEncoder: RequestEncoder = ({ headers, body }) => {
- return {
- bodyHeaders: {
- 'content-type': 'application/json',
- },
- body: JSON.stringify(body),
- };
-};
diff --git a/packages/sdk/src/internal/shim-types.ts b/packages/sdk/src/internal/shim-types.ts
deleted file mode 100644
index 8ddf7b0ad..000000000
--- a/packages/sdk/src/internal/shim-types.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-/**
- * Shims for types that we can't always rely on being available globally.
- *
- * Note: these only exist at the type-level, there is no corresponding runtime
- * version for any of these symbols.
- */
-
-type NeverToAny<T> = T extends never ? any : T;
-
-/** @ts-ignore */
-type _DOMReadableStream<R = any> = globalThis.ReadableStream<R>;
-
-/** @ts-ignore */
-type _NodeReadableStream<R = any> = import('stream/web').ReadableStream<R>;
-
-type _ConditionalNodeReadableStream<R = any> =
- typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream<R>;
-
-type _ReadableStream<R = any> = NeverToAny<
- | ([0] extends [1 & _DOMReadableStream<R>] ? never : _DOMReadableStream<R>)
- | ([0] extends [1 & _ConditionalNodeReadableStream<R>] ? never : _ConditionalNodeReadableStream<R>)
->;
-
-export type { _ReadableStream as ReadableStream };
diff --git a/packages/sdk/src/internal/shims.ts b/packages/sdk/src/internal/shims.ts
deleted file mode 100644
index 17a7967aa..000000000
--- a/packages/sdk/src/internal/shims.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-/**
- * This module provides internal shims and utility functions for environments where certain Node.js or global types may not be available.
- *
- * These are used to ensure we can provide a consistent behaviour between different JavaScript environments and good error
- * messages in cases where an environment isn't fully supported.
- */
-
-import type { Fetch } from './builtin-types';
-import type { ReadableStream } from './shim-types';
-
-export function getDefaultFetch(): Fetch {
- if (typeof fetch !== 'undefined') {
- return fetch as any;
- }
-
- throw new Error(
- '`fetch` is not defined as a global; Either pass `fetch` to the client, `new Opencode({ fetch })` or polyfill the global, `globalThis.fetch = fetch`',
- );
-}
-
-type ReadableStreamArgs = ConstructorParameters<typeof ReadableStream>;
-
-export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream {
- const ReadableStream = (globalThis as any).ReadableStream;
- if (typeof ReadableStream === 'undefined') {
- // Note: All of the platforms / runtimes we officially support already define
- // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.
- throw new Error(
- '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`',
- );
- }
-
- return new ReadableStream(...args);
-}
-
-export function ReadableStreamFrom<T>(iterable: Iterable<T> | AsyncIterable<T>): ReadableStream<T> {
- let iter: AsyncIterator<T> | Iterator<T> =
- Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
-
- return makeReadableStream({
- start() {},
- async pull(controller: any) {
- const { done, value } = await iter.next();
- if (done) {
- controller.close();
- } else {
- controller.enqueue(value);
- }
- },
- async cancel() {
- await iter.return?.();
- },
- });
-}
-
-/**
- * Most browsers don't yet have async iterable support for ReadableStream,
- * and Node has a very different way of reading bytes from its "ReadableStream".
- *
- * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
- */
-export function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {
- if (stream[Symbol.asyncIterator]) return stream;
-
- const reader = stream.getReader();
- return {
- async next() {
- try {
- const result = await reader.read();
- if (result?.done) reader.releaseLock(); // release lock when stream becomes closed
- return result;
- } catch (e) {
- reader.releaseLock(); // release lock when stream becomes errored
- throw e;
- }
- },
- async return() {
- const cancelPromise = reader.cancel();
- reader.releaseLock();
- await cancelPromise;
- return { done: true, value: undefined };
- },
- [Symbol.asyncIterator]() {
- return this;
- },
- };
-}
-
-/**
- * Cancels a ReadableStream we don't need to consume.
- * See https://undici.nodejs.org/#/?id=garbage-collection
- */
-export async function CancelReadableStream(stream: any): Promise<void> {
- if (stream === null || typeof stream !== 'object') return;
-
- if (stream[Symbol.asyncIterator]) {
- await stream[Symbol.asyncIterator]().return?.();
- return;
- }
-
- const reader = stream.getReader();
- const cancelPromise = reader.cancel();
- reader.releaseLock();
- await cancelPromise;
-}
diff --git a/packages/sdk/src/internal/to-file.ts b/packages/sdk/src/internal/to-file.ts
deleted file mode 100644
index 245e84933..000000000
--- a/packages/sdk/src/internal/to-file.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-import { BlobPart, getName, makeFile, isAsyncIterable } from './uploads';
-import type { FilePropertyBag } from './builtin-types';
-import { checkFileSupport } from './uploads';
-
-type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | DataView;
-
-/**
- * Intended to match DOM Blob, node-fetch Blob, node:buffer Blob, etc.
- * Don't add arrayBuffer here, node-fetch doesn't have it
- */
-interface BlobLike {
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */
- readonly size: number;
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */
- readonly type: string;
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */
- text(): Promise<string>;
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */
- slice(start?: number, end?: number): BlobLike;
-}
-
-/**
- * This check adds the arrayBuffer() method type because it is available and used at runtime
- */
-const isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>
- value != null &&
- typeof value === 'object' &&
- typeof value.size === 'number' &&
- typeof value.type === 'string' &&
- typeof value.text === 'function' &&
- typeof value.slice === 'function' &&
- typeof value.arrayBuffer === 'function';
-
-/**
- * Intended to match DOM File, node:buffer File, undici File, etc.
- */
-interface FileLike extends BlobLike {
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */
- readonly lastModified: number;
- /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */
- readonly name?: string | undefined;
-}
-
-/**
- * This check adds the arrayBuffer() method type because it is available and used at runtime
- */
-const isFileLike = (value: any): value is FileLike & { arrayBuffer(): Promise<ArrayBuffer> } =>
- value != null &&
- typeof value === 'object' &&
- typeof value.name === 'string' &&
- typeof value.lastModified === 'number' &&
- isBlobLike(value);
-
-/**
- * Intended to match DOM Response, node-fetch Response, undici Response, etc.
- */
-export interface ResponseLike {
- url: string;
- blob(): Promise<BlobLike>;
-}
-
-const isResponseLike = (value: any): value is ResponseLike =>
- value != null &&
- typeof value === 'object' &&
- typeof value.url === 'string' &&
- typeof value.blob === 'function';
-
-export type ToFileInput =
- | FileLike
- | ResponseLike
- | Exclude<BlobLikePart, string>
- | AsyncIterable<BlobLikePart>;
-
-/**
- * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
- * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
- * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
- * @param {Object=} options additional properties
- * @param {string=} options.type the MIME type of the content
- * @param {number=} options.lastModified the last modified timestamp
- * @returns a {@link File} with the given properties
- */
-export async function toFile(
- value: ToFileInput | PromiseLike<ToFileInput>,
- name?: string | null | undefined,
- options?: FilePropertyBag | undefined,
-): Promise<File> {
- checkFileSupport();
-
- // If it's a promise, resolve it.
- value = await value;
-
- // If we've been given a `File` we don't need to do anything
- if (isFileLike(value)) {
- if (value instanceof File) {
- return value;
- }
- return makeFile([await value.arrayBuffer()], value.name);
- }
-
- if (isResponseLike(value)) {
- const blob = await value.blob();
- name ||= new URL(value.url).pathname.split(/[\\/]/).pop();
-
- return makeFile(await getBytes(blob), name, options);
- }
-
- const parts = await getBytes(value);
-
- name ||= getName(value);
-
- if (!options?.type) {
- const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);
- if (typeof type === 'string') {
- options = { ...options, type };
- }
- }
-
- return makeFile(parts, name, options);
-}
-
-async function getBytes(value: BlobLikePart | AsyncIterable<BlobLikePart>): Promise<Array<BlobPart>> {
- let parts: Array<BlobPart> = [];
- if (
- typeof value === 'string' ||
- ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.
- value instanceof ArrayBuffer
- ) {
- parts.push(value);
- } else if (isBlobLike(value)) {
- parts.push(value instanceof Blob ? value : await value.arrayBuffer());
- } else if (
- isAsyncIterable(value) // includes Readable, ReadableStream, etc.
- ) {
- for await (const chunk of value) {
- parts.push(...(await getBytes(chunk as BlobLikePart))); // TODO, consider validating?
- }
- } else {
- const constructor = value?.constructor?.name;
- throw new Error(
- `Unexpected data type: ${typeof value}${
- constructor ? `; constructor: ${constructor}` : ''
- }${propsForError(value)}`,
- );
- }
-
- return parts;
-}
-
-function propsForError(value: unknown): string {
- if (typeof value !== 'object' || value === null) return '';
- const props = Object.getOwnPropertyNames(value);
- return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`;
-}
diff --git a/packages/sdk/src/internal/types.ts b/packages/sdk/src/internal/types.ts
deleted file mode 100644
index b668dfc0f..000000000
--- a/packages/sdk/src/internal/types.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export type PromiseOrValue<T> = T | Promise<T>;
-export type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
-
-export type KeysEnum<T> = { [P in keyof Required<T>]: true };
-
-export type FinalizedRequestInit = RequestInit & { headers: Headers };
-
-type NotAny<T> = [0] extends [1 & T] ? never : T;
-
-/**
- * Some environments overload the global fetch function, and Parameters<T> only gets the last signature.
- */
-type OverloadedParameters<T> =
- T extends (
- {
- (...args: infer A): unknown;
- (...args: infer B): unknown;
- (...args: infer C): unknown;
- (...args: infer D): unknown;
- }
- ) ?
- A | B | C | D
- : T extends (
- {
- (...args: infer A): unknown;
- (...args: infer B): unknown;
- (...args: infer C): unknown;
- }
- ) ?
- A | B | C
- : T extends (
- {
- (...args: infer A): unknown;
- (...args: infer B): unknown;
- }
- ) ?
- A | B
- : T extends (...args: infer A) => unknown ? A
- : never;
-
-/* eslint-disable */
-/**
- * These imports attempt to get types from a parent package's dependencies.
- * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which
- * would cause typescript to show types not present at runtime. To avoid this, we import
- * directly from parent node_modules folders.
- *
- * We need to check multiple levels because we don't know what directory structure we'll be in.
- * For example, pnpm generates directories like this:
- * ```
- * node_modules
- * ├── .pnpm
- * │ └── [email protected]
- * │ └── node_modules
- * │ └── pkg
- * │ └── internal
- * │ └── types.d.ts
- * ├── pkg -> .pnpm/[email protected]/node_modules/pkg
- * └── undici
- * ```
- *
- * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition
- */
-/** @ts-ignore For users with \@types/node */
-type UndiciTypesRequestInit = NotAny<import('../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici-types/index.d.ts').RequestInit>;
-/** @ts-ignore For users with undici */
-type UndiciRequestInit = NotAny<import('../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/undici/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/undici/index.d.ts').RequestInit>;
-/** @ts-ignore For users with \@types/bun */
-type BunRequestInit = globalThis.FetchRequestInit;
-/** @ts-ignore For users with node-fetch@2 */
-type NodeFetch2RequestInit = NotAny<import('../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/@types/node-fetch/index.d.ts').RequestInit>;
-/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */
-type NodeFetch3RequestInit = NotAny<import('../node_modules/node-fetch').RequestInit> | NotAny<import('../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../node_modules/node-fetch').RequestInit> | NotAny<import('../../../../../../../../../../node_modules/node-fetch').RequestInit>;
-/** @ts-ignore For users who use Deno */
-type FetchRequestInit = NonNullable<OverloadedParameters<typeof fetch>[1]>;
-/* eslint-enable */
-
-type RequestInits =
- | NotAny<UndiciTypesRequestInit>
- | NotAny<UndiciRequestInit>
- | NotAny<BunRequestInit>
- | NotAny<NodeFetch2RequestInit>
- | NotAny<NodeFetch3RequestInit>
- | NotAny<RequestInit>
- | NotAny<FetchRequestInit>;
-
-/**
- * This type contains `RequestInit` options that may be available on the current runtime,
- * including per-platform extensions like `dispatcher`, `agent`, `client`, etc.
- */
-export type MergedRequestInit = RequestInits &
- /** We don't include these in the types as they'll be overridden for every request. */
- Partial<Record<'body' | 'headers' | 'method' | 'signal', never>>;
diff --git a/packages/sdk/src/internal/uploads.ts b/packages/sdk/src/internal/uploads.ts
deleted file mode 100644
index eb55f834e..000000000
--- a/packages/sdk/src/internal/uploads.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-import { type RequestOptions } from './request-options';
-import type { FilePropertyBag, Fetch } from './builtin-types';
-import type { Opencode } from '../client';
-import { ReadableStreamFrom } from './shims';
-
-export type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | DataView;
-type FsReadStream = AsyncIterable<Uint8Array> & { path: string | { toString(): string } };
-
-// https://github.com/oven-sh/bun/issues/5980
-interface BunFile extends Blob {
- readonly name?: string | undefined;
-}
-
-export const checkFileSupport = () => {
- if (typeof File === 'undefined') {
- const { process } = globalThis as any;
- const isOldNode =
- typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;
- throw new Error(
- '`File` is not defined as a global, which is required for file uploads.' +
- (isOldNode ?
- " Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`."
- : ''),
- );
- }
-};
-
-/**
- * Typically, this is a native "File" class.
- *
- * We provide the {@link toFile} utility to convert a variety of objects
- * into the File class.
- *
- * For convenience, you can also pass a fetch Response, or in Node,
- * the result of fs.createReadStream().
- */
-export type Uploadable = File | Response | FsReadStream | BunFile;
-
-/**
- * Construct a `File` instance. This is used to ensure a helpful error is thrown
- * for environments that don't define a global `File` yet.
- */
-export function makeFile(
- fileBits: BlobPart[],
- fileName: string | undefined,
- options?: FilePropertyBag,
-): File {
- checkFileSupport();
- return new File(fileBits as any, fileName ?? 'unknown_file', options);
-}
-
-export function getName(value: any): string | undefined {
- return (
- (
- (typeof value === 'object' &&
- value !== null &&
- (('name' in value && value.name && String(value.name)) ||
- ('url' in value && value.url && String(value.url)) ||
- ('filename' in value && value.filename && String(value.filename)) ||
- ('path' in value && value.path && String(value.path)))) ||
- ''
- )
- .split(/[\\/]/)
- .pop() || undefined
- );
-}
-
-export const isAsyncIterable = (value: any): value is AsyncIterable<any> =>
- value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';
-
-/**
- * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.
- * Otherwise returns the request as is.
- */
-export const maybeMultipartFormRequestOptions = async (
- opts: RequestOptions,
- fetch: Opencode | Fetch,
-): Promise<RequestOptions> => {
- if (!hasUploadableValue(opts.body)) return opts;
-
- return { ...opts, body: await createForm(opts.body, fetch) };
-};
-
-type MultipartFormRequestOptions = Omit<RequestOptions, 'body'> & { body: unknown };
-
-export const multipartFormRequestOptions = async (
- opts: MultipartFormRequestOptions,
- fetch: Opencode | Fetch,
-): Promise<RequestOptions> => {
- return { ...opts, body: await createForm(opts.body, fetch) };
-};
-
-const supportsFormDataMap = /* @__PURE__ */ new WeakMap<Fetch, Promise<boolean>>();
-
-/**
- * node-fetch doesn't support the global FormData object in recent node versions. Instead of sending
- * properly-encoded form data, it just stringifies the object, resulting in a request body of "[object FormData]".
- * This function detects if the fetch function provided supports the global FormData object to avoid
- * confusing error messages later on.
- */
-function supportsFormData(fetchObject: Opencode | Fetch): Promise<boolean> {
- const fetch: Fetch = typeof fetchObject === 'function' ? fetchObject : (fetchObject as any).fetch;
- const cached = supportsFormDataMap.get(fetch);
- if (cached) return cached;
- const promise = (async () => {
- try {
- const FetchResponse = (
- 'Response' in fetch ?
- fetch.Response
- : (await fetch('data:,')).constructor) as typeof Response;
- const data = new FormData();
- if (data.toString() === (await new FetchResponse(data).text())) {
- return false;
- }
- return true;
- } catch {
- // avoid false negatives
- return true;
- }
- })();
- supportsFormDataMap.set(fetch, promise);
- return promise;
-}
-
-export const createForm = async <T = Record<string, unknown>>(
- body: T | undefined,
- fetch: Opencode | Fetch,
-): Promise<FormData> => {
- if (!(await supportsFormData(fetch))) {
- throw new TypeError(
- 'The provided fetch function does not support file uploads with the current global FormData class.',
- );
- }
- const form = new FormData();
- await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));
- return form;
-};
-
-// We check for Blob not File because Bun.File doesn't inherit from File,
-// but they both inherit from Blob and have a `name` property at runtime.
-const isNamedBlob = (value: unknown) => value instanceof Blob && 'name' in value;
-
-const isUploadable = (value: unknown) =>
- typeof value === 'object' &&
- value !== null &&
- (value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));
-
-const hasUploadableValue = (value: unknown): boolean => {
- if (isUploadable(value)) return true;
- if (Array.isArray(value)) return value.some(hasUploadableValue);
- if (value && typeof value === 'object') {
- for (const k in value) {
- if (hasUploadableValue((value as any)[k])) return true;
- }
- }
- return false;
-};
-
-const addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {
- if (value === undefined) return;
- if (value == null) {
- throw new TypeError(
- `Received null for "${key}"; to pass null in FormData, you must use the string 'null'`,
- );
- }
-
- // TODO: make nested formats configurable
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
- form.append(key, String(value));
- } else if (value instanceof Response) {
- form.append(key, makeFile([await value.blob()], getName(value)));
- } else if (isAsyncIterable(value)) {
- form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value)));
- } else if (isNamedBlob(value)) {
- form.append(key, value, getName(value));
- } else if (Array.isArray(value)) {
- await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));
- } else if (typeof value === 'object') {
- await Promise.all(
- Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)),
- );
- } else {
- throw new TypeError(
- `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`,
- );
- }
-};
diff --git a/packages/sdk/src/internal/utils.ts b/packages/sdk/src/internal/utils.ts
deleted file mode 100644
index 3cbfacce2..000000000
--- a/packages/sdk/src/internal/utils.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export * from './utils/values';
-export * from './utils/base64';
-export * from './utils/env';
-export * from './utils/log';
-export * from './utils/uuid';
-export * from './utils/sleep';
diff --git a/packages/sdk/src/internal/utils/base64.ts b/packages/sdk/src/internal/utils/base64.ts
deleted file mode 100644
index 05d7bd9b4..000000000
--- a/packages/sdk/src/internal/utils/base64.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { OpencodeError } from '../../core/error';
-import { encodeUTF8 } from './bytes';
-
-export const toBase64 = (data: string | Uint8Array | null | undefined): string => {
- if (!data) return '';
-
- if (typeof (globalThis as any).Buffer !== 'undefined') {
- return (globalThis as any).Buffer.from(data).toString('base64');
- }
-
- if (typeof data === 'string') {
- data = encodeUTF8(data);
- }
-
- if (typeof btoa !== 'undefined') {
- return btoa(String.fromCharCode.apply(null, data as any));
- }
-
- throw new OpencodeError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined');
-};
-
-export const fromBase64 = (str: string): Uint8Array => {
- if (typeof (globalThis as any).Buffer !== 'undefined') {
- const buf = (globalThis as any).Buffer.from(str, 'base64');
- return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
- }
-
- if (typeof atob !== 'undefined') {
- const bstr = atob(str);
- const buf = new Uint8Array(bstr.length);
- for (let i = 0; i < bstr.length; i++) {
- buf[i] = bstr.charCodeAt(i);
- }
- return buf;
- }
-
- throw new OpencodeError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined');
-};
diff --git a/packages/sdk/src/internal/utils/bytes.ts b/packages/sdk/src/internal/utils/bytes.ts
deleted file mode 100644
index 8da627abe..000000000
--- a/packages/sdk/src/internal/utils/bytes.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-export function concatBytes(buffers: Uint8Array[]): Uint8Array {
- let length = 0;
- for (const buffer of buffers) {
- length += buffer.length;
- }
- const output = new Uint8Array(length);
- let index = 0;
- for (const buffer of buffers) {
- output.set(buffer, index);
- index += buffer.length;
- }
-
- return output;
-}
-
-let encodeUTF8_: (str: string) => Uint8Array;
-export function encodeUTF8(str: string) {
- let encoder;
- return (
- encodeUTF8_ ??
- ((encoder = new (globalThis as any).TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder)))
- )(str);
-}
-
-let decodeUTF8_: (bytes: Uint8Array) => string;
-export function decodeUTF8(bytes: Uint8Array) {
- let decoder;
- return (
- decodeUTF8_ ??
- ((decoder = new (globalThis as any).TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder)))
- )(bytes);
-}
diff --git a/packages/sdk/src/internal/utils/env.ts b/packages/sdk/src/internal/utils/env.ts
deleted file mode 100644
index 2d8480077..000000000
--- a/packages/sdk/src/internal/utils/env.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-/**
- * Read an environment variable.
- *
- * Trims beginning and trailing whitespace.
- *
- * Will return undefined if the environment variable doesn't exist or cannot be accessed.
- */
-export const readEnv = (env: string): string | undefined => {
- if (typeof (globalThis as any).process !== 'undefined') {
- return (globalThis as any).process.env?.[env]?.trim() ?? undefined;
- }
- if (typeof (globalThis as any).Deno !== 'undefined') {
- return (globalThis as any).Deno.env?.get?.(env)?.trim();
- }
- return undefined;
-};
diff --git a/packages/sdk/src/internal/utils/log.ts b/packages/sdk/src/internal/utils/log.ts
deleted file mode 100644
index 44ac16a02..000000000
--- a/packages/sdk/src/internal/utils/log.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { hasOwn } from './values';
-import { type Opencode } from '../../client';
-import { RequestOptions } from '../request-options';
-
-type LogFn = (message: string, ...rest: unknown[]) => void;
-export type Logger = {
- error: LogFn;
- warn: LogFn;
- info: LogFn;
- debug: LogFn;
-};
-export type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
-
-const levelNumbers = {
- off: 0,
- error: 200,
- warn: 300,
- info: 400,
- debug: 500,
-};
-
-export const parseLogLevel = (
- maybeLevel: string | undefined,
- sourceName: string,
- client: Opencode,
-): LogLevel | undefined => {
- if (!maybeLevel) {
- return undefined;
- }
- if (hasOwn(levelNumbers, maybeLevel)) {
- return maybeLevel;
- }
- loggerFor(client).warn(
- `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(
- Object.keys(levelNumbers),
- )}`,
- );
- return undefined;
-};
-
-function noop() {}
-
-function makeLogFn(fnLevel: keyof Logger, logger: Logger | undefined, logLevel: LogLevel) {
- if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
- return noop;
- } else {
- // Don't wrap logger functions, we want the stacktrace intact!
- return logger[fnLevel].bind(logger);
- }
-}
-
-const noopLogger = {
- error: noop,
- warn: noop,
- info: noop,
- debug: noop,
-};
-
-let cachedLoggers = /* @__PURE__ */ new WeakMap<Logger, [LogLevel, Logger]>();
-
-export function loggerFor(client: Opencode): Logger {
- const logger = client.logger;
- const logLevel = client.logLevel ?? 'off';
- if (!logger) {
- return noopLogger;
- }
-
- const cachedLogger = cachedLoggers.get(logger);
- if (cachedLogger && cachedLogger[0] === logLevel) {
- return cachedLogger[1];
- }
-
- const levelLogger = {
- error: makeLogFn('error', logger, logLevel),
- warn: makeLogFn('warn', logger, logLevel),
- info: makeLogFn('info', logger, logLevel),
- debug: makeLogFn('debug', logger, logLevel),
- };
-
- cachedLoggers.set(logger, [logLevel, levelLogger]);
-
- return levelLogger;
-}
-
-export const formatRequestDetails = (details: {
- options?: RequestOptions | undefined;
- headers?: Headers | Record<string, string> | undefined;
- retryOfRequestLogID?: string | undefined;
- retryOf?: string | undefined;
- url?: string | undefined;
- status?: number | undefined;
- method?: string | undefined;
- durationMs?: number | undefined;
- message?: unknown;
- body?: unknown;
-}) => {
- if (details.options) {
- details.options = { ...details.options };
- delete details.options['headers']; // redundant + leaks internals
- }
- if (details.headers) {
- details.headers = Object.fromEntries(
- (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(
- ([name, value]) => [
- name,
- (
- name.toLowerCase() === 'authorization' ||
- name.toLowerCase() === 'cookie' ||
- name.toLowerCase() === 'set-cookie'
- ) ?
- '***'
- : value,
- ],
- ),
- );
- }
- if ('retryOfRequestLogID' in details) {
- if (details.retryOfRequestLogID) {
- details.retryOf = details.retryOfRequestLogID;
- }
- delete details.retryOfRequestLogID;
- }
- return details;
-};
diff --git a/packages/sdk/src/internal/utils/path.ts b/packages/sdk/src/internal/utils/path.ts
deleted file mode 100644
index 6ca96e0dd..000000000
--- a/packages/sdk/src/internal/utils/path.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { OpencodeError } from '../../core/error';
-
-/**
- * Percent-encode everything that isn't safe to have in a path without encoding safe chars.
- *
- * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
- * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
- * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
- * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
- */
-export function encodeURIPath(str: string) {
- return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
-}
-
-const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
-
-export const createPathTagFunction = (pathEncoder = encodeURIPath) =>
- function path(statics: readonly string[], ...params: readonly unknown[]): string {
- // If there are no params, no processing is needed.
- if (statics.length === 1) return statics[0]!;
-
- let postPath = false;
- const invalidSegments = [];
- const path = statics.reduce((previousValue, currentValue, index) => {
- if (/[?#]/.test(currentValue)) {
- postPath = true;
- }
- const value = params[index];
- let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
- if (
- index !== params.length &&
- (value == null ||
- (typeof value === 'object' &&
- // handle values from other realms
- value.toString ===
- Object.getPrototypeOf(Object.getPrototypeOf((value as any).hasOwnProperty ?? EMPTY) ?? EMPTY)
- ?.toString))
- ) {
- encoded = value + '';
- invalidSegments.push({
- start: previousValue.length + currentValue.length,
- length: encoded.length,
- error: `Value of type ${Object.prototype.toString
- .call(value)
- .slice(8, -1)} is not a valid path parameter`,
- });
- }
- return previousValue + currentValue + (index === params.length ? '' : encoded);
- }, '');
-
- const pathOnly = path.split(/[?#]/, 1)[0]!;
- const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
- let match;
-
- // Find all invalid segments
- while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
- invalidSegments.push({
- start: match.index,
- length: match[0].length,
- error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
- });
- }
-
- invalidSegments.sort((a, b) => a.start - b.start);
-
- if (invalidSegments.length > 0) {
- let lastEnd = 0;
- const underline = invalidSegments.reduce((acc, segment) => {
- const spaces = ' '.repeat(segment.start - lastEnd);
- const arrows = '^'.repeat(segment.length);
- lastEnd = segment.start + segment.length;
- return acc + spaces + arrows;
- }, '');
-
- throw new OpencodeError(
- `Path parameters result in path with invalid segments:\n${invalidSegments
- .map((e) => e.error)
- .join('\n')}\n${path}\n${underline}`,
- );
- }
-
- return path;
- };
-
-/**
- * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
- */
-export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
diff --git a/packages/sdk/src/internal/utils/sleep.ts b/packages/sdk/src/internal/utils/sleep.ts
deleted file mode 100644
index 65e52962b..000000000
--- a/packages/sdk/src/internal/utils/sleep.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
diff --git a/packages/sdk/src/internal/utils/uuid.ts b/packages/sdk/src/internal/utils/uuid.ts
deleted file mode 100644
index b0e53aaf7..000000000
--- a/packages/sdk/src/internal/utils/uuid.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-/**
- * https://stackoverflow.com/a/2117523
- */
-export let uuid4 = function () {
- const { crypto } = globalThis as any;
- if (crypto?.randomUUID) {
- uuid4 = crypto.randomUUID.bind(crypto);
- return crypto.randomUUID();
- }
- const u8 = new Uint8Array(1);
- const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff;
- return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
- (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16),
- );
-};
diff --git a/packages/sdk/src/internal/utils/values.ts b/packages/sdk/src/internal/utils/values.ts
deleted file mode 100644
index b2421fd88..000000000
--- a/packages/sdk/src/internal/utils/values.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { OpencodeError } from '../../core/error';
-
-// https://url.spec.whatwg.org/#url-scheme-string
-const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
-
-export const isAbsoluteURL = (url: string): boolean => {
- return startsWithSchemeRegexp.test(url);
-};
-
-export let isArray = (val: unknown): val is unknown[] => ((isArray = Array.isArray), isArray(val));
-export let isReadonlyArray = isArray as (val: unknown) => val is readonly unknown[];
-
-/** Returns an object if the given value isn't an object, otherwise returns as-is */
-export function maybeObj(x: unknown): object {
- if (typeof x !== 'object') {
- return {};
- }
-
- return x ?? {};
-}
-
-// https://stackoverflow.com/a/34491287
-export function isEmptyObj(obj: Object | null | undefined): boolean {
- if (!obj) return true;
- for (const _k in obj) return false;
- return true;
-}
-
-// https://eslint.org/docs/latest/rules/no-prototype-builtins
-export function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T {
- return Object.prototype.hasOwnProperty.call(obj, key);
-}
-
-export function isObj(obj: unknown): obj is Record<string, unknown> {
- return obj != null && typeof obj === 'object' && !Array.isArray(obj);
-}
-
-export const ensurePresent = <T>(value: T | null | undefined): T => {
- if (value == null) {
- throw new OpencodeError(`Expected a value to be given but received ${value} instead.`);
- }
-
- return value;
-};
-
-export const validatePositiveInteger = (name: string, n: unknown): number => {
- if (typeof n !== 'number' || !Number.isInteger(n)) {
- throw new OpencodeError(`${name} must be an integer`);
- }
- if (n < 0) {
- throw new OpencodeError(`${name} must be a positive integer`);
- }
- return n;
-};
-
-export const coerceInteger = (value: unknown): number => {
- if (typeof value === 'number') return Math.round(value);
- if (typeof value === 'string') return parseInt(value, 10);
-
- throw new OpencodeError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
-};
-
-export const coerceFloat = (value: unknown): number => {
- if (typeof value === 'number') return value;
- if (typeof value === 'string') return parseFloat(value);
-
- throw new OpencodeError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
-};
-
-export const coerceBoolean = (value: unknown): boolean => {
- if (typeof value === 'boolean') return value;
- if (typeof value === 'string') return value === 'true';
- return Boolean(value);
-};
-
-export const maybeCoerceInteger = (value: unknown): number | undefined => {
- if (value === undefined) {
- return undefined;
- }
- return coerceInteger(value);
-};
-
-export const maybeCoerceFloat = (value: unknown): number | undefined => {
- if (value === undefined) {
- return undefined;
- }
- return coerceFloat(value);
-};
-
-export const maybeCoerceBoolean = (value: unknown): boolean | undefined => {
- if (value === undefined) {
- return undefined;
- }
- return coerceBoolean(value);
-};
-
-export const safeJSON = (text: string) => {
- try {
- return JSON.parse(text);
- } catch (err) {
- return undefined;
- }
-};
diff --git a/packages/sdk/src/resource.ts b/packages/sdk/src/resource.ts
deleted file mode 100644
index 363e3516b..000000000
--- a/packages/sdk/src/resource.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/** @deprecated Import from ./core/resource instead */
-export * from './core/resource';
diff --git a/packages/sdk/src/resources.ts b/packages/sdk/src/resources.ts
deleted file mode 100644
index b283d5781..000000000
--- a/packages/sdk/src/resources.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './resources/index';
diff --git a/packages/sdk/src/resources/app.ts b/packages/sdk/src/resources/app.ts
deleted file mode 100644
index 8ee56e320..000000000
--- a/packages/sdk/src/resources/app.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class AppResource extends APIResource {
- /**
- * Get app info
- */
- get(options?: RequestOptions): APIPromise<App> {
- return this._client.get('/app', options);
- }
-
- /**
- * Initialize the app
- */
- init(options?: RequestOptions): APIPromise<AppInitResponse> {
- return this._client.post('/app/init', options);
- }
-
- /**
- * Write a log entry to the server logs
- */
- log(body: AppLogParams, options?: RequestOptions): APIPromise<AppLogResponse> {
- return this._client.post('/log', { body, ...options });
- }
-
- /**
- * List all modes
- */
- modes(options?: RequestOptions): APIPromise<AppModesResponse> {
- return this._client.get('/mode', options);
- }
-
- /**
- * List all providers
- */
- providers(options?: RequestOptions): APIPromise<AppProvidersResponse> {
- return this._client.get('/config/providers', options);
- }
-}
-
-export interface App {
- git: boolean;
-
- hostname: string;
-
- path: App.Path;
-
- time: App.Time;
-}
-
-export namespace App {
- export interface Path {
- config: string;
-
- cwd: string;
-
- data: string;
-
- root: string;
-
- state: string;
- }
-
- export interface Time {
- initialized?: number;
- }
-}
-
-export interface Mode {
- name: string;
-
- tools: { [key: string]: boolean };
-
- model?: Mode.Model;
-
- prompt?: string;
-
- temperature?: number;
-}
-
-export namespace Mode {
- export interface Model {
- modelID: string;
-
- providerID: string;
- }
-}
-
-export interface Model {
- id: string;
-
- attachment: boolean;
-
- cost: Model.Cost;
-
- limit: Model.Limit;
-
- name: string;
-
- options: { [key: string]: unknown };
-
- reasoning: boolean;
-
- release_date: string;
-
- temperature: boolean;
-
- tool_call: boolean;
-}
-
-export namespace Model {
- export interface Cost {
- input: number;
-
- output: number;
-
- cache_read?: number;
-
- cache_write?: number;
- }
-
- export interface Limit {
- context: number;
-
- output: number;
- }
-}
-
-export interface Provider {
- id: string;
-
- env: Array<string>;
-
- models: { [key: string]: Model };
-
- name: string;
-
- api?: string;
-
- npm?: string;
-}
-
-export type AppInitResponse = boolean;
-
-export type AppLogResponse = boolean;
-
-export type AppModesResponse = Array<Mode>;
-
-export interface AppProvidersResponse {
- default: { [key: string]: string };
-
- providers: Array<Provider>;
-}
-
-export interface AppLogParams {
- /**
- * Log level
- */
- level: 'debug' | 'info' | 'error' | 'warn';
-
- /**
- * Log message
- */
- message: string;
-
- /**
- * Service name for the log entry
- */
- service: string;
-
- /**
- * Additional metadata for the log entry
- */
- extra?: { [key: string]: unknown };
-}
-
-export declare namespace AppResource {
- export {
- type App as App,
- type Mode as Mode,
- type Model as Model,
- type Provider as Provider,
- type AppInitResponse as AppInitResponse,
- type AppLogResponse as AppLogResponse,
- type AppModesResponse as AppModesResponse,
- type AppProvidersResponse as AppProvidersResponse,
- type AppLogParams as AppLogParams,
- };
-}
diff --git a/packages/sdk/src/resources/config.ts b/packages/sdk/src/resources/config.ts
deleted file mode 100644
index 11592f4aa..000000000
--- a/packages/sdk/src/resources/config.ts
+++ /dev/null
@@ -1,492 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import * as ConfigAPI from './config';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class ConfigResource extends APIResource {
- /**
- * Get config info
- */
- get(options?: RequestOptions): APIPromise<Config> {
- return this._client.get('/config', options);
- }
-}
-
-export interface Config {
- /**
- * JSON schema reference for configuration validation
- */
- $schema?: string;
-
- /**
- * Modes configuration, see https://opencode.ai/docs/modes
- */
- agent?: Config.Agent;
-
- /**
- * @deprecated Use 'share' field instead. Share newly created sessions
- * automatically
- */
- autoshare?: boolean;
-
- /**
- * Automatically update to the latest version
- */
- autoupdate?: boolean;
-
- /**
- * Disable providers that are loaded automatically
- */
- disabled_providers?: Array<string>;
-
- experimental?: Config.Experimental;
-
- /**
- * Additional instruction files or patterns to include
- */
- instructions?: Array<string>;
-
- /**
- * Custom keybind configurations
- */
- keybinds?: KeybindsConfig;
-
- /**
- * @deprecated Always uses stretch layout.
- */
- layout?: 'auto' | 'stretch';
-
- /**
- * MCP (Model Context Protocol) server configurations
- */
- mcp?: { [key: string]: McpLocalConfig | McpRemoteConfig };
-
- /**
- * Modes configuration, see https://opencode.ai/docs/modes
- */
- mode?: Config.Mode;
-
- /**
- * Model to use in the format of provider/model, eg anthropic/claude-2
- */
- model?: string;
-
- /**
- * Custom provider configurations and model overrides
- */
- provider?: { [key: string]: Config.Provider };
-
- /**
- * Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
- * enables automatic sharing, 'disabled' disables all sharing
- */
- share?: 'manual' | 'auto' | 'disabled';
-
- /**
- * Small model to use for tasks like summarization and title generation in the
- * format of provider/model
- */
- small_model?: string;
-
- /**
- * Theme name to use for the interface
- */
- theme?: string;
-
- /**
- * Custom username to display in conversations instead of system username
- */
- username?: string;
-}
-
-export namespace Config {
- /**
- * Modes configuration, see https://opencode.ai/docs/modes
- */
- export interface Agent {
- general?: Agent.General;
-
- [k: string]: Agent.AgentConfig | undefined;
- }
-
- export namespace Agent {
- export interface General extends ConfigAPI.ModeConfig {
- description: string;
- }
-
- export interface AgentConfig extends ConfigAPI.ModeConfig {
- description: string;
- }
- }
-
- export interface AgentConfig extends ConfigAPI.ModeConfig {
- description: string;
- }
-
- export interface AgentConfig extends ConfigAPI.ModeConfig {
- description: string;
- }
-
- export interface Experimental {
- hook?: Experimental.Hook;
- }
-
- export namespace Experimental {
- export interface Hook {
- file_edited?: { [key: string]: Array<Hook.FileEdited> };
-
- session_completed?: Array<Hook.SessionCompleted>;
- }
-
- export namespace Hook {
- export interface FileEdited {
- command: Array<string>;
-
- environment?: { [key: string]: string };
- }
-
- export interface SessionCompleted {
- command: Array<string>;
-
- environment?: { [key: string]: string };
- }
- }
- }
-
- /**
- * Modes configuration, see https://opencode.ai/docs/modes
- */
- export interface Mode {
- build?: ConfigAPI.ModeConfig;
-
- plan?: ConfigAPI.ModeConfig;
-
- [k: string]: ConfigAPI.ModeConfig | undefined;
- }
-
- export interface Provider {
- models: { [key: string]: Provider.Models };
-
- id?: string;
-
- api?: string;
-
- env?: Array<string>;
-
- name?: string;
-
- npm?: string;
-
- options?: Provider.Options;
- }
-
- export namespace Provider {
- export interface Models {
- id?: string;
-
- attachment?: boolean;
-
- cost?: Models.Cost;
-
- limit?: Models.Limit;
-
- name?: string;
-
- options?: { [key: string]: unknown };
-
- reasoning?: boolean;
-
- release_date?: string;
-
- temperature?: boolean;
-
- tool_call?: boolean;
- }
-
- export namespace Models {
- export interface Cost {
- input: number;
-
- output: number;
-
- cache_read?: number;
-
- cache_write?: number;
- }
-
- export interface Limit {
- context: number;
-
- output: number;
- }
- }
-
- export interface Options {
- apiKey?: string;
-
- baseURL?: string;
-
- [k: string]: unknown;
- }
- }
-}
-
-export interface KeybindsConfig {
- /**
- * Exit the application
- */
- app_exit: string;
-
- /**
- * Show help dialog
- */
- app_help: string;
-
- /**
- * Open external editor
- */
- editor_open: string;
-
- /**
- * Close file
- */
- file_close: string;
-
- /**
- * Split/unified diff
- */
- file_diff_toggle: string;
-
- /**
- * List files
- */
- file_list: string;
-
- /**
- * Search file
- */
- file_search: string;
-
- /**
- * Clear input field
- */
- input_clear: string;
-
- /**
- * Insert newline in input
- */
- input_newline: string;
-
- /**
- * Paste from clipboard
- */
- input_paste: string;
-
- /**
- * Submit input
- */
- input_submit: string;
-
- /**
- * Leader key for keybind combinations
- */
- leader: string;
-
- /**
- * Copy message
- */
- messages_copy: string;
-
- /**
- * Navigate to first message
- */
- messages_first: string;
-
- /**
- * Scroll messages down by half page
- */
- messages_half_page_down: string;
-
- /**
- * Scroll messages up by half page
- */
- messages_half_page_up: string;
-
- /**
- * Navigate to last message
- */
- messages_last: string;
-
- /**
- * Toggle layout
- */
- messages_layout_toggle: string;
-
- /**
- * Navigate to next message
- */
- messages_next: string;
-
- /**
- * Scroll messages down by one page
- */
- messages_page_down: string;
-
- /**
- * Scroll messages up by one page
- */
- messages_page_up: string;
-
- /**
- * Navigate to previous message
- */
- messages_previous: string;
-
- /**
- * Redo message
- */
- messages_redo: string;
-
- /**
- * @deprecated use messages_undo. Revert message
- */
- messages_revert: string;
-
- /**
- * Undo message
- */
- messages_undo: string;
-
- /**
- * List available models
- */
- model_list: string;
-
- /**
- * Create/update AGENTS.md
- */
- project_init: string;
-
- /**
- * Compact the session
- */
- session_compact: string;
-
- /**
- * Export session to editor
- */
- session_export: string;
-
- /**
- * Interrupt current session
- */
- session_interrupt: string;
-
- /**
- * List all sessions
- */
- session_list: string;
-
- /**
- * Create a new session
- */
- session_new: string;
-
- /**
- * Share current session
- */
- session_share: string;
-
- /**
- * Unshare current session
- */
- session_unshare: string;
-
- /**
- * Next mode
- */
- switch_mode: string;
-
- /**
- * Previous Mode
- */
- switch_mode_reverse: string;
-
- /**
- * List available themes
- */
- theme_list: string;
-
- /**
- * Toggle tool details
- */
- tool_details: string;
-}
-
-export interface McpLocalConfig {
- /**
- * Command and arguments to run the MCP server
- */
- command: Array<string>;
-
- /**
- * Type of MCP server connection
- */
- type: 'local';
-
- /**
- * Enable or disable the MCP server on startup
- */
- enabled?: boolean;
-
- /**
- * Environment variables to set when running the MCP server
- */
- environment?: { [key: string]: string };
-}
-
-export interface McpRemoteConfig {
- /**
- * Type of MCP server connection
- */
- type: 'remote';
-
- /**
- * URL of the remote MCP server
- */
- url: string;
-
- /**
- * Enable or disable the MCP server on startup
- */
- enabled?: boolean;
-
- /**
- * Headers to send with the request
- */
- headers?: { [key: string]: string };
-}
-
-export interface ModeConfig {
- disable?: boolean;
-
- model?: string;
-
- prompt?: string;
-
- temperature?: number;
-
- tools?: { [key: string]: boolean };
-}
-
-export declare namespace ConfigResource {
- export {
- type Config as Config,
- type KeybindsConfig as KeybindsConfig,
- type McpLocalConfig as McpLocalConfig,
- type McpRemoteConfig as McpRemoteConfig,
- type ModeConfig as ModeConfig,
- };
-}
diff --git a/packages/sdk/src/resources/event.ts b/packages/sdk/src/resources/event.ts
deleted file mode 100644
index bd51b22b3..000000000
--- a/packages/sdk/src/resources/event.ts
+++ /dev/null
@@ -1,267 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import * as SessionAPI from './session';
-import * as Shared from './shared';
-import { APIPromise } from '../core/api-promise';
-import { Stream } from '../core/streaming';
-import { RequestOptions } from '../internal/request-options';
-
-export class Event extends APIResource {
- /**
- * Get events
- */
- list(options?: RequestOptions): APIPromise<Stream<EventListResponse>> {
- return this._client.get('/event', { ...options, stream: true }) as APIPromise<Stream<EventListResponse>>;
- }
-}
-
-export type EventListResponse =
- | EventListResponse.EventInstallationUpdated
- | EventListResponse.EventLspClientDiagnostics
- | EventListResponse.EventMessageUpdated
- | EventListResponse.EventMessageRemoved
- | EventListResponse.EventMessagePartUpdated
- | EventListResponse.EventMessagePartRemoved
- | EventListResponse.EventStorageWrite
- | EventListResponse.EventPermissionUpdated
- | EventListResponse.EventFileEdited
- | EventListResponse.EventSessionUpdated
- | EventListResponse.EventSessionDeleted
- | EventListResponse.EventSessionIdle
- | EventListResponse.EventSessionError
- | EventListResponse.EventServerConnected
- | EventListResponse.EventFileWatcherUpdated
- | EventListResponse.EventIdeInstalled;
-
-export namespace EventListResponse {
- export interface EventInstallationUpdated {
- properties: EventInstallationUpdated.Properties;
-
- type: 'installation.updated';
- }
-
- export namespace EventInstallationUpdated {
- export interface Properties {
- version: string;
- }
- }
-
- export interface EventLspClientDiagnostics {
- properties: EventLspClientDiagnostics.Properties;
-
- type: 'lsp.client.diagnostics';
- }
-
- export namespace EventLspClientDiagnostics {
- export interface Properties {
- path: string;
-
- serverID: string;
- }
- }
-
- export interface EventMessageUpdated {
- properties: EventMessageUpdated.Properties;
-
- type: 'message.updated';
- }
-
- export namespace EventMessageUpdated {
- export interface Properties {
- info: SessionAPI.Message;
- }
- }
-
- export interface EventMessageRemoved {
- properties: EventMessageRemoved.Properties;
-
- type: 'message.removed';
- }
-
- export namespace EventMessageRemoved {
- export interface Properties {
- messageID: string;
-
- sessionID: string;
- }
- }
-
- export interface EventMessagePartUpdated {
- properties: EventMessagePartUpdated.Properties;
-
- type: 'message.part.updated';
- }
-
- export namespace EventMessagePartUpdated {
- export interface Properties {
- part: SessionAPI.Part;
- }
- }
-
- export interface EventMessagePartRemoved {
- properties: EventMessagePartRemoved.Properties;
-
- type: 'message.part.removed';
- }
-
- export namespace EventMessagePartRemoved {
- export interface Properties {
- messageID: string;
-
- partID: string;
-
- sessionID: string;
- }
- }
-
- export interface EventStorageWrite {
- properties: EventStorageWrite.Properties;
-
- type: 'storage.write';
- }
-
- export namespace EventStorageWrite {
- export interface Properties {
- key: string;
-
- content?: unknown;
- }
- }
-
- export interface EventPermissionUpdated {
- properties: EventPermissionUpdated.Properties;
-
- type: 'permission.updated';
- }
-
- export namespace EventPermissionUpdated {
- export interface Properties {
- id: string;
-
- metadata: { [key: string]: unknown };
-
- sessionID: string;
-
- time: Properties.Time;
-
- title: string;
- }
-
- export namespace Properties {
- export interface Time {
- created: number;
- }
- }
- }
-
- export interface EventFileEdited {
- properties: EventFileEdited.Properties;
-
- type: 'file.edited';
- }
-
- export namespace EventFileEdited {
- export interface Properties {
- file: string;
- }
- }
-
- export interface EventSessionUpdated {
- properties: EventSessionUpdated.Properties;
-
- type: 'session.updated';
- }
-
- export namespace EventSessionUpdated {
- export interface Properties {
- info: SessionAPI.Session;
- }
- }
-
- export interface EventSessionDeleted {
- properties: EventSessionDeleted.Properties;
-
- type: 'session.deleted';
- }
-
- export namespace EventSessionDeleted {
- export interface Properties {
- info: SessionAPI.Session;
- }
- }
-
- export interface EventSessionIdle {
- properties: EventSessionIdle.Properties;
-
- type: 'session.idle';
- }
-
- export namespace EventSessionIdle {
- export interface Properties {
- sessionID: string;
- }
- }
-
- export interface EventSessionError {
- properties: EventSessionError.Properties;
-
- type: 'session.error';
- }
-
- export namespace EventSessionError {
- export interface Properties {
- error?:
- | Shared.ProviderAuthError
- | Shared.UnknownError
- | Properties.MessageOutputLengthError
- | Shared.MessageAbortedError;
-
- sessionID?: string;
- }
-
- export namespace Properties {
- export interface MessageOutputLengthError {
- data: unknown;
-
- name: 'MessageOutputLengthError';
- }
- }
- }
-
- export interface EventServerConnected {
- properties: unknown;
-
- type: 'server.connected';
- }
-
- export interface EventFileWatcherUpdated {
- properties: EventFileWatcherUpdated.Properties;
-
- type: 'file.watcher.updated';
- }
-
- export namespace EventFileWatcherUpdated {
- export interface Properties {
- event: 'rename' | 'change';
-
- file: string;
- }
- }
-
- export interface EventIdeInstalled {
- properties: EventIdeInstalled.Properties;
-
- type: 'ide.installed';
- }
-
- export namespace EventIdeInstalled {
- export interface Properties {
- ide: string;
- }
- }
-}
-
-export declare namespace Event {
- export { type EventListResponse as EventListResponse };
-}
diff --git a/packages/sdk/src/resources/file.ts b/packages/sdk/src/resources/file.ts
deleted file mode 100644
index fd7bdac69..000000000
--- a/packages/sdk/src/resources/file.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class FileResource extends APIResource {
- /**
- * Read a file
- */
- read(query: FileReadParams, options?: RequestOptions): APIPromise<FileReadResponse> {
- return this._client.get('/file', { query, ...options });
- }
-
- /**
- * Get file status
- */
- status(options?: RequestOptions): APIPromise<FileStatusResponse> {
- return this._client.get('/file/status', options);
- }
-}
-
-export interface File {
- added: number;
-
- path: string;
-
- removed: number;
-
- status: 'added' | 'deleted' | 'modified';
-}
-
-export interface FileReadResponse {
- content: string;
-
- type: 'raw' | 'patch';
-}
-
-export type FileStatusResponse = Array<File>;
-
-export interface FileReadParams {
- path: string;
-}
-
-export declare namespace FileResource {
- export {
- type File as File,
- type FileReadResponse as FileReadResponse,
- type FileStatusResponse as FileStatusResponse,
- type FileReadParams as FileReadParams,
- };
-}
diff --git a/packages/sdk/src/resources/find.ts b/packages/sdk/src/resources/find.ts
deleted file mode 100644
index d9d6597e5..000000000
--- a/packages/sdk/src/resources/find.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class Find extends APIResource {
- /**
- * Find files
- */
- files(query: FindFilesParams, options?: RequestOptions): APIPromise<FindFilesResponse> {
- return this._client.get('/find/file', { query, ...options });
- }
-
- /**
- * Find workspace symbols
- */
- symbols(query: FindSymbolsParams, options?: RequestOptions): APIPromise<FindSymbolsResponse> {
- return this._client.get('/find/symbol', { query, ...options });
- }
-
- /**
- * Find text in files
- */
- text(query: FindTextParams, options?: RequestOptions): APIPromise<FindTextResponse> {
- return this._client.get('/find', { query, ...options });
- }
-}
-
-export interface Symbol {
- kind: number;
-
- location: Symbol.Location;
-
- name: string;
-}
-
-export namespace Symbol {
- export interface Location {
- range: Location.Range;
-
- uri: string;
- }
-
- export namespace Location {
- export interface Range {
- end: Range.End;
-
- start: Range.Start;
- }
-
- export namespace Range {
- export interface End {
- character: number;
-
- line: number;
- }
-
- export interface Start {
- character: number;
-
- line: number;
- }
- }
- }
-}
-
-export type FindFilesResponse = Array<string>;
-
-export type FindSymbolsResponse = Array<Symbol>;
-
-export type FindTextResponse = Array<FindTextResponse.FindTextResponseItem>;
-
-export namespace FindTextResponse {
- export interface FindTextResponseItem {
- absolute_offset: number;
-
- line_number: number;
-
- lines: FindTextResponseItem.Lines;
-
- path: FindTextResponseItem.Path;
-
- submatches: Array<FindTextResponseItem.Submatch>;
- }
-
- export namespace FindTextResponseItem {
- export interface Lines {
- text: string;
- }
-
- export interface Path {
- text: string;
- }
-
- export interface Submatch {
- end: number;
-
- match: Submatch.Match;
-
- start: number;
- }
-
- export namespace Submatch {
- export interface Match {
- text: string;
- }
- }
- }
-}
-
-export interface FindFilesParams {
- query: string;
-}
-
-export interface FindSymbolsParams {
- query: string;
-}
-
-export interface FindTextParams {
- pattern: string;
-}
-
-export declare namespace Find {
- export {
- type Symbol as Symbol,
- type FindFilesResponse as FindFilesResponse,
- type FindSymbolsResponse as FindSymbolsResponse,
- type FindTextResponse as FindTextResponse,
- type FindFilesParams as FindFilesParams,
- type FindSymbolsParams as FindSymbolsParams,
- type FindTextParams as FindTextParams,
- };
-}
diff --git a/packages/sdk/src/resources/index.ts b/packages/sdk/src/resources/index.ts
deleted file mode 100644
index 4e7934af1..000000000
--- a/packages/sdk/src/resources/index.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export * from './shared';
-export {
- AppResource,
- type App,
- type Mode,
- type Model,
- type Provider,
- type AppInitResponse,
- type AppLogResponse,
- type AppModesResponse,
- type AppProvidersResponse,
- type AppLogParams,
-} from './app';
-export {
- ConfigResource,
- type Config,
- type KeybindsConfig,
- type McpLocalConfig,
- type McpRemoteConfig,
- type ModeConfig,
-} from './config';
-export { Event, type EventListResponse } from './event';
-export {
- FileResource,
- type File,
- type FileReadResponse,
- type FileStatusResponse,
- type FileReadParams,
-} from './file';
-export {
- Find,
- type Symbol,
- type FindFilesResponse,
- type FindSymbolsResponse,
- type FindTextResponse,
- type FindFilesParams,
- type FindSymbolsParams,
- type FindTextParams,
-} from './find';
-export {
- SessionResource,
- type AssistantMessage,
- type FilePart,
- type FilePartInput,
- type FilePartSource,
- type FilePartSourceText,
- type FileSource,
- type Message,
- type Part,
- type Session,
- type SnapshotPart,
- type StepFinishPart,
- type StepStartPart,
- type SymbolSource,
- type TextPart,
- type TextPartInput,
- type ToolPart,
- type ToolStateCompleted,
- type ToolStateError,
- type ToolStatePending,
- type ToolStateRunning,
- type UserMessage,
- type SessionListResponse,
- type SessionDeleteResponse,
- type SessionAbortResponse,
- type SessionInitResponse,
- type SessionMessagesResponse,
- type SessionSummarizeResponse,
- type SessionChatParams,
- type SessionInitParams,
- type SessionRevertParams,
- type SessionSummarizeParams,
-} from './session';
-export {
- Tui,
- type TuiAppendPromptResponse,
- type TuiOpenHelpResponse,
- type TuiAppendPromptParams,
-} from './tui';
diff --git a/packages/sdk/src/resources/session.ts b/packages/sdk/src/resources/session.ts
deleted file mode 100644
index 5dbdc31f8..000000000
--- a/packages/sdk/src/resources/session.ts
+++ /dev/null
@@ -1,605 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import * as SessionAPI from './session';
-import * as Shared from './shared';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-import { path } from '../internal/utils/path';
-
-export class SessionResource extends APIResource {
- /**
- * Create a new session
- */
- create(options?: RequestOptions): APIPromise<Session> {
- return this._client.post('/session', options);
- }
-
- /**
- * List all sessions
- */
- list(options?: RequestOptions): APIPromise<SessionListResponse> {
- return this._client.get('/session', options);
- }
-
- /**
- * Delete a session and all its data
- */
- delete(id: string, options?: RequestOptions): APIPromise<SessionDeleteResponse> {
- return this._client.delete(path`/session/${id}`, options);
- }
-
- /**
- * Abort a session
- */
- abort(id: string, options?: RequestOptions): APIPromise<SessionAbortResponse> {
- return this._client.post(path`/session/${id}/abort`, options);
- }
-
- /**
- * Create and send a new message to a session
- */
- chat(id: string, body: SessionChatParams, options?: RequestOptions): APIPromise<AssistantMessage> {
- return this._client.post(path`/session/${id}/message`, { body, ...options });
- }
-
- /**
- * Analyze the app and create an AGENTS.md file
- */
- init(id: string, body: SessionInitParams, options?: RequestOptions): APIPromise<SessionInitResponse> {
- return this._client.post(path`/session/${id}/init`, { body, ...options });
- }
-
- /**
- * List messages for a session
- */
- messages(id: string, options?: RequestOptions): APIPromise<SessionMessagesResponse> {
- return this._client.get(path`/session/${id}/message`, options);
- }
-
- /**
- * Revert a message
- */
- revert(id: string, body: SessionRevertParams, options?: RequestOptions): APIPromise<Session> {
- return this._client.post(path`/session/${id}/revert`, { body, ...options });
- }
-
- /**
- * Share a session
- */
- share(id: string, options?: RequestOptions): APIPromise<Session> {
- return this._client.post(path`/session/${id}/share`, options);
- }
-
- /**
- * Summarize the session
- */
- summarize(
- id: string,
- body: SessionSummarizeParams,
- options?: RequestOptions,
- ): APIPromise<SessionSummarizeResponse> {
- return this._client.post(path`/session/${id}/summarize`, { body, ...options });
- }
-
- /**
- * Restore all reverted messages
- */
- unrevert(id: string, options?: RequestOptions): APIPromise<Session> {
- return this._client.post(path`/session/${id}/unrevert`, options);
- }
-
- /**
- * Unshare the session
- */
- unshare(id: string, options?: RequestOptions): APIPromise<Session> {
- return this._client.delete(path`/session/${id}/share`, options);
- }
-}
-
-export interface AssistantMessage {
- id: string;
-
- cost: number;
-
- mode: string;
-
- modelID: string;
-
- path: AssistantMessage.Path;
-
- providerID: string;
-
- role: 'assistant';
-
- sessionID: string;
-
- system: Array<string>;
-
- time: AssistantMessage.Time;
-
- tokens: AssistantMessage.Tokens;
-
- error?:
- | Shared.ProviderAuthError
- | Shared.UnknownError
- | AssistantMessage.MessageOutputLengthError
- | Shared.MessageAbortedError;
-
- summary?: boolean;
-}
-
-export namespace AssistantMessage {
- export interface Path {
- cwd: string;
-
- root: string;
- }
-
- export interface Time {
- created: number;
-
- completed?: number;
- }
-
- export interface Tokens {
- cache: Tokens.Cache;
-
- input: number;
-
- output: number;
-
- reasoning: number;
- }
-
- export namespace Tokens {
- export interface Cache {
- read: number;
-
- write: number;
- }
- }
-
- export interface MessageOutputLengthError {
- data: unknown;
-
- name: 'MessageOutputLengthError';
- }
-}
-
-export interface FilePart {
- id: string;
-
- messageID: string;
-
- mime: string;
-
- sessionID: string;
-
- type: 'file';
-
- url: string;
-
- filename?: string;
-
- source?: FilePartSource;
-}
-
-export interface FilePartInput {
- mime: string;
-
- type: 'file';
-
- url: string;
-
- id?: string;
-
- filename?: string;
-
- source?: FilePartSource;
-}
-
-export type FilePartSource = FileSource | SymbolSource;
-
-export interface FilePartSourceText {
- end: number;
-
- start: number;
-
- value: string;
-}
-
-export interface FileSource {
- path: string;
-
- text: FilePartSourceText;
-
- type: 'file';
-}
-
-export type Message = UserMessage | AssistantMessage;
-
-export type Part =
- | TextPart
- | FilePart
- | ToolPart
- | StepStartPart
- | StepFinishPart
- | SnapshotPart
- | Part.PatchPart;
-
-export namespace Part {
- export interface PatchPart {
- id: string;
-
- files: Array<string>;
-
- hash: string;
-
- messageID: string;
-
- sessionID: string;
-
- type: 'patch';
- }
-}
-
-export interface Session {
- id: string;
-
- time: Session.Time;
-
- title: string;
-
- version: string;
-
- parentID?: string;
-
- revert?: Session.Revert;
-
- share?: Session.Share;
-}
-
-export namespace Session {
- export interface Time {
- created: number;
-
- updated: number;
- }
-
- export interface Revert {
- messageID: string;
-
- diff?: string;
-
- partID?: string;
-
- snapshot?: string;
- }
-
- export interface Share {
- url: string;
- }
-}
-
-export interface SnapshotPart {
- id: string;
-
- messageID: string;
-
- sessionID: string;
-
- snapshot: string;
-
- type: 'snapshot';
-}
-
-export interface StepFinishPart {
- id: string;
-
- cost: number;
-
- messageID: string;
-
- sessionID: string;
-
- tokens: StepFinishPart.Tokens;
-
- type: 'step-finish';
-}
-
-export namespace StepFinishPart {
- export interface Tokens {
- cache: Tokens.Cache;
-
- input: number;
-
- output: number;
-
- reasoning: number;
- }
-
- export namespace Tokens {
- export interface Cache {
- read: number;
-
- write: number;
- }
- }
-}
-
-export interface StepStartPart {
- id: string;
-
- messageID: string;
-
- sessionID: string;
-
- type: 'step-start';
-}
-
-export interface SymbolSource {
- kind: number;
-
- name: string;
-
- path: string;
-
- range: SymbolSource.Range;
-
- text: FilePartSourceText;
-
- type: 'symbol';
-}
-
-export namespace SymbolSource {
- export interface Range {
- end: Range.End;
-
- start: Range.Start;
- }
-
- export namespace Range {
- export interface End {
- character: number;
-
- line: number;
- }
-
- export interface Start {
- character: number;
-
- line: number;
- }
- }
-}
-
-export interface TextPart {
- id: string;
-
- messageID: string;
-
- sessionID: string;
-
- text: string;
-
- type: 'text';
-
- synthetic?: boolean;
-
- time?: TextPart.Time;
-}
-
-export namespace TextPart {
- export interface Time {
- start: number;
-
- end?: number;
- }
-}
-
-export interface TextPartInput {
- text: string;
-
- type: 'text';
-
- id?: string;
-
- synthetic?: boolean;
-
- time?: TextPartInput.Time;
-}
-
-export namespace TextPartInput {
- export interface Time {
- start: number;
-
- end?: number;
- }
-}
-
-export interface ToolPart {
- id: string;
-
- callID: string;
-
- messageID: string;
-
- sessionID: string;
-
- state: ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError;
-
- tool: string;
-
- type: 'tool';
-}
-
-export interface ToolStateCompleted {
- input: { [key: string]: unknown };
-
- metadata: { [key: string]: unknown };
-
- output: string;
-
- status: 'completed';
-
- time: ToolStateCompleted.Time;
-
- title: string;
-}
-
-export namespace ToolStateCompleted {
- export interface Time {
- end: number;
-
- start: number;
- }
-}
-
-export interface ToolStateError {
- error: string;
-
- input: { [key: string]: unknown };
-
- status: 'error';
-
- time: ToolStateError.Time;
-}
-
-export namespace ToolStateError {
- export interface Time {
- end: number;
-
- start: number;
- }
-}
-
-export interface ToolStatePending {
- status: 'pending';
-}
-
-export interface ToolStateRunning {
- status: 'running';
-
- time: ToolStateRunning.Time;
-
- input?: unknown;
-
- metadata?: { [key: string]: unknown };
-
- title?: string;
-}
-
-export namespace ToolStateRunning {
- export interface Time {
- start: number;
- }
-}
-
-export interface UserMessage {
- id: string;
-
- role: 'user';
-
- sessionID: string;
-
- time: UserMessage.Time;
-}
-
-export namespace UserMessage {
- export interface Time {
- created: number;
- }
-}
-
-export type SessionListResponse = Array<Session>;
-
-export type SessionDeleteResponse = boolean;
-
-export type SessionAbortResponse = boolean;
-
-export type SessionInitResponse = boolean;
-
-export type SessionMessagesResponse = Array<SessionMessagesResponse.SessionMessagesResponseItem>;
-
-export namespace SessionMessagesResponse {
- export interface SessionMessagesResponseItem {
- info: SessionAPI.Message;
-
- parts: Array<SessionAPI.Part>;
- }
-}
-
-export type SessionSummarizeResponse = boolean;
-
-export interface SessionChatParams {
- modelID: string;
-
- parts: Array<TextPartInput | FilePartInput>;
-
- providerID: string;
-
- messageID?: string;
-
- mode?: string;
-
- system?: string;
-
- tools?: { [key: string]: boolean };
-}
-
-export interface SessionInitParams {
- messageID: string;
-
- modelID: string;
-
- providerID: string;
-}
-
-export interface SessionRevertParams {
- messageID: string;
-
- partID?: string;
-}
-
-export interface SessionSummarizeParams {
- modelID: string;
-
- providerID: string;
-}
-
-export declare namespace SessionResource {
- export {
- type AssistantMessage as AssistantMessage,
- type FilePart as FilePart,
- type FilePartInput as FilePartInput,
- type FilePartSource as FilePartSource,
- type FilePartSourceText as FilePartSourceText,
- type FileSource as FileSource,
- type Message as Message,
- type Part as Part,
- type Session as Session,
- type SnapshotPart as SnapshotPart,
- type StepFinishPart as StepFinishPart,
- type StepStartPart as StepStartPart,
- type SymbolSource as SymbolSource,
- type TextPart as TextPart,
- type TextPartInput as TextPartInput,
- type ToolPart as ToolPart,
- type ToolStateCompleted as ToolStateCompleted,
- type ToolStateError as ToolStateError,
- type ToolStatePending as ToolStatePending,
- type ToolStateRunning as ToolStateRunning,
- type UserMessage as UserMessage,
- type SessionListResponse as SessionListResponse,
- type SessionDeleteResponse as SessionDeleteResponse,
- type SessionAbortResponse as SessionAbortResponse,
- type SessionInitResponse as SessionInitResponse,
- type SessionMessagesResponse as SessionMessagesResponse,
- type SessionSummarizeResponse as SessionSummarizeResponse,
- type SessionChatParams as SessionChatParams,
- type SessionInitParams as SessionInitParams,
- type SessionRevertParams as SessionRevertParams,
- type SessionSummarizeParams as SessionSummarizeParams,
- };
-}
diff --git a/packages/sdk/src/resources/shared.ts b/packages/sdk/src/resources/shared.ts
deleted file mode 100644
index 31378f6fe..000000000
--- a/packages/sdk/src/resources/shared.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-export interface MessageAbortedError {
- data: unknown;
-
- name: 'MessageAbortedError';
-}
-
-export interface ProviderAuthError {
- data: ProviderAuthError.Data;
-
- name: 'ProviderAuthError';
-}
-
-export namespace ProviderAuthError {
- export interface Data {
- message: string;
-
- providerID: string;
- }
-}
-
-export interface UnknownError {
- data: UnknownError.Data;
-
- name: 'UnknownError';
-}
-
-export namespace UnknownError {
- export interface Data {
- message: string;
- }
-}
diff --git a/packages/sdk/src/resources/tui.ts b/packages/sdk/src/resources/tui.ts
deleted file mode 100644
index c7efbdd6c..000000000
--- a/packages/sdk/src/resources/tui.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIResource } from '../core/resource';
-import { APIPromise } from '../core/api-promise';
-import { RequestOptions } from '../internal/request-options';
-
-export class Tui extends APIResource {
- /**
- * Append prompt to the TUI
- */
- appendPrompt(body: TuiAppendPromptParams, options?: RequestOptions): APIPromise<TuiAppendPromptResponse> {
- return this._client.post('/tui/append-prompt', { body, ...options });
- }
-
- /**
- * Open the help dialog
- */
- openHelp(options?: RequestOptions): APIPromise<TuiOpenHelpResponse> {
- return this._client.post('/tui/open-help', options);
- }
-}
-
-export type TuiAppendPromptResponse = boolean;
-
-export type TuiOpenHelpResponse = boolean;
-
-export interface TuiAppendPromptParams {
- text: string;
-}
-
-export declare namespace Tui {
- export {
- type TuiAppendPromptResponse as TuiAppendPromptResponse,
- type TuiOpenHelpResponse as TuiOpenHelpResponse,
- type TuiAppendPromptParams as TuiAppendPromptParams,
- };
-}
diff --git a/packages/sdk/src/streaming.ts b/packages/sdk/src/streaming.ts
deleted file mode 100644
index 9e6da1063..000000000
--- a/packages/sdk/src/streaming.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/** @deprecated Import from ./core/streaming instead */
-export * from './core/streaming';
diff --git a/packages/sdk/src/uploads.ts b/packages/sdk/src/uploads.ts
deleted file mode 100644
index b2ef64710..000000000
--- a/packages/sdk/src/uploads.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/** @deprecated Import from ./core/uploads instead */
-export * from './core/uploads';
diff --git a/packages/sdk/src/version.ts b/packages/sdk/src/version.ts
deleted file mode 100644
index 48ca0ae07..000000000
--- a/packages/sdk/src/version.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const VERSION = '0.1.0-alpha.20'; // x-release-please-version
diff --git a/packages/sdk/sst-env.d.ts b/packages/sdk/sst-env.d.ts
deleted file mode 100644
index b6a7e9066..000000000
--- a/packages/sdk/sst-env.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* This file is auto-generated by SST. Do not edit. */
-/* tslint:disable */
-/* eslint-disable */
-/* deno-fmt-ignore-file */
-
-/// <reference path="../../sst-env.d.ts" />
-
-import "sst"
-export {} \ No newline at end of file
diff --git a/packages/sdk/stainless/generate.ts b/packages/sdk/stainless/generate.ts
new file mode 100755
index 000000000..0a766d0d7
--- /dev/null
+++ b/packages/sdk/stainless/generate.ts
@@ -0,0 +1,15 @@
+#!/usr/bin/env bun
+import { $ } from "bun"
+const dir = new URL(".", import.meta.url).pathname
+process.chdir(dir)
+
+console.log("=== Generating Stainless SDK ===")
+console.log(process.cwd())
+
+await $`rm -rf go`
+await $`bun run ../../opencode/src/index.ts generate > openapi.json`
+await $`stl builds create --branch dev --pull --allow-empty --+target go`
+
+await $`rm -rf ../go`
+await $`mv opencode-go/ ../go`
+await $`rm -rf ../go/.git`
diff --git a/packages/sdk/stainless/stainless-workspace.json b/packages/sdk/stainless/stainless-workspace.json
new file mode 100644
index 000000000..b4230b05e
--- /dev/null
+++ b/packages/sdk/stainless/stainless-workspace.json
@@ -0,0 +1,5 @@
+{
+ "project": "opencode",
+ "openapi_spec": "openapi.json",
+ "stainless_config": "stainless.yml"
+}
diff --git a/packages/sdk/stainless/stainless.yml b/packages/sdk/stainless/stainless.yml
new file mode 100644
index 000000000..3bc7ab0e0
--- /dev/null
+++ b/packages/sdk/stainless/stainless.yml
@@ -0,0 +1,151 @@
+# yaml-language-server: $schema=https://app.stainless.com/config-internal.schema.json
+
+organization:
+ name: opencode
+ docs: "https://opencode.ai/docs"
+ contact: "[email protected]"
+
+targets:
+ typescript:
+ package_name: "@opencode-ai/sdk"
+ production_repo: "sst/opencode-sdk-js"
+ publish:
+ npm: true
+ go:
+ package_name: opencode
+ production_repo: sst/opencode-sdk-go
+ python:
+ project_name: opencode-ai
+ package_name: opencode_ai
+ production_repo: sst/opencode-sdk-python
+ publish:
+ pypi: true
+
+environments:
+ production: http://localhost:54321
+
+streaming:
+ on_event:
+ - kind: fallthrough
+ handle: yield
+
+resources:
+ $shared:
+ models:
+ unknownError: UnknownError
+ providerAuthError: ProviderAuthError
+ messageAbortedError: MessageAbortedError
+
+ event:
+ methods:
+ list:
+ endpoint: get /event
+ paginated: false
+ streaming:
+ # This method is always streaming.
+ param_discriminator: null
+
+ app:
+ models:
+ app: App
+ logLevel: LogLevel
+ provider: Provider
+ model: Model
+ mode: Mode
+ methods:
+ get: get /app
+ init: post /app/init
+ log: post /log
+ modes: get /mode
+ providers: get /config/providers
+
+ find:
+ models:
+ match: Match
+ symbol: Symbol
+ methods:
+ text: get /find
+ files: get /find/file
+ symbols: get /find/symbol
+
+ file:
+ models:
+ file: File
+ methods:
+ read: get /file
+ status: get /file/status
+
+ config:
+ models:
+ config: Config
+ keybindsConfig: KeybindsConfig
+ mcpLocalConfig: McpLocalConfig
+ mcpRemoteConfig: McpRemoteConfig
+ modeConfig: ModeConfig
+ methods:
+ get: get /config
+
+ session:
+ models:
+ session: Session
+ message: Message
+ part: Part
+ textPart: TextPart
+ textPartInput: TextPartInput
+ filePart: FilePart
+ filePartInput: FilePartInput
+ filePartSourceText: FilePartSourceText
+ filePartSource: FilePartSource
+ fileSource: FileSource
+ symbolSource: SymbolSource
+ toolPart: ToolPart
+ stepStartPart: StepStartPart
+ stepFinishPart: StepFinishPart
+ snapshotPart: SnapshotPart
+ assistantMessage: AssistantMessage
+ userMessage: UserMessage
+ toolStatePending: ToolStatePending
+ toolStateRunning: ToolStateRunning
+ toolStateCompleted: ToolStateCompleted
+ toolStateError: ToolStateError
+
+ methods:
+ list: get /session
+ create: post /session
+ delete: delete /session/{id}
+ init: post /session/{id}/init
+ abort: post /session/{id}/abort
+ share: post /session/{id}/share
+ unshare: delete /session/{id}/share
+ summarize: post /session/{id}/summarize
+ messages: get /session/{id}/message
+ chat: post /session/{id}/message
+ revert: post /session/{id}/revert
+ unrevert: post /session/{id}/unrevert
+
+ tui:
+ methods:
+ appendPrompt: post /tui/append-prompt
+ openHelp: post /tui/open-help
+
+settings:
+ disable_mock_tests: true
+ license: MIT
+
+security:
+ - {}
+
+readme:
+ example_requests:
+ default:
+ type: request
+ endpoint: get /session
+ params: {}
+ headline:
+ type: request
+ endpoint: get /session
+ params: {}
+ streaming:
+ type: request
+ endpoint: get /event
+ params: {}
diff --git a/packages/sdk/tests/api-resources/app.test.ts b/packages/sdk/tests/api-resources/app.test.ts
deleted file mode 100644
index 9ccf4557c..000000000
--- a/packages/sdk/tests/api-resources/app.test.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource app', () => {
- // skipped: tests are disabled for the time being
- test.skip('get', async () => {
- const responsePromise = client.app.get();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('init', async () => {
- const responsePromise = client.app.init();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('log: only required params', async () => {
- const responsePromise = client.app.log({ level: 'debug', message: 'message', service: 'service' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('log: required and optional params', async () => {
- const response = await client.app.log({
- level: 'debug',
- message: 'message',
- service: 'service',
- extra: { foo: 'bar' },
- });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('modes', async () => {
- const responsePromise = client.app.modes();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('providers', async () => {
- const responsePromise = client.app.providers();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/api-resources/config.test.ts b/packages/sdk/tests/api-resources/config.test.ts
deleted file mode 100644
index f85fb1005..000000000
--- a/packages/sdk/tests/api-resources/config.test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource config', () => {
- // skipped: tests are disabled for the time being
- test.skip('get', async () => {
- const responsePromise = client.config.get();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/api-resources/event.test.ts b/packages/sdk/tests/api-resources/event.test.ts
deleted file mode 100644
index 4e228bc86..000000000
--- a/packages/sdk/tests/api-resources/event.test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource event', () => {
- // skipped: tests are disabled for the time being
- test.skip('list', async () => {
- const responsePromise = client.event.list();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/api-resources/file.test.ts b/packages/sdk/tests/api-resources/file.test.ts
deleted file mode 100644
index 4c5178739..000000000
--- a/packages/sdk/tests/api-resources/file.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource file', () => {
- // skipped: tests are disabled for the time being
- test.skip('read: only required params', async () => {
- const responsePromise = client.file.read({ path: 'path' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('read: required and optional params', async () => {
- const response = await client.file.read({ path: 'path' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('status', async () => {
- const responsePromise = client.file.status();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/api-resources/find.test.ts b/packages/sdk/tests/api-resources/find.test.ts
deleted file mode 100644
index ce0e7c0ae..000000000
--- a/packages/sdk/tests/api-resources/find.test.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource find', () => {
- // skipped: tests are disabled for the time being
- test.skip('files: only required params', async () => {
- const responsePromise = client.find.files({ query: 'query' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('files: required and optional params', async () => {
- const response = await client.find.files({ query: 'query' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('symbols: only required params', async () => {
- const responsePromise = client.find.symbols({ query: 'query' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('symbols: required and optional params', async () => {
- const response = await client.find.symbols({ query: 'query' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('text: only required params', async () => {
- const responsePromise = client.find.text({ pattern: 'pattern' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('text: required and optional params', async () => {
- const response = await client.find.text({ pattern: 'pattern' });
- });
-});
diff --git a/packages/sdk/tests/api-resources/session.test.ts b/packages/sdk/tests/api-resources/session.test.ts
deleted file mode 100644
index 2acf08251..000000000
--- a/packages/sdk/tests/api-resources/session.test.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource session', () => {
- // skipped: tests are disabled for the time being
- test.skip('create', async () => {
- const responsePromise = client.session.create();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('list', async () => {
- const responsePromise = client.session.list();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('delete', async () => {
- const responsePromise = client.session.delete('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('abort', async () => {
- const responsePromise = client.session.abort('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('chat: only required params', async () => {
- const responsePromise = client.session.chat('id', {
- modelID: 'modelID',
- parts: [{ text: 'text', type: 'text' }],
- providerID: 'providerID',
- });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('chat: required and optional params', async () => {
- const response = await client.session.chat('id', {
- modelID: 'modelID',
- parts: [{ text: 'text', type: 'text', id: 'id', synthetic: true, time: { start: 0, end: 0 } }],
- providerID: 'providerID',
- messageID: 'msg',
- mode: 'mode',
- system: 'system',
- tools: { foo: true },
- });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('init: only required params', async () => {
- const responsePromise = client.session.init('id', {
- messageID: 'messageID',
- modelID: 'modelID',
- providerID: 'providerID',
- });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('init: required and optional params', async () => {
- const response = await client.session.init('id', {
- messageID: 'messageID',
- modelID: 'modelID',
- providerID: 'providerID',
- });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('messages', async () => {
- const responsePromise = client.session.messages('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('revert: only required params', async () => {
- const responsePromise = client.session.revert('id', { messageID: 'msg' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('revert: required and optional params', async () => {
- const response = await client.session.revert('id', { messageID: 'msg', partID: 'prt' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('share', async () => {
- const responsePromise = client.session.share('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('summarize: only required params', async () => {
- const responsePromise = client.session.summarize('id', { modelID: 'modelID', providerID: 'providerID' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('summarize: required and optional params', async () => {
- const response = await client.session.summarize('id', { modelID: 'modelID', providerID: 'providerID' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('unrevert', async () => {
- const responsePromise = client.session.unrevert('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('unshare', async () => {
- const responsePromise = client.session.unshare('id');
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/api-resources/tui.test.ts b/packages/sdk/tests/api-resources/tui.test.ts
deleted file mode 100644
index 8ac0d4359..000000000
--- a/packages/sdk/tests/api-resources/tui.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import Opencode from '@opencode-ai/sdk';
-
-const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' });
-
-describe('resource tui', () => {
- // skipped: tests are disabled for the time being
- test.skip('appendPrompt: only required params', async () => {
- const responsePromise = client.tui.appendPrompt({ text: 'text' });
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-
- // skipped: tests are disabled for the time being
- test.skip('appendPrompt: required and optional params', async () => {
- const response = await client.tui.appendPrompt({ text: 'text' });
- });
-
- // skipped: tests are disabled for the time being
- test.skip('openHelp', async () => {
- const responsePromise = client.tui.openHelp();
- const rawResponse = await responsePromise.asResponse();
- expect(rawResponse).toBeInstanceOf(Response);
- const response = await responsePromise;
- expect(response).not.toBeInstanceOf(Response);
- const dataAndResponse = await responsePromise.withResponse();
- expect(dataAndResponse.data).toBe(response);
- expect(dataAndResponse.response).toBe(rawResponse);
- });
-});
diff --git a/packages/sdk/tests/base64.test.ts b/packages/sdk/tests/base64.test.ts
deleted file mode 100644
index bf2d17042..000000000
--- a/packages/sdk/tests/base64.test.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { fromBase64, toBase64 } from '@opencode-ai/sdk/internal/utils/base64';
-
-describe.each(['Buffer', 'atob'])('with %s', (mode) => {
- let originalBuffer: BufferConstructor;
- beforeAll(() => {
- if (mode === 'atob') {
- originalBuffer = globalThis.Buffer;
- // @ts-expect-error Can't assign undefined to BufferConstructor
- delete globalThis.Buffer;
- }
- });
- afterAll(() => {
- if (mode === 'atob') {
- globalThis.Buffer = originalBuffer;
- }
- });
- test('toBase64', () => {
- const testCases = [
- {
- input: 'hello world',
- expected: 'aGVsbG8gd29ybGQ=',
- },
- {
- input: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]),
- expected: 'aGVsbG8gd29ybGQ=',
- },
- {
- input: undefined,
- expected: '',
- },
- {
- input: new Uint8Array([
- 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123,
- 193, 71,
- ]),
- expected: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH',
- },
- {
- input: '✓',
- expected: '4pyT',
- },
- {
- input: new Uint8Array([226, 156, 147]),
- expected: '4pyT',
- },
- ];
-
- testCases.forEach(({ input, expected }) => {
- expect(toBase64(input)).toBe(expected);
- });
- });
-
- test('fromBase64', () => {
- const testCases = [
- {
- input: 'aGVsbG8gd29ybGQ=',
- expected: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]),
- },
- {
- input: '',
- expected: new Uint8Array([]),
- },
- {
- input: '5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH',
- expected: new Uint8Array([
- 229, 102, 215, 230, 65, 22, 46, 87, 243, 176, 99, 99, 31, 174, 8, 242, 83, 142, 169, 64, 122, 123,
- 193, 71,
- ]),
- },
- {
- input: '4pyT',
- expected: new Uint8Array([226, 156, 147]),
- },
- ];
-
- testCases.forEach(({ input, expected }) => {
- expect(fromBase64(input)).toEqual(expected);
- });
- });
-});
diff --git a/packages/sdk/tests/buildHeaders.test.ts b/packages/sdk/tests/buildHeaders.test.ts
deleted file mode 100644
index dfa8d4360..000000000
--- a/packages/sdk/tests/buildHeaders.test.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { inspect } from 'node:util';
-import { buildHeaders, type HeadersLike, type NullableHeaders } from '@opencode-ai/sdk/internal/headers';
-
-function inspectNullableHeaders(headers: NullableHeaders) {
- return `NullableHeaders {${[
- ...[...headers.values.entries()].map(([name, value]) => ` ${inspect(name)}: ${inspect(value)}`),
- ...[...headers.nulls].map((name) => ` ${inspect(name)}: null`),
- ].join(', ')} }`;
-}
-
-describe('buildHeaders', () => {
- const cases: [HeadersLike[], string][] = [
- [[new Headers({ 'content-type': 'text/plain' })], `NullableHeaders { 'content-type': 'text/plain' }`],
- [
- [
- {
- 'content-type': 'text/plain',
- },
- {
- 'Content-Type': undefined,
- },
- ],
- `NullableHeaders { 'content-type': 'text/plain' }`,
- ],
- [
- [
- {
- 'content-type': 'text/plain',
- },
- {
- 'Content-Type': null,
- },
- ],
- `NullableHeaders { 'content-type': null }`,
- ],
- [
- [
- {
- cookie: 'name1=value1',
- Cookie: 'name2=value2',
- },
- ],
- `NullableHeaders { 'cookie': 'name2=value2' }`,
- ],
- [
- [
- {
- cookie: 'name1=value1',
- Cookie: undefined,
- },
- ],
- `NullableHeaders { 'cookie': 'name1=value1' }`,
- ],
- [
- [
- {
- cookie: ['name1=value1', 'name2=value2'],
- },
- ],
- `NullableHeaders { 'cookie': 'name1=value1; name2=value2' }`,
- ],
- [
- [
- {
- 'x-foo': ['name1=value1', 'name2=value2'],
- },
- ],
- `NullableHeaders { 'x-foo': 'name1=value1, name2=value2' }`,
- ],
- [
- [
- [
- ['cookie', 'name1=value1'],
- ['cookie', 'name2=value2'],
- ['Cookie', 'name3=value3'],
- ],
- ],
- `NullableHeaders { 'cookie': 'name1=value1; name2=value2; name3=value3' }`,
- ],
- [[undefined], `NullableHeaders { }`],
- [[null], `NullableHeaders { }`],
- ];
- for (const [input, expected] of cases) {
- test(expected, () => {
- expect(inspectNullableHeaders(buildHeaders(input))).toEqual(expected);
- });
- }
-});
diff --git a/packages/sdk/tests/form.test.ts b/packages/sdk/tests/form.test.ts
deleted file mode 100644
index e8cc4edb0..000000000
--- a/packages/sdk/tests/form.test.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { multipartFormRequestOptions, createForm } from '@opencode-ai/sdk/internal/uploads';
-import { toFile } from '@opencode-ai/sdk/core/uploads';
-
-describe('form data validation', () => {
- test('valid values do not error', async () => {
- await multipartFormRequestOptions(
- {
- body: {
- foo: 'foo',
- string: 1,
- bool: true,
- file: await toFile(Buffer.from('some-content')),
- blob: new Blob(['Some content'], { type: 'text/plain' }),
- },
- },
- fetch,
- );
- });
-
- test('null', async () => {
- await expect(
- multipartFormRequestOptions(
- {
- body: {
- null: null,
- },
- },
- fetch,
- ),
- ).rejects.toThrow(TypeError);
- });
-
- test('undefined is stripped', async () => {
- const form = await createForm(
- {
- foo: undefined,
- bar: 'baz',
- },
- fetch,
- );
- expect(form.has('foo')).toBe(false);
- expect(form.get('bar')).toBe('baz');
- });
-
- test('nested undefined property is stripped', async () => {
- const form = await createForm(
- {
- bar: {
- baz: undefined,
- },
- },
- fetch,
- );
- expect(Array.from(form.entries())).toEqual([]);
-
- const form2 = await createForm(
- {
- bar: {
- foo: 'string',
- baz: undefined,
- },
- },
- fetch,
- );
- expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]);
- });
-
- test('nested undefined array item is stripped', async () => {
- const form = await createForm(
- {
- bar: [undefined, undefined],
- },
- fetch,
- );
- expect(Array.from(form.entries())).toEqual([]);
-
- const form2 = await createForm(
- {
- bar: [undefined, 'foo'],
- },
- fetch,
- );
- expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]);
- });
-});
diff --git a/packages/sdk/tests/index.test.ts b/packages/sdk/tests/index.test.ts
deleted file mode 100644
index 05b51e074..000000000
--- a/packages/sdk/tests/index.test.ts
+++ /dev/null
@@ -1,690 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { APIPromise } from '@opencode-ai/sdk/core/api-promise';
-
-import util from 'node:util';
-import Opencode from '@opencode-ai/sdk';
-import { APIUserAbortError } from '@opencode-ai/sdk';
-const defaultFetch = fetch;
-
-describe('instantiate client', () => {
- const env = process.env;
-
- beforeEach(() => {
- jest.resetModules();
- process.env = { ...env };
- });
-
- afterEach(() => {
- process.env = env;
- });
-
- describe('defaultHeaders', () => {
- const client = new Opencode({
- baseURL: 'http://localhost:5000/',
- defaultHeaders: { 'X-My-Default-Header': '2' },
- });
-
- test('they are used in the request', async () => {
- const { req } = await client.buildRequest({ path: '/foo', method: 'post' });
- expect(req.headers.get('x-my-default-header')).toEqual('2');
- });
-
- test('can ignore `undefined` and leave the default', async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- headers: { 'X-My-Default-Header': undefined },
- });
- expect(req.headers.get('x-my-default-header')).toEqual('2');
- });
-
- test('can be removed with `null`', async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- headers: { 'X-My-Default-Header': null },
- });
- expect(req.headers.has('x-my-default-header')).toBe(false);
- });
- });
- describe('logging', () => {
- const env = process.env;
-
- beforeEach(() => {
- process.env = { ...env };
- process.env['OPENCODE_LOG'] = undefined;
- });
-
- afterEach(() => {
- process.env = env;
- });
-
- const forceAPIResponseForClient = async (client: Opencode) => {
- await new APIPromise(
- client,
- Promise.resolve({
- response: new Response(),
- controller: new AbortController(),
- requestLogID: 'log_000000',
- retryOfRequestLogID: undefined,
- startTime: Date.now(),
- options: {
- method: 'get',
- path: '/',
- },
- }),
- );
- };
-
- test('debug logs when log level is debug', async () => {
- const debugMock = jest.fn();
- const logger = {
- debug: debugMock,
- info: jest.fn(),
- warn: jest.fn(),
- error: jest.fn(),
- };
-
- const client = new Opencode({ logger: logger, logLevel: 'debug' });
-
- await forceAPIResponseForClient(client);
- expect(debugMock).toHaveBeenCalled();
- });
-
- test('default logLevel is warn', async () => {
- const client = new Opencode({});
- expect(client.logLevel).toBe('warn');
- });
-
- test('debug logs are skipped when log level is info', async () => {
- const debugMock = jest.fn();
- const logger = {
- debug: debugMock,
- info: jest.fn(),
- warn: jest.fn(),
- error: jest.fn(),
- };
-
- const client = new Opencode({ logger: logger, logLevel: 'info' });
-
- await forceAPIResponseForClient(client);
- expect(debugMock).not.toHaveBeenCalled();
- });
-
- test('debug logs happen with debug env var', async () => {
- const debugMock = jest.fn();
- const logger = {
- debug: debugMock,
- info: jest.fn(),
- warn: jest.fn(),
- error: jest.fn(),
- };
-
- process.env['OPENCODE_LOG'] = 'debug';
- const client = new Opencode({ logger: logger });
- expect(client.logLevel).toBe('debug');
-
- await forceAPIResponseForClient(client);
- expect(debugMock).toHaveBeenCalled();
- });
-
- test('warn when env var level is invalid', async () => {
- const warnMock = jest.fn();
- const logger = {
- debug: jest.fn(),
- info: jest.fn(),
- warn: warnMock,
- error: jest.fn(),
- };
-
- process.env['OPENCODE_LOG'] = 'not a log level';
- const client = new Opencode({ logger: logger });
- expect(client.logLevel).toBe('warn');
- expect(warnMock).toHaveBeenCalledWith(
- 'process.env[\'OPENCODE_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]',
- );
- });
-
- test('client log level overrides env var', async () => {
- const debugMock = jest.fn();
- const logger = {
- debug: debugMock,
- info: jest.fn(),
- warn: jest.fn(),
- error: jest.fn(),
- };
-
- process.env['OPENCODE_LOG'] = 'debug';
- const client = new Opencode({ logger: logger, logLevel: 'off' });
-
- await forceAPIResponseForClient(client);
- expect(debugMock).not.toHaveBeenCalled();
- });
-
- test('no warning logged for invalid env var level + valid client level', async () => {
- const warnMock = jest.fn();
- const logger = {
- debug: jest.fn(),
- info: jest.fn(),
- warn: warnMock,
- error: jest.fn(),
- };
-
- process.env['OPENCODE_LOG'] = 'not a log level';
- const client = new Opencode({ logger: logger, logLevel: 'debug' });
- expect(client.logLevel).toBe('debug');
- expect(warnMock).not.toHaveBeenCalled();
- });
- });
-
- describe('defaultQuery', () => {
- test('with null query params given', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' } });
- expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo');
- });
-
- test('multiple default query params', () => {
- const client = new Opencode({
- baseURL: 'http://localhost:5000/',
- defaultQuery: { apiVersion: 'foo', hello: 'world' },
- });
- expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world');
- });
-
- test('overriding with `undefined`', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' } });
- expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo');
- });
- });
-
- test('custom fetch', async () => {
- const client = new Opencode({
- baseURL: 'http://localhost:5000/',
- fetch: (url) => {
- return Promise.resolve(
- new Response(JSON.stringify({ url, custom: true }), {
- headers: { 'Content-Type': 'application/json' },
- }),
- );
- },
- });
-
- const response = await client.get('/foo');
- expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true });
- });
-
- test('explicit global fetch', async () => {
- // make sure the global fetch type is assignable to our Fetch type
- const client = new Opencode({ baseURL: 'http://localhost:5000/', fetch: defaultFetch });
- });
-
- test('custom signal', async () => {
- const client = new Opencode({
- baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
- fetch: (...args) => {
- return new Promise((resolve, reject) =>
- setTimeout(
- () =>
- defaultFetch(...args)
- .then(resolve)
- .catch(reject),
- 300,
- ),
- );
- },
- });
-
- const controller = new AbortController();
- setTimeout(() => controller.abort(), 200);
-
- const spy = jest.spyOn(client, 'request');
-
- await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError);
- expect(spy).toHaveBeenCalledTimes(1);
- });
-
- test('normalized method', async () => {
- let capturedRequest: RequestInit | undefined;
- const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise<Response> => {
- capturedRequest = init;
- return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } });
- };
-
- const client = new Opencode({ baseURL: 'http://localhost:5000/', fetch: testFetch });
-
- await client.patch('/foo');
- expect(capturedRequest?.method).toEqual('PATCH');
- });
-
- describe('baseUrl', () => {
- test('trailing slash', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/custom/path/' });
- expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo');
- });
-
- test('no trailing slash', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/custom/path' });
- expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo');
- });
-
- afterEach(() => {
- process.env['OPENCODE_BASE_URL'] = undefined;
- });
-
- test('explicit option', () => {
- const client = new Opencode({ baseURL: 'https://example.com' });
- expect(client.baseURL).toEqual('https://example.com');
- });
-
- test('env variable', () => {
- process.env['OPENCODE_BASE_URL'] = 'https://example.com/from_env';
- const client = new Opencode({});
- expect(client.baseURL).toEqual('https://example.com/from_env');
- });
-
- test('empty env variable', () => {
- process.env['OPENCODE_BASE_URL'] = ''; // empty
- const client = new Opencode({});
- expect(client.baseURL).toEqual('http://localhost:54321');
- });
-
- test('blank env variable', () => {
- process.env['OPENCODE_BASE_URL'] = ' '; // blank
- const client = new Opencode({});
- expect(client.baseURL).toEqual('http://localhost:54321');
- });
-
- test('in request options', () => {
- const client = new Opencode({});
- expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
- 'http://localhost:5000/option/foo',
- );
- });
-
- test('in request options overridden by client options', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/client' });
- expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
- 'http://localhost:5000/client/foo',
- );
- });
-
- test('in request options overridden by env variable', () => {
- process.env['OPENCODE_BASE_URL'] = 'http://localhost:5000/env';
- const client = new Opencode({});
- expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual(
- 'http://localhost:5000/env/foo',
- );
- });
- });
-
- test('maxRetries option is correctly set', () => {
- const client = new Opencode({ maxRetries: 4 });
- expect(client.maxRetries).toEqual(4);
-
- // default
- const client2 = new Opencode({});
- expect(client2.maxRetries).toEqual(2);
- });
-
- describe('withOptions', () => {
- test('creates a new client with overridden options', async () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/', maxRetries: 3 });
-
- const newClient = client.withOptions({
- maxRetries: 5,
- baseURL: 'http://localhost:5001/',
- });
-
- // Verify the new client has updated options
- expect(newClient.maxRetries).toEqual(5);
- expect(newClient.baseURL).toEqual('http://localhost:5001/');
-
- // Verify the original client is unchanged
- expect(client.maxRetries).toEqual(3);
- expect(client.baseURL).toEqual('http://localhost:5000/');
-
- // Verify it's a different instance
- expect(newClient).not.toBe(client);
- expect(newClient.constructor).toBe(client.constructor);
- });
-
- test('inherits options from the parent client', async () => {
- const client = new Opencode({
- baseURL: 'http://localhost:5000/',
- defaultHeaders: { 'X-Test-Header': 'test-value' },
- defaultQuery: { 'test-param': 'test-value' },
- });
-
- const newClient = client.withOptions({
- baseURL: 'http://localhost:5001/',
- });
-
- // Test inherited options remain the same
- expect(newClient.buildURL('/foo', null)).toEqual('http://localhost:5001/foo?test-param=test-value');
-
- const { req } = await newClient.buildRequest({ path: '/foo', method: 'get' });
- expect(req.headers.get('x-test-header')).toEqual('test-value');
- });
-
- test('respects runtime property changes when creating new client', () => {
- const client = new Opencode({ baseURL: 'http://localhost:5000/', timeout: 1000 });
-
- // Modify the client properties directly after creation
- client.baseURL = 'http://localhost:6000/';
- client.timeout = 2000;
-
- // Create a new client with withOptions
- const newClient = client.withOptions({
- maxRetries: 10,
- });
-
- // Verify the new client uses the updated properties, not the original ones
- expect(newClient.baseURL).toEqual('http://localhost:6000/');
- expect(newClient.timeout).toEqual(2000);
- expect(newClient.maxRetries).toEqual(10);
-
- // Original client should still have its modified properties
- expect(client.baseURL).toEqual('http://localhost:6000/');
- expect(client.timeout).toEqual(2000);
- expect(client.maxRetries).not.toEqual(10);
-
- // Verify URL building uses the updated baseURL
- expect(newClient.buildURL('/bar', null)).toEqual('http://localhost:6000/bar');
- });
- });
-});
-
-describe('request building', () => {
- const client = new Opencode({});
-
- describe('custom headers', () => {
- test('handles undefined', async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- body: { value: 'hello' },
- headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null },
- });
- expect(req.headers.get('x-foo')).toEqual('bar');
- expect(req.headers.get('x-Foo')).toEqual('bar');
- expect(req.headers.get('X-Foo')).toEqual('bar');
- expect(req.headers.get('x-baz')).toEqual(null);
- });
- });
-});
-
-describe('default encoder', () => {
- const client = new Opencode({});
-
- class Serializable {
- toJSON() {
- return { $type: 'Serializable' };
- }
- }
- class Collection<T> {
- #things: T[];
- constructor(things: T[]) {
- this.#things = Array.from(things);
- }
- toJSON() {
- return Array.from(this.#things);
- }
- [Symbol.iterator]() {
- return this.#things[Symbol.iterator];
- }
- }
- for (const jsonValue of [{}, [], { __proto__: null }, new Serializable(), new Collection(['item'])]) {
- test(`serializes ${util.inspect(jsonValue)} as json`, async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- body: jsonValue,
- });
- expect(req.headers).toBeInstanceOf(Headers);
- expect(req.headers.get('content-type')).toEqual('application/json');
- expect(req.body).toBe(JSON.stringify(jsonValue));
- });
- }
-
- const encoder = new TextEncoder();
- const asyncIterable = (async function* () {
- yield encoder.encode('a\n');
- yield encoder.encode('b\n');
- yield encoder.encode('c\n');
- })();
- for (const streamValue of [
- [encoder.encode('a\nb\nc\n')][Symbol.iterator](),
- new Response('a\nb\nc\n').body,
- asyncIterable,
- ]) {
- test(`converts ${util.inspect(streamValue)} to ReadableStream`, async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- body: streamValue,
- });
- expect(req.headers).toBeInstanceOf(Headers);
- expect(req.headers.get('content-type')).toEqual(null);
- expect(req.body).toBeInstanceOf(ReadableStream);
- expect(await new Response(req.body).text()).toBe('a\nb\nc\n');
- });
- }
-
- test(`can set content-type for ReadableStream`, async () => {
- const { req } = await client.buildRequest({
- path: '/foo',
- method: 'post',
- body: new Response('a\nb\nc\n').body,
- headers: { 'Content-Type': 'text/plain' },
- });
- expect(req.headers).toBeInstanceOf(Headers);
- expect(req.headers.get('content-type')).toEqual('text/plain');
- expect(req.body).toBeInstanceOf(ReadableStream);
- expect(await new Response(req.body).text()).toBe('a\nb\nc\n');
- });
-});
-
-describe('retries', () => {
- test('retry on timeout', async () => {
- let count = 0;
- const testFetch = async (
- url: string | URL | Request,
- { signal }: RequestInit = {},
- ): Promise<Response> => {
- if (count++ === 0) {
- return new Promise(
- (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))),
- );
- }
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
-
- const client = new Opencode({ timeout: 10, fetch: testFetch });
-
- expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
- expect(count).toEqual(2);
- expect(
- await client
- .request({ path: '/foo', method: 'get' })
- .asResponse()
- .then((r) => r.text()),
- ).toEqual(JSON.stringify({ a: 1 }));
- expect(count).toEqual(3);
- });
-
- test('retry count header', async () => {
- let count = 0;
- let capturedRequest: RequestInit | undefined;
- const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise<Response> => {
- count++;
- if (count <= 2) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After': '0.1',
- },
- });
- }
- capturedRequest = init;
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
-
- const client = new Opencode({ fetch: testFetch, maxRetries: 4 });
-
- expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
-
- expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('2');
- expect(count).toEqual(3);
- });
-
- test('omit retry count header', async () => {
- let count = 0;
- let capturedRequest: RequestInit | undefined;
- const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise<Response> => {
- count++;
- if (count <= 2) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After': '0.1',
- },
- });
- }
- capturedRequest = init;
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
- const client = new Opencode({ fetch: testFetch, maxRetries: 4 });
-
- expect(
- await client.request({
- path: '/foo',
- method: 'get',
- headers: { 'X-Stainless-Retry-Count': null },
- }),
- ).toEqual({ a: 1 });
-
- expect((capturedRequest!.headers as Headers).has('x-stainless-retry-count')).toBe(false);
- });
-
- test('omit retry count header by default', async () => {
- let count = 0;
- let capturedRequest: RequestInit | undefined;
- const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise<Response> => {
- count++;
- if (count <= 2) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After': '0.1',
- },
- });
- }
- capturedRequest = init;
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
- const client = new Opencode({
- fetch: testFetch,
- maxRetries: 4,
- defaultHeaders: { 'X-Stainless-Retry-Count': null },
- });
-
- expect(
- await client.request({
- path: '/foo',
- method: 'get',
- }),
- ).toEqual({ a: 1 });
-
- expect(capturedRequest!.headers as Headers).not.toHaveProperty('x-stainless-retry-count');
- });
-
- test('overwrite retry count header', async () => {
- let count = 0;
- let capturedRequest: RequestInit | undefined;
- const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise<Response> => {
- count++;
- if (count <= 2) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After': '0.1',
- },
- });
- }
- capturedRequest = init;
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
- const client = new Opencode({ fetch: testFetch, maxRetries: 4 });
-
- expect(
- await client.request({
- path: '/foo',
- method: 'get',
- headers: { 'X-Stainless-Retry-Count': '42' },
- }),
- ).toEqual({ a: 1 });
-
- expect((capturedRequest!.headers as Headers).get('x-stainless-retry-count')).toEqual('42');
- });
-
- test('retry on 429 with retry-after', async () => {
- let count = 0;
- const testFetch = async (
- url: string | URL | Request,
- { signal }: RequestInit = {},
- ): Promise<Response> => {
- if (count++ === 0) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After': '0.1',
- },
- });
- }
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
-
- const client = new Opencode({ fetch: testFetch });
-
- expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
- expect(count).toEqual(2);
- expect(
- await client
- .request({ path: '/foo', method: 'get' })
- .asResponse()
- .then((r) => r.text()),
- ).toEqual(JSON.stringify({ a: 1 }));
- expect(count).toEqual(3);
- });
-
- test('retry on 429 with retry-after-ms', async () => {
- let count = 0;
- const testFetch = async (
- url: string | URL | Request,
- { signal }: RequestInit = {},
- ): Promise<Response> => {
- if (count++ === 0) {
- return new Response(undefined, {
- status: 429,
- headers: {
- 'Retry-After-Ms': '10',
- },
- });
- }
- return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } });
- };
-
- const client = new Opencode({ fetch: testFetch });
-
- expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 });
- expect(count).toEqual(2);
- expect(
- await client
- .request({ path: '/foo', method: 'get' })
- .asResponse()
- .then((r) => r.text()),
- ).toEqual(JSON.stringify({ a: 1 }));
- expect(count).toEqual(3);
- });
-});
diff --git a/packages/sdk/tests/internal/decoders/line.test.ts b/packages/sdk/tests/internal/decoders/line.test.ts
deleted file mode 100644
index e9874befb..000000000
--- a/packages/sdk/tests/internal/decoders/line.test.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { findDoubleNewlineIndex, LineDecoder } from '@opencode-ai/sdk/internal/decoders/line';
-
-function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] {
- const decoder = new LineDecoder();
- const lines: string[] = [];
- for (const chunk of chunks) {
- lines.push(...decoder.decode(chunk));
- }
-
- if (flush) {
- lines.push(...decoder.flush());
- }
-
- return lines;
-}
-
-describe('line decoder', () => {
- test('basic', () => {
- // baz is not included because the line hasn't ended yet
- expect(decodeChunks(['foo', ' bar\nbaz'])).toEqual(['foo bar']);
- });
-
- test('basic with \\r', () => {
- expect(decodeChunks(['foo', ' bar\r\nbaz'])).toEqual(['foo bar']);
- expect(decodeChunks(['foo', ' bar\r\nbaz'], { flush: true })).toEqual(['foo bar', 'baz']);
- });
-
- test('trailing new lines', () => {
- expect(decodeChunks(['foo', ' bar', 'baz\n', 'thing\n'])).toEqual(['foo barbaz', 'thing']);
- });
-
- test('trailing new lines with \\r', () => {
- expect(decodeChunks(['foo', ' bar', 'baz\r\n', 'thing\r\n'])).toEqual(['foo barbaz', 'thing']);
- });
-
- test('escaped new lines', () => {
- expect(decodeChunks(['foo', ' bar\\nbaz\n'])).toEqual(['foo bar\\nbaz']);
- });
-
- test('escaped new lines with \\r', () => {
- expect(decodeChunks(['foo', ' bar\\r\\nbaz\n'])).toEqual(['foo bar\\r\\nbaz']);
- });
-
- test('\\r & \\n split across multiple chunks', () => {
- expect(decodeChunks(['foo\r', '\n', 'bar'], { flush: true })).toEqual(['foo', 'bar']);
- });
-
- test('single \\r', () => {
- expect(decodeChunks(['foo\r', 'bar'], { flush: true })).toEqual(['foo', 'bar']);
- });
-
- test('double \\r', () => {
- expect(decodeChunks(['foo\r', 'bar\r'], { flush: true })).toEqual(['foo', 'bar']);
- expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']);
- // implementation detail that we don't yield the single \r line until a new \r or \n is encountered
- expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: false })).toEqual(['foo']);
- });
-
- test('double \\r then \\r\\n', () => {
- expect(decodeChunks(['foo\r', '\r', '\r', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']);
- expect(decodeChunks(['foo\n', '\n', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']);
- });
-
- test('double newline', () => {
- expect(decodeChunks(['foo\n\nbar'], { flush: true })).toEqual(['foo', '', 'bar']);
- expect(decodeChunks(['foo', '\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']);
- expect(decodeChunks(['foo\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']);
- expect(decodeChunks(['foo', '\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']);
- });
-
- test('multi-byte characters across chunks', () => {
- const decoder = new LineDecoder();
-
- // bytes taken from the string 'известни' and arbitrarily split
- // so that some multi-byte characters span multiple chunks
- expect(decoder.decode(new Uint8Array([0xd0]))).toHaveLength(0);
- expect(decoder.decode(new Uint8Array([0xb8, 0xd0, 0xb7, 0xd0]))).toHaveLength(0);
- expect(
- decoder.decode(new Uint8Array([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8])),
- ).toHaveLength(0);
-
- const decoded = decoder.decode(new Uint8Array([0xa]));
- expect(decoded).toEqual(['известни']);
- });
-
- test('flushing trailing newlines', () => {
- expect(decodeChunks(['foo\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']);
- });
-
- test('flushing empty buffer', () => {
- expect(decodeChunks([], { flush: true })).toEqual([]);
- });
-});
-
-describe('findDoubleNewlineIndex', () => {
- test('finds \\n\\n', () => {
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\nbar'))).toBe(5);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\nbar'))).toBe(2);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\n'))).toBe(5);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\n'))).toBe(2);
- });
-
- test('finds \\r\\r', () => {
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\rbar'))).toBe(5);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\rbar'))).toBe(2);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\r'))).toBe(5);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\r'))).toBe(2);
- });
-
- test('finds \\r\\n\\r\\n', () => {
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\nbar'))).toBe(7);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\nbar'))).toBe(4);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\n'))).toBe(7);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\n'))).toBe(4);
- });
-
- test('returns -1 when no double newline found', () => {
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\nbar'))).toBe(-1);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\rbar'))).toBe(-1);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\nbar'))).toBe(-1);
- expect(findDoubleNewlineIndex(new TextEncoder().encode(''))).toBe(-1);
- });
-
- test('handles incomplete patterns', () => {
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r'))).toBe(-1);
- expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n'))).toBe(-1);
- });
-});
diff --git a/packages/sdk/tests/path.test.ts b/packages/sdk/tests/path.test.ts
deleted file mode 100644
index bece09472..000000000
--- a/packages/sdk/tests/path.test.ts
+++ /dev/null
@@ -1,462 +0,0 @@
-import { createPathTagFunction, encodeURIPath } from '@opencode-ai/sdk/internal/utils/path';
-import { inspect } from 'node:util';
-import { runInNewContext } from 'node:vm';
-
-describe('path template tag function', () => {
- test('validates input', () => {
- const testParams = ['', '.', '..', 'x', '%2e', '%2E', '%2e%2e', '%2E%2e', '%2e%2E', '%2E%2E'];
- const testCases = [
- ['/path_params/', '/a'],
- ['/path_params/', '/'],
- ['/path_params/', ''],
- ['', '/a'],
- ['', '/'],
- ['', ''],
- ['a'],
- [''],
- ['/path_params/', ':initiate'],
- ['/path_params/', '.json'],
- ['/path_params/', '?beta=true'],
- ['/path_params/', '.?beta=true'],
- ['/path_params/', '/', '/download'],
- ['/path_params/', '-', '/download'],
- ['/path_params/', '', '/download'],
- ['/path_params/', '.', '/download'],
- ['/path_params/', '..', '/download'],
- ['/plain/path'],
- ];
-
- function paramPermutations(len: number): string[][] {
- if (len === 0) return [];
- if (len === 1) return testParams.map((e) => [e]);
- const rest = paramPermutations(len - 1);
- return testParams.flatMap((e) => rest.map((r) => [e, ...r]));
- }
-
- // We need to test how %2E is handled, so we use a custom encoder that does no escaping.
- const rawPath = createPathTagFunction((s) => s);
-
- const emptyObject = {};
- const mathObject = Math;
- const numberObject = new Number();
- const stringObject = new String();
- const basicClass = new (class {})();
- const classWithToString = new (class {
- toString() {
- return 'ok';
- }
- })();
-
- // Invalid values
- expect(() => rawPath`/a/${null}/b`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Null is not a valid path parameter\n' +
- '/a/null/b\n' +
- ' ^^^^',
- );
- expect(() => rawPath`/a/${undefined}/b`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Undefined is not a valid path parameter\n' +
- '/a/undefined/b\n' +
- ' ^^^^^^^^^',
- );
- expect(() => rawPath`/a/${emptyObject}/b`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Object is not a valid path parameter\n' +
- '/a/[object Object]/b\n' +
- ' ^^^^^^^^^^^^^^^',
- );
- expect(() => rawPath`?${mathObject}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Math is not a valid path parameter\n' +
- '?[object Math]\n' +
- ' ^^^^^^^^^^^^^',
- );
- expect(() => rawPath`/${basicClass}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Object is not a valid path parameter\n' +
- '/[object Object]\n' +
- ' ^^^^^^^^^^^^^^',
- );
- expect(() => rawPath`/../${''}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value ".." can\'t be safely passed as a path parameter\n' +
- '/../\n' +
- ' ^^',
- );
- expect(() => rawPath`/../${{}}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value ".." can\'t be safely passed as a path parameter\n' +
- 'Value of type Object is not a valid path parameter\n' +
- '/../[object Object]\n' +
- ' ^^ ^^^^^^^^^^^^^^',
- );
-
- // Valid values
- expect(rawPath`/${0}`).toBe('/0');
- expect(rawPath`/${''}`).toBe('/');
- expect(rawPath`/${numberObject}`).toBe('/0');
- expect(rawPath`${stringObject}/`).toBe('/');
- expect(rawPath`/${classWithToString}`).toBe('/ok');
-
- // We need to check what happens with cross-realm values, which we might get from
- // Jest or other frames in a browser.
-
- const newRealm = runInNewContext('globalThis');
- expect(newRealm.Object).not.toBe(Object);
-
- const crossRealmObject = newRealm.Object();
- const crossRealmMathObject = newRealm.Math;
- const crossRealmNumber = new newRealm.Number();
- const crossRealmString = new newRealm.String();
- const crossRealmClass = new (class extends newRealm.Object {})();
- const crossRealmClassWithToString = new (class extends newRealm.Object {
- toString() {
- return 'ok';
- }
- })();
-
- // Invalid cross-realm values
- expect(() => rawPath`/a/${crossRealmObject}/b`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Object is not a valid path parameter\n' +
- '/a/[object Object]/b\n' +
- ' ^^^^^^^^^^^^^^^',
- );
- expect(() => rawPath`?${crossRealmMathObject}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Math is not a valid path parameter\n' +
- '?[object Math]\n' +
- ' ^^^^^^^^^^^^^',
- );
- expect(() => rawPath`/${crossRealmClass}`).toThrow(
- 'Path parameters result in path with invalid segments:\n' +
- 'Value of type Object is not a valid path parameter\n' +
- '/[object Object]\n' +
- ' ^^^^^^^^^^^^^^^',
- );
-
- // Valid cross-realm values
- expect(rawPath`/${crossRealmNumber}`).toBe('/0');
- expect(rawPath`${crossRealmString}/`).toBe('/');
- expect(rawPath`/${crossRealmClassWithToString}`).toBe('/ok');
-
- const results: {
- [pathParts: string]: {
- [params: string]: { valid: boolean; result?: string; error?: string };
- };
- } = {};
-
- for (const pathParts of testCases) {
- const pathResults: Record<string, { valid: boolean; result?: string; error?: string }> = {};
- results[JSON.stringify(pathParts)] = pathResults;
- for (const params of paramPermutations(pathParts.length - 1)) {
- const stringRaw = String.raw({ raw: pathParts }, ...params);
- const plainString = String.raw(
- { raw: pathParts.map((e) => e.replace(/\./g, 'x')) },
- ...params.map((e) => 'X'.repeat(e.length)),
- );
- const normalizedStringRaw = new URL(stringRaw, 'https://example.com').href;
- const normalizedPlainString = new URL(plainString, 'https://example.com').href;
- const pathResultsKey = JSON.stringify(params);
- try {
- const result = rawPath(pathParts, ...params);
- expect(result).toBe(stringRaw);
- // there are no special segments, so the length of the normalized path is
- // equal to the length of the normalized plain path.
- expect(normalizedStringRaw.length).toBe(normalizedPlainString.length);
- pathResults[pathResultsKey] = {
- valid: true,
- result,
- };
- } catch (e) {
- const error = String(e);
- expect(error).toMatch(/Path parameters result in path with invalid segment/);
- // there are special segments, so the length of the normalized path is
- // different than the length of the normalized plain path.
- expect(normalizedStringRaw.length).not.toBe(normalizedPlainString.length);
- pathResults[pathResultsKey] = {
- valid: false,
- error,
- };
- }
- }
- }
-
- expect(results).toMatchObject({
- '["/path_params/","/a"]': {
- '["x"]': { valid: true, result: '/path_params/x/a' },
- '[""]': { valid: true, result: '/path_params//a' },
- '["%2E%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E%2e/a\n' +
- ' ^^^^^^',
- },
- '["%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E/a\n' +
- ' ^^^',
- },
- },
- '["/path_params/","/"]': {
- '["x"]': { valid: true, result: '/path_params/x/' },
- '[""]': { valid: true, result: '/path_params//' },
- '["%2e%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2e%2E/\n' +
- ' ^^^^^^',
- },
- '["%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2e" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2e/\n' +
- ' ^^^',
- },
- },
- '["/path_params/",""]': {
- '[""]': { valid: true, result: '/path_params/' },
- '["x"]': { valid: true, result: '/path_params/x' },
- '["%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E\n' +
- ' ^^^',
- },
- '["%2E%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E%2e\n' +
- ' ^^^^^^',
- },
- },
- '["","/a"]': {
- '[""]': { valid: true, result: '/a' },
- '["x"]': { valid: true, result: 'x/a' },
- '["%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E" can\'t be safely passed as a path parameter\n%2E/a\n^^^',
- },
- '["%2e%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' +
- '%2e%2E/a\n' +
- '^^^^^^',
- },
- },
- '["","/"]': {
- '["x"]': { valid: true, result: 'x/' },
- '[""]': { valid: true, result: '/' },
- '["%2E%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' +
- '%2E%2e/\n' +
- '^^^^^^',
- },
- '["."]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "." can\'t be safely passed as a path parameter\n' +
- './\n^',
- },
- },
- '["",""]': {
- '[""]': { valid: true, result: '' },
- '["x"]': { valid: true, result: 'x' },
- '[".."]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value ".." can\'t be safely passed as a path parameter\n' +
- '..\n^^',
- },
- '["."]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "." can\'t be safely passed as a path parameter\n' +
- '.\n^',
- },
- },
- '["a"]': {},
- '[""]': {},
- '["/path_params/",":initiate"]': {
- '[""]': { valid: true, result: '/path_params/:initiate' },
- '["."]': { valid: true, result: '/path_params/.:initiate' },
- },
- '["/path_params/",".json"]': {
- '["x"]': { valid: true, result: '/path_params/x.json' },
- '["."]': { valid: true, result: '/path_params/..json' },
- },
- '["/path_params/","?beta=true"]': {
- '["x"]': { valid: true, result: '/path_params/x?beta=true' },
- '[""]': { valid: true, result: '/path_params/?beta=true' },
- '["%2E%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E%2E?beta=true\n' +
- ' ^^^^^^',
- },
- '["%2e%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2e%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2e%2E?beta=true\n' +
- ' ^^^^^^',
- },
- },
- '["/path_params/",".?beta=true"]': {
- '[".."]': { valid: true, result: '/path_params/...?beta=true' },
- '["x"]': { valid: true, result: '/path_params/x.?beta=true' },
- '[""]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "." can\'t be safely passed as a path parameter\n' +
- '/path_params/.?beta=true\n' +
- ' ^',
- },
- '["%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2e." can\'t be safely passed as a path parameter\n' +
- '/path_params/%2e.?beta=true\n' +
- ' ^^^^',
- },
- },
- '["/path_params/","/","/download"]': {
- '["",""]': { valid: true, result: '/path_params///download' },
- '["","x"]': { valid: true, result: '/path_params//x/download' },
- '[".","%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "." can\'t be safely passed as a path parameter\n' +
- 'Value "%2e" can\'t be safely passed as a path parameter\n' +
- '/path_params/./%2e/download\n' +
- ' ^ ^^^',
- },
- '["%2E%2e","%2e"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E%2e" can\'t be safely passed as a path parameter\n' +
- 'Value "%2e" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E%2e/%2e/download\n' +
- ' ^^^^^^ ^^^',
- },
- },
- '["/path_params/","-","/download"]': {
- '["","%2e"]': { valid: true, result: '/path_params/-%2e/download' },
- '["%2E",".."]': { valid: true, result: '/path_params/%2E-../download' },
- },
- '["/path_params/","","/download"]': {
- '["%2E%2e","%2e%2E"]': { valid: true, result: '/path_params/%2E%2e%2e%2E/download' },
- '["%2E",".."]': { valid: true, result: '/path_params/%2E../download' },
- '["","%2E"]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E" can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E/download\n' +
- ' ^^^',
- },
- '["%2E","."]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "%2E." can\'t be safely passed as a path parameter\n' +
- '/path_params/%2E./download\n' +
- ' ^^^^',
- },
- },
- '["/path_params/",".","/download"]': {
- '["%2e%2e",""]': { valid: true, result: '/path_params/%2e%2e./download' },
- '["","%2e%2e"]': { valid: true, result: '/path_params/.%2e%2e/download' },
- '["",""]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value "." can\'t be safely passed as a path parameter\n' +
- '/path_params/./download\n' +
- ' ^',
- },
- '["","."]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value ".." can\'t be safely passed as a path parameter\n' +
- '/path_params/../download\n' +
- ' ^^',
- },
- },
- '["/path_params/","..","/download"]': {
- '["","%2E"]': { valid: true, result: '/path_params/..%2E/download' },
- '["","x"]': { valid: true, result: '/path_params/..x/download' },
- '["",""]': {
- valid: false,
- error:
- 'Error: Path parameters result in path with invalid segments:\n' +
- 'Value ".." can\'t be safely passed as a path parameter\n' +
- '/path_params/../download\n' +
- ' ^^',
- },
- },
- });
- });
-});
-
-describe('encodeURIPath', () => {
- const testCases: string[] = [
- '',
- // Every ASCII character
- ...Array.from({ length: 0x7f }, (_, i) => String.fromCharCode(i)),
- // Unicode BMP codepoint
- 'å',
- // Unicode supplementary codepoint
- '😃',
- ];
-
- for (const param of testCases) {
- test('properly encodes ' + inspect(param), () => {
- const encoded = encodeURIPath(param);
- const naiveEncoded = encodeURIComponent(param);
- // we should never encode more characters than encodeURIComponent
- expect(naiveEncoded.length).toBeGreaterThanOrEqual(encoded.length);
- expect(decodeURIComponent(encoded)).toBe(param);
- });
- }
-
- test("leaves ':' intact", () => {
- expect(encodeURIPath(':')).toBe(':');
- });
-
- test("leaves '@' intact", () => {
- expect(encodeURIPath('@')).toBe('@');
- });
-});
diff --git a/packages/sdk/tests/streaming.test.ts b/packages/sdk/tests/streaming.test.ts
deleted file mode 100644
index ea4bdad01..000000000
--- a/packages/sdk/tests/streaming.test.ts
+++ /dev/null
@@ -1,219 +0,0 @@
-import assert from 'assert';
-import { _iterSSEMessages } from '@opencode-ai/sdk/core/streaming';
-import { ReadableStreamFrom } from '@opencode-ai/sdk/internal/shims';
-
-describe('streaming decoding', () => {
- test('basic', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: completion\n');
- yield Buffer.from('data: {"foo":true}\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(JSON.parse(event.value.data)).toEqual({ foo: true });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('data without event', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('data: {"foo":true}\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toBeNull();
- expect(JSON.parse(event.value.data)).toEqual({ foo: true });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('event without data', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: foo\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('foo');
- expect(event.value.data).toEqual('');
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('multiple events', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: foo\n');
- yield Buffer.from('\n');
- yield Buffer.from('event: ping\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('foo');
- expect(event.value.data).toEqual('');
-
- event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('ping');
- expect(event.value.data).toEqual('');
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('multiple events with data', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: foo\n');
- yield Buffer.from('data: {"foo":true}\n');
- yield Buffer.from('\n');
- yield Buffer.from('event: ping\n');
- yield Buffer.from('data: {"bar":false}\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('foo');
- expect(JSON.parse(event.value.data)).toEqual({ foo: true });
-
- event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('ping');
- expect(JSON.parse(event.value.data)).toEqual({ bar: false });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('multiple data lines with empty line', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: ping\n');
- yield Buffer.from('data: {\n');
- yield Buffer.from('data: "foo":\n');
- yield Buffer.from('data: \n');
- yield Buffer.from('data:\n');
- yield Buffer.from('data: true}\n');
- yield Buffer.from('\n\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('ping');
- expect(JSON.parse(event.value.data)).toEqual({ foo: true });
- expect(event.value.data).toEqual('{\n"foo":\n\n\ntrue}');
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('data json escaped double new line', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: ping\n');
- yield Buffer.from('data: {"foo": "my long\\n\\ncontent"}');
- yield Buffer.from('\n\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('ping');
- expect(JSON.parse(event.value.data)).toEqual({ foo: 'my long\n\ncontent' });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('special new line characters', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('data: {"content": "culpa "}\n');
- yield Buffer.from('\n');
- yield Buffer.from('data: {"content": "');
- yield Buffer.from([0xe2, 0x80, 0xa8]);
- yield Buffer.from('"}\n');
- yield Buffer.from('\n');
- yield Buffer.from('data: {"content": "foo"}\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(JSON.parse(event.value.data)).toEqual({ content: 'culpa ' });
-
- event = await stream.next();
- assert(event.value);
- expect(JSON.parse(event.value.data)).toEqual({ content: Buffer.from([0xe2, 0x80, 0xa8]).toString() });
-
- event = await stream.next();
- assert(event.value);
- expect(JSON.parse(event.value.data)).toEqual({ content: 'foo' });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-
- test('multi-byte characters across chunks', async () => {
- async function* body(): AsyncGenerator<Buffer> {
- yield Buffer.from('event: completion\n');
- yield Buffer.from('data: {"content": "');
- // bytes taken from the string 'известни' and arbitrarily split
- // so that some multi-byte characters span multiple chunks
- yield Buffer.from([0xd0]);
- yield Buffer.from([0xb8, 0xd0, 0xb7, 0xd0]);
- yield Buffer.from([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8]);
- yield Buffer.from('"}\n');
- yield Buffer.from('\n');
- }
-
- const stream = _iterSSEMessages(new Response(ReadableStreamFrom(body())), new AbortController())[
- Symbol.asyncIterator
- ]();
-
- let event = await stream.next();
- assert(event.value);
- expect(event.value.event).toEqual('completion');
- expect(JSON.parse(event.value.data)).toEqual({ content: 'известни' });
-
- event = await stream.next();
- expect(event.done).toBeTruthy();
- });
-});
diff --git a/packages/sdk/tests/stringifyQuery.test.ts b/packages/sdk/tests/stringifyQuery.test.ts
deleted file mode 100644
index a028772d4..000000000
--- a/packages/sdk/tests/stringifyQuery.test.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-import { Opencode } from '@opencode-ai/sdk';
-
-const { stringifyQuery } = Opencode.prototype as any;
-
-describe(stringifyQuery, () => {
- for (const [input, expected] of [
- [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'],
- [{ a: null, b: false, c: undefined }, 'a=&b=false'],
- [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`],
- [
- { 'a/b': 'c/d', 'e=f': 'g&h' },
- `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent(
- 'e=f',
- )}=${encodeURIComponent('g&h')}`,
- ],
- ]) {
- it(`${JSON.stringify(input)} -> ${expected}`, () => {
- expect(stringifyQuery(input)).toEqual(expected);
- });
- }
-
- for (const value of [[], {}, new Date()]) {
- it(`${JSON.stringify(value)} -> <error>`, () => {
- expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`);
- });
- }
-});
diff --git a/packages/sdk/tests/uploads.test.ts b/packages/sdk/tests/uploads.test.ts
deleted file mode 100644
index c5e52ee09..000000000
--- a/packages/sdk/tests/uploads.test.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import fs from 'fs';
-import type { ResponseLike } from '@opencode-ai/sdk/internal/to-file';
-import { toFile } from '@opencode-ai/sdk/core/uploads';
-import { File } from 'node:buffer';
-
-class MyClass {
- name: string = 'foo';
-}
-
-function mockResponse({ url, content }: { url: string; content?: Blob }): ResponseLike {
- return {
- url,
- blob: async () => content || new Blob([]),
- };
-}
-
-describe('toFile', () => {
- it('throws a helpful error for mismatched types', async () => {
- await expect(
- // @ts-expect-error intentionally mismatched type
- toFile({ foo: 'string' }),
- ).rejects.toThrowErrorMatchingInlineSnapshot(
- `"Unexpected data type: object; constructor: Object; props: ["foo"]"`,
- );
-
- await expect(
- // @ts-expect-error intentionally mismatched type
- toFile(new MyClass()),
- ).rejects.toThrowErrorMatchingInlineSnapshot(
- `"Unexpected data type: object; constructor: MyClass; props: ["name"]"`,
- );
- });
-
- it('disallows string at the type-level', async () => {
- // @ts-expect-error we intentionally do not type support for `string`
- // to help people avoid passing a file path
- const file = await toFile('contents');
- expect(file.text()).resolves.toEqual('contents');
- });
-
- it('extracts a file name from a Response', async () => {
- const response = mockResponse({ url: 'https://example.com/my/audio.mp3' });
- const file = await toFile(response);
- expect(file.name).toEqual('audio.mp3');
- });
-
- it('extracts a file name from a File', async () => {
- const input = new File(['foo'], 'input.jsonl');
- const file = await toFile(input);
- expect(file.name).toEqual('input.jsonl');
- });
-
- it('extracts a file name from a ReadStream', async () => {
- const input = fs.createReadStream(__filename);
- const file = await toFile(input);
- expect(file.name).toEqual('uploads.test.ts');
- });
-
- it('does not copy File objects', async () => {
- const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' });
- const file = await toFile(input);
- expect(file).toBe(input);
- expect(file.name).toEqual('input.jsonl');
- expect(file.type).toBe('jsonl');
- });
-
- it('is assignable to File and Blob', async () => {
- const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' });
- const result = await toFile(input);
- const file: File = result;
- const blob: Blob = result;
- void file, blob;
- });
-});
-
-describe('missing File error message', () => {
- let prevGlobalFile: unknown;
- let prevNodeFile: unknown;
- beforeEach(() => {
- // The file shim captures the global File object when it's first imported.
- const buffer = require('node:buffer');
- // @ts-ignore
- prevGlobalFile = globalThis.File;
- prevNodeFile = buffer.File;
- // @ts-ignore
- globalThis.File = undefined;
- buffer.File = undefined;
- });
- afterEach(() => {
- // Clean up
- // @ts-ignore
- globalThis.File = prevGlobalFile;
- require('node:buffer').File = prevNodeFile;
- });
-
- test('is thrown', async () => {
- const uploads = await import('@opencode-ai/sdk/core/uploads');
- await expect(
- uploads.toFile(mockResponse({ url: 'https://example.com/my/audio.mp3' })),
- ).rejects.toMatchInlineSnapshot(
- `[Error: \`File\` is not defined as a global, which is required for file uploads.]`,
- );
- });
-});
diff --git a/packages/sdk/tsc-multi.json b/packages/sdk/tsc-multi.json
deleted file mode 100644
index 384ddac5b..000000000
--- a/packages/sdk/tsc-multi.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "targets": [
- {
- "extname": ".js",
- "module": "commonjs",
- "shareHelpers": "internal/tslib.js"
- },
- {
- "extname": ".mjs",
- "module": "esnext",
- "shareHelpers": "internal/tslib.mjs"
- }
- ],
- "projects": ["tsconfig.build.json"]
-}
diff --git a/packages/sdk/tsconfig.build.json b/packages/sdk/tsconfig.build.json
deleted file mode 100644
index 2421951bd..000000000
--- a/packages/sdk/tsconfig.build.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "include": ["dist/src"],
- "exclude": [],
- "compilerOptions": {
- "rootDir": "./dist/src",
- "paths": {
- "@opencode-ai/sdk/*": ["dist/src/*"],
- "@opencode-ai/sdk": ["dist/src/index.ts"]
- },
- "noEmit": false,
- "declaration": true,
- "declarationMap": true,
- "outDir": "dist",
- "pretty": true,
- "sourceMap": true
- }
-}
diff --git a/packages/sdk/tsconfig.deno.json b/packages/sdk/tsconfig.deno.json
deleted file mode 100644
index 849e070db..000000000
--- a/packages/sdk/tsconfig.deno.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "extends": "./tsconfig.json",
- "include": ["dist-deno"],
- "exclude": [],
- "compilerOptions": {
- "rootDir": "./dist-deno",
- "lib": ["es2020", "DOM"],
- "noEmit": true,
- "declaration": true,
- "declarationMap": true,
- "outDir": "dist-deno",
- "pretty": true,
- "sourceMap": true
- }
-}
diff --git a/packages/sdk/tsconfig.dist-src.json b/packages/sdk/tsconfig.dist-src.json
deleted file mode 100644
index c550e2996..000000000
--- a/packages/sdk/tsconfig.dist-src.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- // this config is included in the published src directory to prevent TS errors
- // from appearing when users go to source, and VSCode opens the source .ts file
- // via declaration maps
- "include": ["index.ts"],
- "compilerOptions": {
- "target": "ES2015",
- "lib": ["DOM", "DOM.Iterable", "ES2018"],
- "moduleResolution": "node"
- }
-}
diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json
deleted file mode 100644
index aafeb418f..000000000
--- a/packages/sdk/tsconfig.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "include": ["src", "tests", "examples"],
- "exclude": [],
- "compilerOptions": {
- "target": "es2020",
- "lib": ["es2020"],
- "module": "commonjs",
- "moduleResolution": "node",
- "esModuleInterop": true,
- "baseUrl": "./",
- "paths": {
- "@opencode-ai/sdk/*": ["src/*"],
- "@opencode-ai/sdk": ["src/index.ts"]
- },
- "noEmit": true,
-
- "resolveJsonModule": true,
-
- "forceConsistentCasingInFileNames": true,
-
- "strict": true,
- "noImplicitAny": true,
- "strictNullChecks": true,
- "strictFunctionTypes": true,
- "strictBindCallApply": true,
- "strictPropertyInitialization": true,
- "noImplicitThis": true,
- "noImplicitReturns": true,
- "alwaysStrict": true,
- "exactOptionalPropertyTypes": true,
- "noUncheckedIndexedAccess": true,
- "noImplicitOverride": true,
- "noPropertyAccessFromIndexSignature": true,
- "isolatedModules": false,
-
- "skipLibCheck": true
- }
-}
diff --git a/packages/sdk/yarn.lock b/packages/sdk/yarn.lock
deleted file mode 100644
index 58c08d5f1..000000000
--- a/packages/sdk/yarn.lock
+++ /dev/null
@@ -1,3500 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@aashutoshrathi/word-wrap@^1.2.3":
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
- integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
-
-"@ampproject/remapping@^2.2.0":
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630"
- integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==
- dependencies:
- "@jridgewell/gen-mapping" "^0.3.0"
- "@jridgewell/trace-mapping" "^0.3.9"
-
-"@andrewbranch/untar.js@^1.0.3":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00"
- integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==
-
-"@arethetypeswrong/cli@^0.17.0":
- version "0.17.0"
- resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac"
- integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA==
- dependencies:
- "@arethetypeswrong/core" "0.17.0"
- chalk "^4.1.2"
- cli-table3 "^0.6.3"
- commander "^10.0.1"
- marked "^9.1.2"
- marked-terminal "^7.1.0"
- semver "^7.5.4"
-
-"@arethetypeswrong/[email protected]":
- version "0.17.0"
- resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b"
- integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA==
- dependencies:
- "@andrewbranch/untar.js" "^1.0.3"
- cjs-module-lexer "^1.2.3"
- fflate "^0.8.2"
- lru-cache "^10.4.3"
- semver "^7.5.4"
- typescript "5.6.1-rc"
- validate-npm-package-name "^5.0.0"
-
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
- version "7.23.5"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
- integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
- dependencies:
- "@babel/highlight" "^7.23.4"
- chalk "^2.4.2"
-
-"@babel/compat-data@^7.23.5":
- version "7.23.5"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98"
- integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==
-
-"@babel/core@^7.11.6", "@babel/core@^7.12.3":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4"
- integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==
- dependencies:
- "@ampproject/remapping" "^2.2.0"
- "@babel/code-frame" "^7.23.5"
- "@babel/generator" "^7.23.6"
- "@babel/helper-compilation-targets" "^7.23.6"
- "@babel/helper-module-transforms" "^7.23.3"
- "@babel/helpers" "^7.23.6"
- "@babel/parser" "^7.23.6"
- "@babel/template" "^7.22.15"
- "@babel/traverse" "^7.23.6"
- "@babel/types" "^7.23.6"
- convert-source-map "^2.0.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.2"
- json5 "^2.2.3"
- semver "^6.3.1"
-
-"@babel/generator@^7.23.6", "@babel/generator@^7.7.2":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e"
- integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==
- dependencies:
- "@babel/types" "^7.23.6"
- "@jridgewell/gen-mapping" "^0.3.2"
- "@jridgewell/trace-mapping" "^0.3.17"
- jsesc "^2.5.1"
-
-"@babel/helper-compilation-targets@^7.23.6":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991"
- integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==
- dependencies:
- "@babel/compat-data" "^7.23.5"
- "@babel/helper-validator-option" "^7.23.5"
- browserslist "^4.22.2"
- lru-cache "^5.1.1"
- semver "^6.3.1"
-
-"@babel/helper-environment-visitor@^7.22.20":
- version "7.22.20"
- resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
- integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
-
-"@babel/helper-function-name@^7.23.0":
- version "7.23.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
- integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
- dependencies:
- "@babel/template" "^7.22.15"
- "@babel/types" "^7.23.0"
-
-"@babel/helper-hoist-variables@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
- integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
- dependencies:
- "@babel/types" "^7.22.5"
-
-"@babel/helper-module-imports@^7.22.15":
- version "7.22.15"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0"
- integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==
- dependencies:
- "@babel/types" "^7.22.15"
-
-"@babel/helper-module-transforms@^7.23.3":
- version "7.23.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1"
- integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==
- dependencies:
- "@babel/helper-environment-visitor" "^7.22.20"
- "@babel/helper-module-imports" "^7.22.15"
- "@babel/helper-simple-access" "^7.22.5"
- "@babel/helper-split-export-declaration" "^7.22.6"
- "@babel/helper-validator-identifier" "^7.22.20"
-
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
- integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
-
-"@babel/helper-simple-access@^7.22.5":
- version "7.22.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
- integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==
- dependencies:
- "@babel/types" "^7.22.5"
-
-"@babel/helper-split-export-declaration@^7.22.6":
- version "7.22.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
- integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
- dependencies:
- "@babel/types" "^7.22.5"
-
-"@babel/helper-string-parser@^7.23.4":
- version "7.23.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83"
- integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==
-
-"@babel/helper-validator-identifier@^7.22.20":
- version "7.22.20"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
- integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
-
-"@babel/helper-validator-option@^7.23.5":
- version "7.23.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
- integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
-
-"@babel/helpers@^7.23.6":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a"
- integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==
- dependencies:
- "@babel/template" "^7.22.15"
- "@babel/traverse" "^7.23.6"
- "@babel/types" "^7.23.6"
-
-"@babel/highlight@^7.23.4":
- version "7.23.4"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
- integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==
- dependencies:
- "@babel/helper-validator-identifier" "^7.22.20"
- chalk "^2.4.2"
- js-tokens "^4.0.0"
-
-"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b"
- integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==
-
-"@babel/plugin-syntax-async-generators@^7.8.4":
- version "7.8.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
- integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-bigint@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
- integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-class-properties@^7.8.3":
- version "7.12.13"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
- integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.12.13"
-
-"@babel/plugin-syntax-import-meta@^7.8.3":
- version "7.10.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
- integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-syntax-json-strings@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
- integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-jsx@^7.7.2":
- version "7.23.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473"
- integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.22.5"
-
-"@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
- version "7.10.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
- integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
- integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-numeric-separator@^7.8.3":
- version "7.10.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
- integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
- dependencies:
- "@babel/helper-plugin-utils" "^7.10.4"
-
-"@babel/plugin-syntax-object-rest-spread@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
- integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
- integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-optional-chaining@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
- integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-top-level-await@^7.8.3":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
- integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
- dependencies:
- "@babel/helper-plugin-utils" "^7.14.5"
-
-"@babel/plugin-syntax-typescript@^7.7.2":
- version "7.23.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f"
- integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.22.5"
-
-"@babel/template@^7.22.15", "@babel/template@^7.3.3":
- version "7.22.15"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
- integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
- dependencies:
- "@babel/code-frame" "^7.22.13"
- "@babel/parser" "^7.22.15"
- "@babel/types" "^7.22.15"
-
-"@babel/traverse@^7.23.6":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5"
- integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==
- dependencies:
- "@babel/code-frame" "^7.23.5"
- "@babel/generator" "^7.23.6"
- "@babel/helper-environment-visitor" "^7.22.20"
- "@babel/helper-function-name" "^7.23.0"
- "@babel/helper-hoist-variables" "^7.22.5"
- "@babel/helper-split-export-declaration" "^7.22.6"
- "@babel/parser" "^7.23.6"
- "@babel/types" "^7.23.6"
- debug "^4.3.1"
- globals "^11.1.0"
-
-"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3":
- version "7.23.6"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd"
- integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==
- dependencies:
- "@babel/helper-string-parser" "^7.23.4"
- "@babel/helper-validator-identifier" "^7.22.20"
- to-fast-properties "^2.0.0"
-
-"@bcoe/v8-coverage@^0.2.3":
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
- integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-
-"@colors/[email protected]":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
- integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
-
-"@cspotcode/[email protected]":
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
- integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
-
-"@cspotcode/[email protected]":
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
- integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
- dependencies:
- "@cspotcode/source-map-consumer" "0.8.0"
-
-"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
- integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
- dependencies:
- eslint-visitor-keys "^3.3.0"
-
-"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1":
- version "4.12.1"
- resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
- integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
-
-"@eslint/config-array@^0.19.0":
- version "0.19.2"
- resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa"
- integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==
- dependencies:
- "@eslint/object-schema" "^2.1.6"
- debug "^4.3.1"
- minimatch "^3.1.2"
-
-"@eslint/core@^0.10.0":
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091"
- integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==
- dependencies:
- "@types/json-schema" "^7.0.15"
-
-"@eslint/core@^0.11.0":
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12"
- integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==
- dependencies:
- "@types/json-schema" "^7.0.15"
-
-"@eslint/eslintrc@^3.2.0":
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c"
- integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==
- dependencies:
- ajv "^6.12.4"
- debug "^4.3.2"
- espree "^10.0.1"
- globals "^14.0.0"
- ignore "^5.2.0"
- import-fresh "^3.2.1"
- js-yaml "^4.1.0"
- minimatch "^3.1.2"
- strip-json-comments "^3.1.1"
-
-"@eslint/[email protected]":
- version "9.20.0"
- resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4"
- integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==
-
-"@eslint/object-schema@^2.1.6":
- version "2.1.6"
- resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f"
- integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==
-
-"@eslint/plugin-kit@^0.2.5":
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81"
- integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==
- dependencies:
- "@eslint/core" "^0.10.0"
- levn "^0.4.1"
-
-"@humanfs/core@^0.19.1":
- version "0.19.1"
- resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
- integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==
-
-"@humanfs/node@^0.16.6":
- version "0.16.6"
- resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e"
- integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==
- dependencies:
- "@humanfs/core" "^0.19.1"
- "@humanwhocodes/retry" "^0.3.0"
-
-"@humanwhocodes/module-importer@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
- integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
-
-"@humanwhocodes/retry@^0.3.0":
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
- integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
-
-"@humanwhocodes/retry@^0.4.1":
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b"
- integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==
-
-"@istanbuljs/load-nyc-config@^1.0.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
- integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==
- dependencies:
- camelcase "^5.3.1"
- find-up "^4.1.0"
- get-package-type "^0.1.0"
- js-yaml "^3.13.1"
- resolve-from "^5.0.0"
-
-"@istanbuljs/schema@^0.1.2":
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
- integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
-
-"@jest/console@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc"
- integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==
- dependencies:
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- chalk "^4.0.0"
- jest-message-util "^29.7.0"
- jest-util "^29.7.0"
- slash "^3.0.0"
-
-"@jest/core@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f"
- integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==
- dependencies:
- "@jest/console" "^29.7.0"
- "@jest/reporters" "^29.7.0"
- "@jest/test-result" "^29.7.0"
- "@jest/transform" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- ansi-escapes "^4.2.1"
- chalk "^4.0.0"
- ci-info "^3.2.0"
- exit "^0.1.2"
- graceful-fs "^4.2.9"
- jest-changed-files "^29.7.0"
- jest-config "^29.7.0"
- jest-haste-map "^29.7.0"
- jest-message-util "^29.7.0"
- jest-regex-util "^29.6.3"
- jest-resolve "^29.7.0"
- jest-resolve-dependencies "^29.7.0"
- jest-runner "^29.7.0"
- jest-runtime "^29.7.0"
- jest-snapshot "^29.7.0"
- jest-util "^29.7.0"
- jest-validate "^29.7.0"
- jest-watcher "^29.7.0"
- micromatch "^4.0.4"
- pretty-format "^29.7.0"
- slash "^3.0.0"
- strip-ansi "^6.0.0"
-
-"@jest/create-cache-key-function@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0"
- integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==
- dependencies:
- "@jest/types" "^29.6.3"
-
-"@jest/environment@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
- integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
- dependencies:
- "@jest/fake-timers" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- jest-mock "^29.7.0"
-
-"@jest/expect-utils@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6"
- integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==
- dependencies:
- jest-get-type "^29.6.3"
-
-"@jest/expect@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2"
- integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==
- dependencies:
- expect "^29.7.0"
- jest-snapshot "^29.7.0"
-
-"@jest/fake-timers@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
- integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
- dependencies:
- "@jest/types" "^29.6.3"
- "@sinonjs/fake-timers" "^10.0.2"
- "@types/node" "*"
- jest-message-util "^29.7.0"
- jest-mock "^29.7.0"
- jest-util "^29.7.0"
-
-"@jest/globals@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d"
- integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==
- dependencies:
- "@jest/environment" "^29.7.0"
- "@jest/expect" "^29.7.0"
- "@jest/types" "^29.6.3"
- jest-mock "^29.7.0"
-
-"@jest/reporters@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7"
- integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==
- dependencies:
- "@bcoe/v8-coverage" "^0.2.3"
- "@jest/console" "^29.7.0"
- "@jest/test-result" "^29.7.0"
- "@jest/transform" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@jridgewell/trace-mapping" "^0.3.18"
- "@types/node" "*"
- chalk "^4.0.0"
- collect-v8-coverage "^1.0.0"
- exit "^0.1.2"
- glob "^7.1.3"
- graceful-fs "^4.2.9"
- istanbul-lib-coverage "^3.0.0"
- istanbul-lib-instrument "^6.0.0"
- istanbul-lib-report "^3.0.0"
- istanbul-lib-source-maps "^4.0.0"
- istanbul-reports "^3.1.3"
- jest-message-util "^29.7.0"
- jest-util "^29.7.0"
- jest-worker "^29.7.0"
- slash "^3.0.0"
- string-length "^4.0.1"
- strip-ansi "^6.0.0"
- v8-to-istanbul "^9.0.1"
-
-"@jest/schemas@^29.6.3":
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
- integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
- dependencies:
- "@sinclair/typebox" "^0.27.8"
-
-"@jest/source-map@^29.6.3":
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4"
- integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==
- dependencies:
- "@jridgewell/trace-mapping" "^0.3.18"
- callsites "^3.0.0"
- graceful-fs "^4.2.9"
-
-"@jest/test-result@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c"
- integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==
- dependencies:
- "@jest/console" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/istanbul-lib-coverage" "^2.0.0"
- collect-v8-coverage "^1.0.0"
-
-"@jest/test-sequencer@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce"
- integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==
- dependencies:
- "@jest/test-result" "^29.7.0"
- graceful-fs "^4.2.9"
- jest-haste-map "^29.7.0"
- slash "^3.0.0"
-
-"@jest/transform@^29.7.0":
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c"
- integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==
- dependencies:
- "@babel/core" "^7.11.6"
- "@jest/types" "^29.6.3"
- "@jridgewell/trace-mapping" "^0.3.18"
- babel-plugin-istanbul "^6.1.1"
- chalk "^4.0.0"
- convert-source-map "^2.0.0"
- fast-json-stable-stringify "^2.1.0"
- graceful-fs "^4.2.9"
- jest-haste-map "^29.7.0"
- jest-regex-util "^29.6.3"
- jest-util "^29.7.0"
- micromatch "^4.0.4"
- pirates "^4.0.4"
- slash "^3.0.0"
- write-file-atomic "^4.0.2"
-
-"@jest/types@^29.6.3":
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
- integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
- dependencies:
- "@jest/schemas" "^29.6.3"
- "@types/istanbul-lib-coverage" "^2.0.0"
- "@types/istanbul-reports" "^3.0.0"
- "@types/node" "*"
- "@types/yargs" "^17.0.8"
- chalk "^4.0.0"
-
-"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
- integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
- dependencies:
- "@jridgewell/set-array" "^1.0.1"
- "@jridgewell/sourcemap-codec" "^1.4.10"
- "@jridgewell/trace-mapping" "^0.3.9"
-
-"@jridgewell/resolve-uri@^3.1.0":
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
- integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
-
-"@jridgewell/set-array@^1.0.1":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
- integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
-
-"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
- version "1.4.15"
- resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
- integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
-
-"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9":
- version "0.3.20"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
- integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
- dependencies:
- "@jridgewell/resolve-uri" "^3.1.0"
- "@jridgewell/sourcemap-codec" "^1.4.14"
-
-"@nodelib/[email protected]":
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
- integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
- dependencies:
- "@nodelib/fs.stat" "2.0.5"
- run-parallel "^1.1.9"
-
-"@nodelib/[email protected]", "@nodelib/fs.stat@^2.0.2":
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
- integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
-
-"@nodelib/fs.walk@^1.2.3":
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
- integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
- dependencies:
- "@nodelib/fs.scandir" "2.1.5"
- fastq "^1.6.0"
-
-"@pkgr/core@^0.2.4":
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c"
- integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==
-
-"@sinclair/typebox@^0.27.8":
- version "0.27.8"
- resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
- integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
-
-"@sindresorhus/is@^4.6.0":
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
- integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
-
-"@sinonjs/commons@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72"
- integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==
- dependencies:
- type-detect "4.0.8"
-
-"@sinonjs/fake-timers@^10.0.2":
- version "10.3.0"
- resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66"
- integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==
- dependencies:
- "@sinonjs/commons" "^3.0.0"
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.16.tgz#2cd45d709ce76d448d96bf8d0006849541436611"
- integrity sha512-UOCcH1GvjRnnM/LWT6VCGpIk0OhHRq6v1U6QXuPt5wVsgXnXQwnf5k3sG5Cm56hQHDvhRPY6HCsHi/p0oek8oQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.16.tgz#a5bc7d8b1dd850adb0bb95c6b5c742b92201fd01"
- integrity sha512-t3bgqFoYLWvyVtVL6KkFNCINEoOrIlyggT/kJRgi1y0aXSr0oVgcrQ4ezJpdeahZZ4N+Q6vT3ffM30yIunELNA==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.16.tgz#961744908ee5cbb79bc009dcf58cc8b831111f38"
- integrity sha512-DvHuwvEF86YvSd0lwnzVcjOTZ0jcxewIbsN0vc/0fqm9qBdMMjr9ox6VCam1n3yYeRtj4VFgrjeNFksqbUejdQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.16.tgz#43713be3f26757d82d2745dc25f8b63400e0a3d0"
- integrity sha512-9Uu5YlPbyCvbidjKtYEsPpyZlu16roOZ5c2tP1vHfnU9bgf5Tz5q5VovSduNxPHx+ed2iC1b1URODHvDzbbDuQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.16.tgz#394a7d030f3a61902bd3947bb9d70d26d42f3c81"
- integrity sha512-/YZq/qB1CHpeoL0eMzyqK5/tYZn/rzKoCYDviFU4uduSUIJsDJQuQA/skdqUzqbheOXKAd4mnJ1hT04RbJ8FPQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz#71eb108b784f9d551ee8a35ebcdaed972f567981"
- integrity sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz#10dbaedb4e3dfc7268e3a9a66ad3431471ef035b"
- integrity sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.16.tgz#80247adff6c245ff32b44d773c1a148858cd655f"
- integrity sha512-bTD43MbhIHL2s5QgCwyleaGwl96Gk/scF2TaVKdUe4QlJCDV/YK9h5oIBAp63ckHtE8GHlH4c8dZNBiAXn4Org==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.16.tgz#e540afc3ccf3224267b4ddfb408f9d9737984686"
- integrity sha512-/lmZeAN/qV5XbK2SEvi8e2RkIg8FQNYiSA8y2/Zb4gTUMKVO5JMLH0BSWMiIKMstKDPDSxMWgwJaQHF8UMyPmQ==
-
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.16.tgz#f880939fca32c181adfe7e3abd2b6b7857bd3489"
- integrity sha512-BPAfFfODWXtUu6SwaTTftDHvcbDyWBSI/oanUeRbQR5vVWkXoQ3cxLTsDluc3H74IqXS5z1Uyoe0vNo2hB1opA==
-
-"@swc/core@^1.3.102":
- version "1.4.16"
- resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.16.tgz#d175bae2acfecd53bcbd4293f1fba5ec316634a0"
- integrity sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA==
- dependencies:
- "@swc/counter" "^0.1.2"
- "@swc/types" "^0.1.5"
- optionalDependencies:
- "@swc/core-darwin-arm64" "1.4.16"
- "@swc/core-darwin-x64" "1.4.16"
- "@swc/core-linux-arm-gnueabihf" "1.4.16"
- "@swc/core-linux-arm64-gnu" "1.4.16"
- "@swc/core-linux-arm64-musl" "1.4.16"
- "@swc/core-linux-x64-gnu" "1.4.16"
- "@swc/core-linux-x64-musl" "1.4.16"
- "@swc/core-win32-arm64-msvc" "1.4.16"
- "@swc/core-win32-ia32-msvc" "1.4.16"
- "@swc/core-win32-x64-msvc" "1.4.16"
-
-"@swc/counter@^0.1.2", "@swc/counter@^0.1.3":
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9"
- integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
-
-"@swc/jest@^0.2.29":
- version "0.2.36"
- resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.36.tgz#2797450a30d28b471997a17e901ccad946fe693e"
- integrity sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==
- dependencies:
- "@jest/create-cache-key-function" "^29.7.0"
- "@swc/counter" "^0.1.3"
- jsonc-parser "^3.2.0"
-
-"@swc/types@^0.1.5":
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba"
- integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==
- dependencies:
- "@swc/counter" "^0.1.3"
-
-"@tsconfig/node10@^1.0.7":
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
- integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==
-
-"@tsconfig/node12@^1.0.7":
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c"
- integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==
-
-"@tsconfig/node14@^1.0.0":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2"
- integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
-
-"@tsconfig/node16@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
- integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
-
-"@types/babel__core@^7.1.14":
- version "7.20.5"
- resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
- integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==
- dependencies:
- "@babel/parser" "^7.20.7"
- "@babel/types" "^7.20.7"
- "@types/babel__generator" "*"
- "@types/babel__template" "*"
- "@types/babel__traverse" "*"
-
-"@types/babel__generator@*":
- version "7.6.8"
- resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab"
- integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==
- dependencies:
- "@babel/types" "^7.0.0"
-
-"@types/babel__template@*":
- version "7.4.4"
- resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f"
- integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==
- dependencies:
- "@babel/parser" "^7.1.0"
- "@babel/types" "^7.0.0"
-
-"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
- version "7.20.4"
- resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b"
- integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==
- dependencies:
- "@babel/types" "^7.20.7"
-
-"@types/estree@^1.0.6":
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
- integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
-
-"@types/graceful-fs@^4.1.3":
- version "4.1.9"
- resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4"
- integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==
- dependencies:
- "@types/node" "*"
-
-"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
- integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==
-
-"@types/istanbul-lib-report@*":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf"
- integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==
- dependencies:
- "@types/istanbul-lib-coverage" "*"
-
-"@types/istanbul-reports@^3.0.0":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54"
- integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==
- dependencies:
- "@types/istanbul-lib-report" "*"
-
-"@types/jest@^29.4.0":
- version "29.5.11"
- resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c"
- integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==
- dependencies:
- expect "^29.0.0"
- pretty-format "^29.0.0"
-
-"@types/json-schema@^7.0.15":
- version "7.0.15"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
- integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
-
-"@types/node@*":
- version "20.10.5"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2"
- integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==
- dependencies:
- undici-types "~5.26.4"
-
-"@types/node@^20.17.6":
- version "20.17.6"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.6.tgz#6e4073230c180d3579e8c60141f99efdf5df0081"
- integrity sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==
- dependencies:
- undici-types "~6.19.2"
-
-"@types/stack-utils@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
- integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
-
-"@types/yargs-parser@*":
- version "21.0.3"
- resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
- integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==
-
-"@types/yargs@^17.0.8":
- version "17.0.32"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229"
- integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==
- dependencies:
- "@types/yargs-parser" "*"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a"
- integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==
- dependencies:
- "@eslint-community/regexpp" "^4.10.0"
- "@typescript-eslint/scope-manager" "8.31.1"
- "@typescript-eslint/type-utils" "8.31.1"
- "@typescript-eslint/utils" "8.31.1"
- "@typescript-eslint/visitor-keys" "8.31.1"
- graphemer "^1.4.0"
- ignore "^5.3.1"
- natural-compare "^1.4.0"
- ts-api-utils "^2.0.1"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b"
- integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==
- dependencies:
- "@typescript-eslint/scope-manager" "8.31.1"
- "@typescript-eslint/types" "8.31.1"
- "@typescript-eslint/typescript-estree" "8.31.1"
- "@typescript-eslint/visitor-keys" "8.31.1"
- debug "^4.3.4"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b"
- integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==
- dependencies:
- "@typescript-eslint/types" "8.31.1"
- "@typescript-eslint/visitor-keys" "8.31.1"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c"
- integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==
- dependencies:
- "@typescript-eslint/typescript-estree" "8.31.1"
- "@typescript-eslint/utils" "8.31.1"
- debug "^4.3.4"
- ts-api-utils "^2.0.1"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4"
- integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf"
- integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==
- dependencies:
- "@typescript-eslint/types" "8.31.1"
- "@typescript-eslint/visitor-keys" "8.31.1"
- debug "^4.3.4"
- fast-glob "^3.3.2"
- is-glob "^4.0.3"
- minimatch "^9.0.4"
- semver "^7.6.0"
- ts-api-utils "^2.0.1"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14"
- integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==
- dependencies:
- "@eslint-community/eslint-utils" "^4.4.0"
- "@typescript-eslint/scope-manager" "8.31.1"
- "@typescript-eslint/types" "8.31.1"
- "@typescript-eslint/typescript-estree" "8.31.1"
-
-"@typescript-eslint/[email protected]":
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75"
- integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==
- dependencies:
- "@typescript-eslint/types" "8.31.1"
- eslint-visitor-keys "^4.2.0"
-
-acorn-jsx@^5.3.2:
- version "5.3.2"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
- integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-
-acorn-walk@^8.1.1:
- version "8.2.0"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
- integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
-
-acorn@^8.14.0:
- version "8.14.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
- integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
-
-acorn@^8.4.1:
- version "8.7.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
- integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
-
-aggregate-error@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
- integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
- dependencies:
- clean-stack "^2.0.0"
- indent-string "^4.0.0"
-
-ajv@^6.12.4:
- version "6.12.6"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
- integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
- dependencies:
- fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
-
-ansi-escapes@^4.2.1:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
- integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
- dependencies:
- type-fest "^0.21.3"
-
-ansi-escapes@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7"
- integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==
- dependencies:
- environment "^1.0.0"
-
-ansi-regex@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
- integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-
-ansi-regex@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
- integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.0.0, ansi-styles@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
- dependencies:
- color-convert "^2.0.1"
-
-ansi-styles@^5.0.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
- integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
-
-any-promise@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
- integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
-
-anymatch@^3.0.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
- integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
- dependencies:
- normalize-path "^3.0.0"
- picomatch "^2.0.4"
-
-arg@^4.1.0:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
- integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
-
-argparse@^1.0.7:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
- integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
- dependencies:
- sprintf-js "~1.0.2"
-
-argparse@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
- integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-
-babel-jest@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5"
- integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==
- dependencies:
- "@jest/transform" "^29.7.0"
- "@types/babel__core" "^7.1.14"
- babel-plugin-istanbul "^6.1.1"
- babel-preset-jest "^29.6.3"
- chalk "^4.0.0"
- graceful-fs "^4.2.9"
- slash "^3.0.0"
-
-babel-plugin-istanbul@^6.1.1:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
- integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.0.0"
- "@istanbuljs/load-nyc-config" "^1.0.0"
- "@istanbuljs/schema" "^0.1.2"
- istanbul-lib-instrument "^5.0.4"
- test-exclude "^6.0.0"
-
-babel-plugin-jest-hoist@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626"
- integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==
- dependencies:
- "@babel/template" "^7.3.3"
- "@babel/types" "^7.3.3"
- "@types/babel__core" "^7.1.14"
- "@types/babel__traverse" "^7.0.6"
-
-babel-preset-current-node-syntax@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
- integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==
- dependencies:
- "@babel/plugin-syntax-async-generators" "^7.8.4"
- "@babel/plugin-syntax-bigint" "^7.8.3"
- "@babel/plugin-syntax-class-properties" "^7.8.3"
- "@babel/plugin-syntax-import-meta" "^7.8.3"
- "@babel/plugin-syntax-json-strings" "^7.8.3"
- "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3"
- "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
- "@babel/plugin-syntax-numeric-separator" "^7.8.3"
- "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
- "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
- "@babel/plugin-syntax-optional-chaining" "^7.8.3"
- "@babel/plugin-syntax-top-level-await" "^7.8.3"
-
-babel-preset-jest@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c"
- integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==
- dependencies:
- babel-plugin-jest-hoist "^29.6.3"
- babel-preset-current-node-syntax "^1.0.0"
-
-balanced-match@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
- integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-brace-expansion@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
- integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
- dependencies:
- balanced-match "^1.0.0"
-
-braces@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
- integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
- dependencies:
- fill-range "^7.1.1"
-
-browserslist@^4.22.2:
- version "4.22.2"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b"
- integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==
- dependencies:
- caniuse-lite "^1.0.30001565"
- electron-to-chromium "^1.4.601"
- node-releases "^2.0.14"
- update-browserslist-db "^1.0.13"
-
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
- integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
- dependencies:
- fast-json-stable-stringify "2.x"
-
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
- integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
- dependencies:
- node-int64 "^0.4.0"
-
-buffer-from@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
- integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
-
-callsites@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
- integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-camelcase@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
- integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-
-camelcase@^6.2.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
- integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-
-caniuse-lite@^1.0.30001565:
- version "1.0.30001570"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca"
- integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==
-
-chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^4.0.0, chalk@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
- integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chalk@^5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
- integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
-
-char-regex@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
- integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
-
-ci-info@^3.2.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
- integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
-
-cjs-module-lexer@^1.0.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107"
- integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==
-
-cjs-module-lexer@^1.2.3:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170"
- integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==
-
-clean-stack@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
- integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-
-cli-highlight@^2.1.11:
- version "2.1.11"
- resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf"
- integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==
- dependencies:
- chalk "^4.0.0"
- highlight.js "^10.7.1"
- mz "^2.4.0"
- parse5 "^5.1.1"
- parse5-htmlparser2-tree-adapter "^6.0.0"
- yargs "^16.0.0"
-
-cli-table3@^0.6.3, cli-table3@^0.6.5:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f"
- integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==
- dependencies:
- string-width "^4.2.0"
- optionalDependencies:
- "@colors/colors" "1.5.0"
-
-cliui@^7.0.2:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
- integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
- dependencies:
- string-width "^4.2.0"
- strip-ansi "^6.0.0"
- wrap-ansi "^7.0.0"
-
-cliui@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
- integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
- dependencies:
- string-width "^4.2.0"
- strip-ansi "^6.0.1"
- wrap-ansi "^7.0.0"
-
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
-
-collect-v8-coverage@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9"
- integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==
-
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
-
-color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-commander@^10.0.1:
- version "10.0.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
- integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
-
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
-
-convert-source-map@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
- integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
-
-create-jest@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320"
- integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==
- dependencies:
- "@jest/types" "^29.6.3"
- chalk "^4.0.0"
- exit "^0.1.2"
- graceful-fs "^4.2.9"
- jest-config "^29.7.0"
- jest-util "^29.7.0"
- prompts "^2.0.1"
-
-create-require@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
- integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
-
-cross-spawn@^7.0.3, cross-spawn@^7.0.6:
- version "7.0.6"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
- integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
-
-debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
- integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
- dependencies:
- ms "2.1.2"
-
-debug@^4.3.4, debug@^4.3.7:
- version "4.3.7"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
- integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
- dependencies:
- ms "^2.1.3"
-
-dedent@^1.0.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff"
- integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==
-
-deep-is@^0.1.3:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
- integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
-
-deepmerge@^4.2.2:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
- integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
-
-detect-newline@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
- integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
-
-diff-sequences@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
- integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
-
-diff@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
- integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
-
-electron-to-chromium@^1.4.601:
- version "1.4.614"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0"
- integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ==
-
-emittery@^0.13.1:
- version "0.13.1"
- resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
- integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==
-
-emoji-regex@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
- integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-emojilib@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e"
- integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==
-
-environment@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1"
- integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==
-
-error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-escalade@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
- integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
-
-escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
-
-escape-string-regexp@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
- integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
-
-escape-string-regexp@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
- integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-
-eslint-plugin-prettier@^5.4.1:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af"
- integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==
- dependencies:
- prettier-linter-helpers "^1.0.0"
- synckit "^0.11.7"
-
-eslint-plugin-unused-imports@^4.1.4:
- version "4.1.4"
- resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738"
- integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==
-
-eslint-scope@^8.2.0:
- version "8.2.0"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442"
- integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==
- dependencies:
- esrecurse "^4.3.0"
- estraverse "^5.2.0"
-
-eslint-visitor-keys@^3.3.0:
- version "3.4.3"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
- integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
-
-eslint-visitor-keys@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
- integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
-
-eslint@^9.20.1:
- version "9.20.1"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6"
- integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==
- dependencies:
- "@eslint-community/eslint-utils" "^4.2.0"
- "@eslint-community/regexpp" "^4.12.1"
- "@eslint/config-array" "^0.19.0"
- "@eslint/core" "^0.11.0"
- "@eslint/eslintrc" "^3.2.0"
- "@eslint/js" "9.20.0"
- "@eslint/plugin-kit" "^0.2.5"
- "@humanfs/node" "^0.16.6"
- "@humanwhocodes/module-importer" "^1.0.1"
- "@humanwhocodes/retry" "^0.4.1"
- "@types/estree" "^1.0.6"
- "@types/json-schema" "^7.0.15"
- ajv "^6.12.4"
- chalk "^4.0.0"
- cross-spawn "^7.0.6"
- debug "^4.3.2"
- escape-string-regexp "^4.0.0"
- eslint-scope "^8.2.0"
- eslint-visitor-keys "^4.2.0"
- espree "^10.3.0"
- esquery "^1.5.0"
- esutils "^2.0.2"
- fast-deep-equal "^3.1.3"
- file-entry-cache "^8.0.0"
- find-up "^5.0.0"
- glob-parent "^6.0.2"
- ignore "^5.2.0"
- imurmurhash "^0.1.4"
- is-glob "^4.0.0"
- json-stable-stringify-without-jsonify "^1.0.1"
- lodash.merge "^4.6.2"
- minimatch "^3.1.2"
- natural-compare "^1.4.0"
- optionator "^0.9.3"
-
-espree@^10.0.1, espree@^10.3.0:
- version "10.3.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
- integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
- dependencies:
- acorn "^8.14.0"
- acorn-jsx "^5.3.2"
- eslint-visitor-keys "^4.2.0"
-
-esprima@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
- integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
-esquery@^1.5.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
- integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
- dependencies:
- estraverse "^5.1.0"
-
-esrecurse@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
- integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
- dependencies:
- estraverse "^5.2.0"
-
-estraverse@^5.1.0, estraverse@^5.2.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
- integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
-
-esutils@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
- integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
-
-execa@^5.0.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
- integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
- dependencies:
- cross-spawn "^7.0.3"
- get-stream "^6.0.0"
- human-signals "^2.1.0"
- is-stream "^2.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^4.0.1"
- onetime "^5.1.2"
- signal-exit "^3.0.3"
- strip-final-newline "^2.0.0"
-
-exit@^0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
- integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==
-
-expect@^29.0.0, expect@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc"
- integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==
- dependencies:
- "@jest/expect-utils" "^29.7.0"
- jest-get-type "^29.6.3"
- jest-matcher-utils "^29.7.0"
- jest-message-util "^29.7.0"
- jest-util "^29.7.0"
-
-fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-diff@^1.1.2:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
- integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
-
-fast-glob@^3.3.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
- integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
- dependencies:
- "@nodelib/fs.stat" "^2.0.2"
- "@nodelib/fs.walk" "^1.2.3"
- glob-parent "^5.1.2"
- merge2 "^1.3.0"
- micromatch "^4.0.4"
-
[email protected], fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
- integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-fast-levenshtein@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
- integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
-
-fastq@^1.6.0:
- version "1.17.1"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
- integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
- dependencies:
- reusify "^1.0.4"
-
-fb-watchman@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c"
- integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==
- dependencies:
- bser "2.1.1"
-
-fflate@^0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea"
- integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==
-
-file-entry-cache@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
- integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
- dependencies:
- flat-cache "^4.0.0"
-
-fill-range@^7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
- integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
- dependencies:
- to-regex-range "^5.0.1"
-
-find-up@^4.0.0, find-up@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
- integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
- dependencies:
- locate-path "^5.0.0"
- path-exists "^4.0.0"
-
-find-up@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
- integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
- dependencies:
- locate-path "^6.0.0"
- path-exists "^4.0.0"
-
-flat-cache@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
- integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
- dependencies:
- flatted "^3.2.9"
- keyv "^4.5.4"
-
-flatted@^3.2.9:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27"
- integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-
-fsevents@^2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
-function-bind@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
- integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
-
-gensync@^1.0.0-beta.2:
- version "1.0.0-beta.2"
- resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
- integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
-
-get-caller-file@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
- integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-
-get-package-type@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
- integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
-
-get-stdin@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
- integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
-
-get-stream@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
- integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
-
-glob-parent@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
- integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
- dependencies:
- is-glob "^4.0.1"
-
-glob-parent@^6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
- integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
- dependencies:
- is-glob "^4.0.3"
-
-glob@^7.1.3, glob@^7.1.4:
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
- integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.1.1"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@^8.0.1:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
- integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^5.0.1"
- once "^1.3.0"
-
-globals@^11.1.0:
- version "11.12.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
- integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-
-globals@^14.0.0:
- version "14.0.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
- integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
-
-graceful-fs@^4.2.9:
- version "4.2.11"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
- integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
-
-graphemer@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
- integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-hasown@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
- integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
- dependencies:
- function-bind "^1.1.2"
-
-highlight.js@^10.7.1:
- version "10.7.3"
- resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
- integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
-
-html-escaper@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
- integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
-
-human-signals@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
- integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
-
-iconv-lite@^0.6.3:
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
- integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
- dependencies:
- safer-buffer ">= 2.1.2 < 3.0.0"
-
-ignore-walk@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776"
- integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==
- dependencies:
- minimatch "^5.0.1"
-
-ignore@^5.2.0, ignore@^5.3.1:
- version "5.3.2"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
- integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
-
-import-fresh@^3.2.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
- integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
- dependencies:
- parent-module "^1.0.0"
- resolve-from "^4.0.0"
-
-import-local@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
- integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
- dependencies:
- pkg-dir "^4.2.0"
- resolve-cwd "^3.0.0"
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
-
-indent-string@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
- integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@^2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
-
-is-core-module@^2.13.0:
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
- integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
- dependencies:
- hasown "^2.0.0"
-
-is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
-
-is-fullwidth-code-point@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
- integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-generator-fn@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
- integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
-
-is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
- integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-number@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
- integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-is-stream@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
- integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-
-istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756"
- integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==
-
-istanbul-lib-instrument@^5.0.4:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d"
- integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==
- dependencies:
- "@babel/core" "^7.12.3"
- "@babel/parser" "^7.14.7"
- "@istanbuljs/schema" "^0.1.2"
- istanbul-lib-coverage "^3.2.0"
- semver "^6.3.0"
-
-istanbul-lib-instrument@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf"
- integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==
- dependencies:
- "@babel/core" "^7.12.3"
- "@babel/parser" "^7.14.7"
- "@istanbuljs/schema" "^0.1.2"
- istanbul-lib-coverage "^3.2.0"
- semver "^7.5.4"
-
-istanbul-lib-report@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d"
- integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==
- dependencies:
- istanbul-lib-coverage "^3.0.0"
- make-dir "^4.0.0"
- supports-color "^7.1.0"
-
-istanbul-lib-source-maps@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
- integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
- dependencies:
- debug "^4.1.1"
- istanbul-lib-coverage "^3.0.0"
- source-map "^0.6.1"
-
-istanbul-reports@^3.1.3:
- version "3.1.6"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a"
- integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==
- dependencies:
- html-escaper "^2.0.0"
- istanbul-lib-report "^3.0.0"
-
-jest-changed-files@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a"
- integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==
- dependencies:
- execa "^5.0.0"
- jest-util "^29.7.0"
- p-limit "^3.1.0"
-
-jest-circus@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a"
- integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==
- dependencies:
- "@jest/environment" "^29.7.0"
- "@jest/expect" "^29.7.0"
- "@jest/test-result" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- chalk "^4.0.0"
- co "^4.6.0"
- dedent "^1.0.0"
- is-generator-fn "^2.0.0"
- jest-each "^29.7.0"
- jest-matcher-utils "^29.7.0"
- jest-message-util "^29.7.0"
- jest-runtime "^29.7.0"
- jest-snapshot "^29.7.0"
- jest-util "^29.7.0"
- p-limit "^3.1.0"
- pretty-format "^29.7.0"
- pure-rand "^6.0.0"
- slash "^3.0.0"
- stack-utils "^2.0.3"
-
-jest-cli@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995"
- integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==
- dependencies:
- "@jest/core" "^29.7.0"
- "@jest/test-result" "^29.7.0"
- "@jest/types" "^29.6.3"
- chalk "^4.0.0"
- create-jest "^29.7.0"
- exit "^0.1.2"
- import-local "^3.0.2"
- jest-config "^29.7.0"
- jest-util "^29.7.0"
- jest-validate "^29.7.0"
- yargs "^17.3.1"
-
-jest-config@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f"
- integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==
- dependencies:
- "@babel/core" "^7.11.6"
- "@jest/test-sequencer" "^29.7.0"
- "@jest/types" "^29.6.3"
- babel-jest "^29.7.0"
- chalk "^4.0.0"
- ci-info "^3.2.0"
- deepmerge "^4.2.2"
- glob "^7.1.3"
- graceful-fs "^4.2.9"
- jest-circus "^29.7.0"
- jest-environment-node "^29.7.0"
- jest-get-type "^29.6.3"
- jest-regex-util "^29.6.3"
- jest-resolve "^29.7.0"
- jest-runner "^29.7.0"
- jest-util "^29.7.0"
- jest-validate "^29.7.0"
- micromatch "^4.0.4"
- parse-json "^5.2.0"
- pretty-format "^29.7.0"
- slash "^3.0.0"
- strip-json-comments "^3.1.1"
-
-jest-diff@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a"
- integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==
- dependencies:
- chalk "^4.0.0"
- diff-sequences "^29.6.3"
- jest-get-type "^29.6.3"
- pretty-format "^29.7.0"
-
-jest-docblock@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a"
- integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==
- dependencies:
- detect-newline "^3.0.0"
-
-jest-each@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1"
- integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==
- dependencies:
- "@jest/types" "^29.6.3"
- chalk "^4.0.0"
- jest-get-type "^29.6.3"
- jest-util "^29.7.0"
- pretty-format "^29.7.0"
-
-jest-environment-node@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376"
- integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==
- dependencies:
- "@jest/environment" "^29.7.0"
- "@jest/fake-timers" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- jest-mock "^29.7.0"
- jest-util "^29.7.0"
-
-jest-get-type@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
- integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==
-
-jest-haste-map@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104"
- integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==
- dependencies:
- "@jest/types" "^29.6.3"
- "@types/graceful-fs" "^4.1.3"
- "@types/node" "*"
- anymatch "^3.0.3"
- fb-watchman "^2.0.0"
- graceful-fs "^4.2.9"
- jest-regex-util "^29.6.3"
- jest-util "^29.7.0"
- jest-worker "^29.7.0"
- micromatch "^4.0.4"
- walker "^1.0.8"
- optionalDependencies:
- fsevents "^2.3.2"
-
-jest-leak-detector@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728"
- integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==
- dependencies:
- jest-get-type "^29.6.3"
- pretty-format "^29.7.0"
-
-jest-matcher-utils@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12"
- integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==
- dependencies:
- chalk "^4.0.0"
- jest-diff "^29.7.0"
- jest-get-type "^29.6.3"
- pretty-format "^29.7.0"
-
-jest-message-util@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
- integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
- dependencies:
- "@babel/code-frame" "^7.12.13"
- "@jest/types" "^29.6.3"
- "@types/stack-utils" "^2.0.0"
- chalk "^4.0.0"
- graceful-fs "^4.2.9"
- micromatch "^4.0.4"
- pretty-format "^29.7.0"
- slash "^3.0.0"
- stack-utils "^2.0.3"
-
-jest-mock@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
- integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
- dependencies:
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- jest-util "^29.7.0"
-
-jest-pnp-resolver@^1.2.2:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
- integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==
-
-jest-regex-util@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52"
- integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==
-
-jest-resolve-dependencies@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428"
- integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==
- dependencies:
- jest-regex-util "^29.6.3"
- jest-snapshot "^29.7.0"
-
-jest-resolve@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30"
- integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==
- dependencies:
- chalk "^4.0.0"
- graceful-fs "^4.2.9"
- jest-haste-map "^29.7.0"
- jest-pnp-resolver "^1.2.2"
- jest-util "^29.7.0"
- jest-validate "^29.7.0"
- resolve "^1.20.0"
- resolve.exports "^2.0.0"
- slash "^3.0.0"
-
-jest-runner@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e"
- integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==
- dependencies:
- "@jest/console" "^29.7.0"
- "@jest/environment" "^29.7.0"
- "@jest/test-result" "^29.7.0"
- "@jest/transform" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- chalk "^4.0.0"
- emittery "^0.13.1"
- graceful-fs "^4.2.9"
- jest-docblock "^29.7.0"
- jest-environment-node "^29.7.0"
- jest-haste-map "^29.7.0"
- jest-leak-detector "^29.7.0"
- jest-message-util "^29.7.0"
- jest-resolve "^29.7.0"
- jest-runtime "^29.7.0"
- jest-util "^29.7.0"
- jest-watcher "^29.7.0"
- jest-worker "^29.7.0"
- p-limit "^3.1.0"
- source-map-support "0.5.13"
-
-jest-runtime@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817"
- integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==
- dependencies:
- "@jest/environment" "^29.7.0"
- "@jest/fake-timers" "^29.7.0"
- "@jest/globals" "^29.7.0"
- "@jest/source-map" "^29.6.3"
- "@jest/test-result" "^29.7.0"
- "@jest/transform" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- chalk "^4.0.0"
- cjs-module-lexer "^1.0.0"
- collect-v8-coverage "^1.0.0"
- glob "^7.1.3"
- graceful-fs "^4.2.9"
- jest-haste-map "^29.7.0"
- jest-message-util "^29.7.0"
- jest-mock "^29.7.0"
- jest-regex-util "^29.6.3"
- jest-resolve "^29.7.0"
- jest-snapshot "^29.7.0"
- jest-util "^29.7.0"
- slash "^3.0.0"
- strip-bom "^4.0.0"
-
-jest-snapshot@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5"
- integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==
- dependencies:
- "@babel/core" "^7.11.6"
- "@babel/generator" "^7.7.2"
- "@babel/plugin-syntax-jsx" "^7.7.2"
- "@babel/plugin-syntax-typescript" "^7.7.2"
- "@babel/types" "^7.3.3"
- "@jest/expect-utils" "^29.7.0"
- "@jest/transform" "^29.7.0"
- "@jest/types" "^29.6.3"
- babel-preset-current-node-syntax "^1.0.0"
- chalk "^4.0.0"
- expect "^29.7.0"
- graceful-fs "^4.2.9"
- jest-diff "^29.7.0"
- jest-get-type "^29.6.3"
- jest-matcher-utils "^29.7.0"
- jest-message-util "^29.7.0"
- jest-util "^29.7.0"
- natural-compare "^1.4.0"
- pretty-format "^29.7.0"
- semver "^7.5.3"
-
-jest-util@^29.0.0, jest-util@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
- integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
- dependencies:
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- chalk "^4.0.0"
- ci-info "^3.2.0"
- graceful-fs "^4.2.9"
- picomatch "^2.2.3"
-
-jest-validate@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
- integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
- dependencies:
- "@jest/types" "^29.6.3"
- camelcase "^6.2.0"
- chalk "^4.0.0"
- jest-get-type "^29.6.3"
- leven "^3.1.0"
- pretty-format "^29.7.0"
-
-jest-watcher@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2"
- integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==
- dependencies:
- "@jest/test-result" "^29.7.0"
- "@jest/types" "^29.6.3"
- "@types/node" "*"
- ansi-escapes "^4.2.1"
- chalk "^4.0.0"
- emittery "^0.13.1"
- jest-util "^29.7.0"
- string-length "^4.0.1"
-
-jest-worker@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a"
- integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==
- dependencies:
- "@types/node" "*"
- jest-util "^29.7.0"
- merge-stream "^2.0.0"
- supports-color "^8.0.0"
-
-jest@^29.4.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613"
- integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==
- dependencies:
- "@jest/core" "^29.7.0"
- "@jest/types" "^29.6.3"
- import-local "^3.0.2"
- jest-cli "^29.7.0"
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^3.13.1:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
- integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
- dependencies:
- argparse "^1.0.7"
- esprima "^4.0.0"
-
-js-yaml@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
- integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
- dependencies:
- argparse "^2.0.1"
-
-jsesc@^2.5.1:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
- integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
-
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
- integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
-
-json-parse-even-better-errors@^2.3.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
- integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
-
-json-schema-traverse@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
- integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-stable-stringify-without-jsonify@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
- integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
-
-json5@^2.2.2, json5@^2.2.3:
- version "2.2.3"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
- integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
-
-jsonc-parser@^3.2.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a"
- integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==
-
-keyv@^4.5.4:
- version "4.5.4"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
- integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
- dependencies:
- json-buffer "3.0.1"
-
-kleur@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
- integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-
-leven@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
- integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
-
-levn@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
- integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
- dependencies:
- prelude-ls "^1.2.1"
- type-check "~0.4.0"
-
-lines-and-columns@^1.1.6:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
- integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
-
-locate-path@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
- integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
- dependencies:
- p-locate "^4.1.0"
-
-locate-path@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
- integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
- dependencies:
- p-locate "^5.0.0"
-
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
- integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
-
-lodash.merge@^4.6.2:
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
- integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
-
-lru-cache@^10.4.3:
- version "10.4.3"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
- integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
-
-lru-cache@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
-lru-cache@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
- integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
- dependencies:
- yallist "^4.0.0"
-
-make-dir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e"
- integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==
- dependencies:
- semver "^7.5.3"
-
[email protected], make-error@^1.1.1:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
- integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
-
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
- integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
- dependencies:
- tmpl "1.0.5"
-
-marked-terminal@^7.1.0:
- version "7.2.1"
- resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068"
- integrity sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ==
- dependencies:
- ansi-escapes "^7.0.0"
- ansi-regex "^6.1.0"
- chalk "^5.3.0"
- cli-highlight "^2.1.11"
- cli-table3 "^0.6.5"
- node-emoji "^2.1.3"
- supports-hyperlinks "^3.1.0"
-
-marked@^9.1.2:
- version "9.1.6"
- resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695"
- integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==
-
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
-merge2@^1.3.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
- integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-
-micromatch@^4.0.4:
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
- integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
- dependencies:
- braces "^3.0.3"
- picomatch "^2.3.1"
-
-mimic-fn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
- integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
- integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimatch@^5.0.1:
- version "5.1.6"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
- integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
- dependencies:
- brace-expansion "^2.0.1"
-
-minimatch@^9.0.4:
- version "9.0.5"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
- integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
- dependencies:
- brace-expansion "^2.0.1"
-
-minimist@^1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
- integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
-
-mri@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
- integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
-
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-ms@^2.1.3:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
- integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-
-mz@^2.4.0:
- version "2.7.0"
- resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
- integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
- dependencies:
- any-promise "^1.0.0"
- object-assign "^4.0.1"
- thenify-all "^1.0.0"
-
-natural-compare@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
- integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
-
-node-emoji@^2.1.3:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06"
- integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==
- dependencies:
- "@sindresorhus/is" "^4.6.0"
- char-regex "^1.0.2"
- emojilib "^2.4.0"
- skin-tone "^2.0.0"
-
-node-int64@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
- integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
-
-node-releases@^2.0.14:
- version "2.0.14"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
- integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
-
-normalize-path@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
- integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-npm-bundled@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4"
- integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==
- dependencies:
- npm-normalize-package-bin "^2.0.0"
-
-npm-normalize-package-bin@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff"
- integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==
-
-npm-packlist@^5.1.3:
- version "5.1.3"
- resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b"
- integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==
- dependencies:
- glob "^8.0.1"
- ignore-walk "^5.0.1"
- npm-bundled "^2.0.0"
- npm-normalize-package-bin "^2.0.0"
-
-npm-run-path@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
- integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
- dependencies:
- path-key "^3.0.0"
-
-object-assign@^4.0.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
-
-once@^1.3.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
- dependencies:
- wrappy "1"
-
-onetime@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
- integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
- dependencies:
- mimic-fn "^2.1.0"
-
-optionator@^0.9.3:
- version "0.9.3"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
- integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
- dependencies:
- "@aashutoshrathi/word-wrap" "^1.2.3"
- deep-is "^0.1.3"
- fast-levenshtein "^2.0.6"
- levn "^0.4.1"
- prelude-ls "^1.2.1"
- type-check "^0.4.0"
-
-p-all@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb"
- integrity sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw==
- dependencies:
- p-map "^4.0.0"
-
-p-limit@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
- integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
- dependencies:
- p-try "^2.0.0"
-
-p-limit@^3.0.2, p-limit@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
- integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
- dependencies:
- yocto-queue "^0.1.0"
-
-p-locate@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
- integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
- dependencies:
- p-limit "^2.2.0"
-
-p-locate@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
- integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
- dependencies:
- p-limit "^3.0.2"
-
-p-map@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
- integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
- dependencies:
- aggregate-error "^3.0.0"
-
-p-try@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
- integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-
-parent-module@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
- integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
- dependencies:
- callsites "^3.0.0"
-
-parse-json@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
- integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- error-ex "^1.3.1"
- json-parse-even-better-errors "^2.3.0"
- lines-and-columns "^1.1.6"
-
-parse5-htmlparser2-tree-adapter@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6"
- integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==
- dependencies:
- parse5 "^6.0.1"
-
-parse5@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
- integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
-
-parse5@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
- integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
-
-path-exists@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
- integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
-
-path-key@^3.0.0, path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-parse@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
- integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-
-picocolors@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
- integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-
-picocolors@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
- integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
-
-picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
- integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
-
-pirates@^4.0.4:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
- integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
-
-pkg-dir@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
- integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
- dependencies:
- find-up "^4.0.0"
-
-prelude-ls@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
- integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-
-prettier-linter-helpers@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
- integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
- dependencies:
- fast-diff "^1.1.2"
-
-prettier@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848"
- integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==
-
-pretty-format@^29.0.0, pretty-format@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
- integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
- dependencies:
- "@jest/schemas" "^29.6.3"
- ansi-styles "^5.0.0"
- react-is "^18.0.0"
-
-prompts@^2.0.1:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
- integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
- dependencies:
- kleur "^3.0.3"
- sisteransi "^1.0.5"
-
-publint@^0.2.12:
- version "0.2.12"
- resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059"
- integrity sha512-YNeUtCVeM4j9nDiTT2OPczmlyzOkIXNtdDZnSuajAxS/nZ6j3t7Vs9SUB4euQNddiltIwu7Tdd3s+hr08fAsMw==
- dependencies:
- npm-packlist "^5.1.3"
- picocolors "^1.1.1"
- sade "^1.8.1"
-
-punycode@^2.1.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
- integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
-
-pure-rand@^6.0.0:
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7"
- integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==
-
-queue-microtask@^1.2.2:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
- integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-
-react-is@^18.0.0:
- version "18.2.0"
- resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
- integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
-
-readable-stream@^3.4.0:
- version "3.6.2"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
- integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
- dependencies:
- inherits "^2.0.3"
- string_decoder "^1.1.1"
- util-deprecate "^1.0.1"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
- integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
-
-resolve-cwd@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
- integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
- dependencies:
- resolve-from "^5.0.0"
-
-resolve-from@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
- integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-
-resolve-from@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
- integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
-
-resolve.exports@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
- integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
-
-resolve@^1.20.0:
- version "1.22.8"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
- integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
- dependencies:
- is-core-module "^2.13.0"
- path-parse "^1.0.7"
- supports-preserve-symlinks-flag "^1.0.0"
-
-reusify@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
- integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-
-run-parallel@^1.1.9:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
- integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
- dependencies:
- queue-microtask "^1.2.2"
-
-sade@^1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701"
- integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==
- dependencies:
- mri "^1.1.0"
-
-safe-buffer@~5.2.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
- integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
-"safer-buffer@>= 2.1.2 < 3.0.0":
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-semver@^6.3.0, semver@^6.3.1:
- version "6.3.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
- integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-
-semver@^7.5.3:
- version "7.5.4"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
- integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
- dependencies:
- lru-cache "^6.0.0"
-
-semver@^7.5.4:
- version "7.6.3"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
- integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
-
-semver@^7.6.0:
- version "7.7.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
- integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
-
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
-signal-exit@^3.0.3, signal-exit@^3.0.7:
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
- integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
-
-sisteransi@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
- integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
-
-skin-tone@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237"
- integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==
- dependencies:
- unicode-emoji-modifier-base "^1.0.0"
-
-slash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
- integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
-
- version "0.5.13"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"
- integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==
- dependencies:
- buffer-from "^1.0.0"
- source-map "^0.6.0"
-
-source-map@^0.6.0, source-map@^0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
- integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-sprintf-js@~1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
- integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
-
-stack-utils@^2.0.3:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
- integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==
- dependencies:
- escape-string-regexp "^2.0.0"
-
-string-length@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
- integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
- dependencies:
- char-regex "^1.0.2"
- strip-ansi "^6.0.0"
-
-string-to-stream@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42"
- integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==
- dependencies:
- readable-stream "^3.4.0"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string_decoder@^1.1.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
- integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
- dependencies:
- safe-buffer "~5.2.0"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-bom@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
- integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
-
-strip-bom@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
- integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
-
-strip-final-newline@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
- integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-
-strip-json-comments@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
- integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-
-superstruct@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca"
- integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==
-
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.0.0, supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
-supports-color@^8.0.0:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
- integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
- dependencies:
- has-flag "^4.0.0"
-
-supports-hyperlinks@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz#b56150ff0173baacc15f21956450b61f2b18d3ac"
- integrity sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==
- dependencies:
- has-flag "^4.0.0"
- supports-color "^7.0.0"
-
-supports-preserve-symlinks-flag@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
- integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
-
-synckit@^0.11.7:
- version "0.11.8"
- resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457"
- integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==
- dependencies:
- "@pkgr/core" "^0.2.4"
-
-test-exclude@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
- integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
- dependencies:
- "@istanbuljs/schema" "^0.1.2"
- glob "^7.1.4"
- minimatch "^3.0.4"
-
-thenify-all@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
- integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
- dependencies:
- thenify ">= 3.1.0 < 4"
-
-"thenify@>= 3.1.0 < 4":
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
- integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
- dependencies:
- any-promise "^1.0.0"
-
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
- integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
-
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
- integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
-
-to-regex-range@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
- integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
- dependencies:
- is-number "^7.0.0"
-
-ts-api-utils@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd"
- integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==
-
-ts-jest@^29.1.0:
- version "29.1.1"
- resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b"
- integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==
- dependencies:
- bs-logger "0.x"
- fast-json-stable-stringify "2.x"
- jest-util "^29.0.0"
- json5 "^2.2.3"
- lodash.memoize "4.x"
- make-error "1.x"
- semver "^7.5.3"
- yargs-parser "^21.0.1"
-
-ts-node@^10.5.0:
- version "10.7.0"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5"
- integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==
- dependencies:
- "@cspotcode/source-map-support" "0.7.0"
- "@tsconfig/node10" "^1.0.7"
- "@tsconfig/node12" "^1.0.7"
- "@tsconfig/node14" "^1.0.0"
- "@tsconfig/node16" "^1.0.2"
- acorn "^8.4.1"
- acorn-walk "^8.1.1"
- arg "^4.1.0"
- create-require "^1.1.0"
- diff "^4.0.1"
- make-error "^1.1.1"
- v8-compile-cache-lib "^3.0.0"
- yn "3.1.1"
-
-"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz":
- version "1.1.8"
- resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04"
- dependencies:
- debug "^4.3.7"
- fast-glob "^3.3.2"
- get-stdin "^8.0.0"
- p-all "^3.0.0"
- picocolors "^1.1.1"
- signal-exit "^3.0.7"
- string-to-stream "^3.0.1"
- superstruct "^1.0.4"
- tslib "^2.8.1"
- yargs "^17.7.2"
-
-tsconfig-paths@^4.0.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
- integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
- dependencies:
- json5 "^2.2.2"
- minimist "^1.2.6"
- strip-bom "^3.0.0"
-
-tslib@^2.8.1:
- version "2.8.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
- integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
-
-type-check@^0.4.0, type-check@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
- integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
- dependencies:
- prelude-ls "^1.2.1"
-
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
- integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-
-type-fest@^0.21.3:
- version "0.21.3"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
- integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
-
- version "8.31.1"
- resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b"
- integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA==
- dependencies:
- "@typescript-eslint/eslint-plugin" "8.31.1"
- "@typescript-eslint/parser" "8.31.1"
- "@typescript-eslint/utils" "8.31.1"
-
- version "5.6.1-rc"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.1-rc.tgz#d5e4d7d8170174fed607b74cc32aba3d77018e02"
- integrity sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==
-
- version "5.8.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
- integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
-
-undici-types@~5.26.4:
- version "5.26.5"
- resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
- integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
-
-undici-types@~6.19.2:
- version "6.19.8"
- resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
- integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
-
-unicode-emoji-modifier-base@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459"
- integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==
-
-update-browserslist-db@^1.0.13:
- version "1.0.13"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
- integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
- dependencies:
- escalade "^3.1.1"
- picocolors "^1.0.0"
-
-uri-js@^4.2.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
- integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
- dependencies:
- punycode "^2.1.0"
-
-util-deprecate@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
-
-v8-compile-cache-lib@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8"
- integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==
-
-v8-to-istanbul@^9.0.1:
- version "9.2.0"
- resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad"
- integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==
- dependencies:
- "@jridgewell/trace-mapping" "^0.3.12"
- "@types/istanbul-lib-coverage" "^2.0.1"
- convert-source-map "^2.0.0"
-
-validate-npm-package-name@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8"
- integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==
-
-walker@^1.0.8:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
- integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
- dependencies:
- makeerror "1.0.12"
-
-which@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
-
-write-file-atomic@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd"
- integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==
- dependencies:
- imurmurhash "^0.1.4"
- signal-exit "^3.0.7"
-
-y18n@^5.0.5:
- version "5.0.8"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
- integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-
-yallist@^3.0.2:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yargs-parser@^20.2.2:
- version "20.2.9"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
- integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
-
-yargs-parser@^21.0.1, yargs-parser@^21.1.1:
- version "21.1.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
- integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
-
-yargs@^16.0.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
- integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
- dependencies:
- cliui "^7.0.2"
- escalade "^3.1.1"
- get-caller-file "^2.0.5"
- require-directory "^2.1.1"
- string-width "^4.2.0"
- y18n "^5.0.5"
- yargs-parser "^20.2.2"
-
-yargs@^17.3.1, yargs@^17.7.2:
- version "17.7.2"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
- integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
- dependencies:
- cliui "^8.0.1"
- escalade "^3.1.1"
- get-caller-file "^2.0.5"
- require-directory "^2.1.1"
- string-width "^4.2.3"
- y18n "^5.0.5"
- yargs-parser "^21.1.1"
-
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
- integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
-
-yocto-queue@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
- integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==