diff --git a/bun.lock b/bun.lock index a69de088e..9d4e486a0 100644 --- a/bun.lock +++ b/bun.lock @@ -38,6 +38,7 @@ "@octokit/graphql": "9.0.1", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.4.3", + "@opencode-ai/plugin": "workspace:*", "@standard-schema/spec": "1.0.0", "@zip.js/zip.js": "2.7.62", "ai": "catalog:", @@ -74,6 +75,16 @@ "zod-to-json-schema": "3.24.5", }, }, + "packages/plugin": { + "name": "@opencode-ai/plugin", + "version": "0.0.0", + "devDependencies": { + "@hey-api/openapi-ts": "0.80.1", + "@opencode-ai/sdk": "workspace:*", + "@tsconfig/node22": "catalog:", + "typescript": "catalog:", + }, + }, "packages/sdk/js": { "name": "@opencode-ai/sdk", "version": "0.0.0", @@ -416,6 +427,8 @@ "@openauthjs/openauth": ["@openauthjs/openauth@0.4.3", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw=="], + "@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"], + "@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"], "@opencode/function": ["@opencode/function@workspace:packages/function"], diff --git a/opencode.json b/opencode.json index eb9f5f93c..bf6d9d2de 100644 --- a/opencode.json +++ b/opencode.json @@ -1,16 +1,6 @@ { "$schema": "https://opencode.ai/config.json", - "provider": { - "cerebras": { - "options": { - "apiKey": "csk-m33xrvt43whkypn8r4ph9xc8fenhx2f68c3pj22ext45v5k9" - }, - "npm": "@ai-sdk/cerebras", - "models": { - "qwen-3-coder-480b": {} - } - } - }, + "plugin": ["./packages/plugin/src/example.ts"], "mcp": { "context7": { "type": "remote", diff --git a/packages/function/package.json b/packages/function/package.json index 74029e742..df798449a 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode/function", - "version": "0.0.1", + "version": "0.0.0-202508022246", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 048d99b74..5901db106 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.0", + "version": "0.0.0-202508022246", "name": "opencode", "type": "module", "private": true, @@ -36,6 +36,7 @@ "@octokit/graphql": "9.0.1", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.4.3", + "@opencode-ai/plugin": "workspace:*", "@standard-schema/spec": "1.0.0", "@zip.js/zip.js": "2.7.62", "ai": "catalog:", diff --git a/packages/opencode/src/cli/bootstrap.ts b/packages/opencode/src/cli/bootstrap.ts index 3af9809bc..009665022 100644 --- a/packages/opencode/src/cli/bootstrap.ts +++ b/packages/opencode/src/cli/bootstrap.ts @@ -2,6 +2,7 @@ import { App } from "../app/app" import { ConfigHooks } from "../config/hooks" import { Format } from "../format" import { LSP } from "../lsp" +import { Plugin } from "../plugin" import { Share } from "../share/share" import { Snapshot } from "../snapshot" @@ -9,6 +10,7 @@ export async function bootstrap(input: App.Input, cb: (app: App.Info) => Prom return App.provide(input, async (app) => { Share.init() Format.init() + Plugin.init() ConfigHooks.init() LSP.init() Snapshot.init() diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index d00e5f1f9..a7c2c962e 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -23,13 +23,13 @@ export namespace Config { for (const file of ["opencode.jsonc", "opencode.json"]) { const found = await Filesystem.findUp(file, app.path.cwd, app.path.root) for (const resolved of found.toReversed()) { - result = mergeDeep(result, await load(resolved)) + result = mergeDeep(result, await loadFile(resolved)) } } // Override with custom config if provided if (Flag.OPENCODE_CONFIG) { - result = mergeDeep(result, await load(Flag.OPENCODE_CONFIG)) + result = mergeDeep(result, await loadFile(Flag.OPENCODE_CONFIG)) log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG }) } @@ -37,7 +37,7 @@ export namespace Config { if (value.type === "wellknown") { process.env[value.key] = value.token const wellknown = await fetch(`${key}/.well-known/opencode`).then((x) => x.json()) - result = mergeDeep(result, await loadRaw(JSON.stringify(wellknown.config ?? {}), process.cwd())) + result = mergeDeep(result, await load(JSON.stringify(wellknown.config ?? {}), process.cwd())) } } @@ -223,6 +223,7 @@ export namespace Config { $schema: z.string().optional().describe("JSON schema reference for configuration validation"), theme: z.string().optional().describe("Theme name to use for the interface"), keybinds: Keybinds.optional().describe("Custom keybind configurations"), + plugin: z.string().array().optional(), share: z .enum(["manual", "auto", "disabled"]) .optional() @@ -352,9 +353,9 @@ export namespace Config { export const global = lazy(async () => { let result: Info = pipe( {}, - mergeDeep(await load(path.join(Global.Path.config, "config.json"))), - mergeDeep(await load(path.join(Global.Path.config, "opencode.json"))), - mergeDeep(await load(path.join(Global.Path.config, "opencode.jsonc"))), + mergeDeep(await loadFile(path.join(Global.Path.config, "config.json"))), + mergeDeep(await loadFile(path.join(Global.Path.config, "opencode.json"))), + mergeDeep(await loadFile(path.join(Global.Path.config, "opencode.jsonc"))), ) await import(path.join(Global.Path.config, "config"), { @@ -375,25 +376,26 @@ export namespace Config { return result }) - async function load(configPath: string): Promise { - let text = await Bun.file(configPath) + async function loadFile(filepath: string): Promise { + log.info("loading", { path: filepath }) + let text = await Bun.file(filepath) .text() .catch((err) => { if (err.code === "ENOENT") return - throw new JsonError({ path: configPath }, { cause: err }) + throw new JsonError({ path: filepath }, { cause: err }) }) if (!text) return {} - return loadRaw(text, configPath) + return load(text, filepath) } - async function loadRaw(text: string, configPath: string) { + async function load(text: string, filepath: string) { text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => { return process.env[varName] || "" }) const fileMatches = text.match(/\{file:[^}]+\}/g) if (fileMatches) { - const configDir = path.dirname(configPath) + const configDir = path.dirname(filepath) const lines = text.split("\n") for (const match of fileMatches) { @@ -428,7 +430,7 @@ export namespace Config { .join("\n") throw new JsonError({ - path: configPath, + path: filepath, message: `\n--- JSONC Input ---\n${text}\n--- Errors ---\n${errorDetails}\n--- End ---`, }) } @@ -437,11 +439,21 @@ export namespace Config { if (parsed.success) { if (!parsed.data.$schema) { parsed.data.$schema = "https://opencode.ai/config.json" - await Bun.write(configPath, JSON.stringify(parsed.data, null, 2)) + await Bun.write(filepath, JSON.stringify(parsed.data, null, 2)) } - return parsed.data + const data = parsed.data + if (data.plugin) { + for (let i = 0; i < data.plugin?.length; i++) { + const plugin = data.plugin[i] + if (typeof plugin === "string") { + data.plugin[i] = path.resolve(path.dirname(filepath), plugin) + } + } + } + return data } - throw new InvalidError({ path: configPath, issues: parsed.error.issues }) + + throw new InvalidError({ path: filepath, issues: parsed.error.issues }) } export const JsonError = NamedError.create( "ConfigJsonError", diff --git a/packages/opencode/src/permission/index.ts b/packages/opencode/src/permission/index.ts index 157b7039b..53c49696e 100644 --- a/packages/opencode/src/permission/index.ts +++ b/packages/opencode/src/permission/index.ts @@ -3,6 +3,7 @@ import { z } from "zod" import { Bus } from "../bus" import { Log } from "../util/log" import { Identifier } from "../id/id" +import { Plugin } from "../plugin" export namespace Permission { const log = Log.create({ service: "permission" }) @@ -67,7 +68,7 @@ export namespace Permission { }, ) - export function ask(input: { + export async function ask(input: { type: Info["type"] title: Info["title"] pattern?: Info["pattern"] @@ -95,6 +96,18 @@ export namespace Permission { created: Date.now(), }, } + + switch ( + await Plugin.trigger("permission.ask", info, { + status: "ask", + }).then((x) => x.status) + ) { + case "deny": + throw new RejectedError(info.sessionID, info.id, info.callID) + case "allow": + return + } + pending[input.sessionID] = pending[input.sessionID] || {} return new Promise((resolve, reject) => { pending[input.sessionID][info.id] = { diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts new file mode 100644 index 000000000..59830aa54 --- /dev/null +++ b/packages/opencode/src/plugin/index.ts @@ -0,0 +1,85 @@ +import type { Hooks, Plugin as PluginInstance } from "@opencode-ai/plugin" +import { App } from "../app/app" +import { Config } from "../config/config" +import { Bus } from "../bus" +import { Log } from "../util/log" +import { createOpencodeClient } from "@opencode-ai/sdk" +import { Server } from "../server/server" +import { pathOr } from "remeda" + +export namespace Plugin { + const log = Log.create({ service: "plugin" }) + + const state = App.state("plugin", async (app) => { + const client = createOpencodeClient({ + baseUrl: "http://localhost:4096", + fetch: async (...args) => Server.app().fetch(...args), + }) + const config = await Config.get() + const hooks = [] + for (const plugin of config.plugin ?? []) { + log.info("loading plugin", { path: plugin }) + const mod = await import(plugin) + for (const [_name, fn] of Object.entries(mod)) { + const init = await fn({ + client, + app, + $: Bun.$, + }) + hooks.push(init) + } + } + + return { + hooks, + } + }) + + type Path = T extends object + ? { + [K in keyof T]: K extends string + ? T[K] extends Function | undefined + ? `${Prefix}${K}` + : Path + : never + }[keyof T] + : never + + export type FunctionFromKey> = P extends `${infer K}.${infer R}` + ? K extends keyof T + ? R extends Path + ? FunctionFromKey + : never + : never + : P extends keyof T + ? T[P] + : never + + export async function trigger< + Name extends Path>, + Input = Parameters, Name>>[0], + Output = Parameters, Name>>[1], + >(fn: Name, input: Input, output: Output): Promise { + if (!fn) return output + const path = fn.split(".") + for (const hook of await state().then((x) => x.hooks)) { + // @ts-expect-error + const fn = pathOr(hook, path, undefined) + if (!fn) continue + // @ts-expect-error + await fn(input, output) + } + return output + } + + export function init() { + Bus.subscribeAll(async (input) => { + const hooks = await state().then((x) => x.hooks) + for (const hook of hooks) { + hook["event"]?.({ + event: input, + }) + } + }) + } +} diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 28b670e0d..6e3ea85fe 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -97,7 +97,7 @@ export namespace Provider { Array.isArray(msg.content) && msg.content.some((part: any) => part.type === "image_url"), ) } - } catch { } + } catch {} const headers: Record = { ...init.headers, ...copilot.HEADERS, @@ -283,26 +283,26 @@ export namespace Provider { cost: !model.cost && !existing?.cost ? { - input: 0, - output: 0, - cache_read: 0, - cache_write: 0, - } + input: 0, + output: 0, + cache_read: 0, + cache_write: 0, + } : { - cache_read: 0, - cache_write: 0, - ...existing?.cost, - ...model.cost, - }, + cache_read: 0, + cache_write: 0, + ...existing?.cost, + ...model.cost, + }, options: { ...existing?.options, ...model.options, }, limit: model.limit ?? existing?.limit ?? { - context: 0, - output: 0, - }, + context: 0, + output: 0, + }, } parsed.models[modelID] = parsedModel } @@ -386,6 +386,10 @@ export namespace Provider { }) } + export async function getProvider(providerID: string) { + return state().then((s) => s.providers[providerID]) + } + export async function getModel(providerID: string, modelID: string) { const key = `${providerID}/${modelID}` const s = await state() diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 76da0fbf5..c97dd34d9 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -19,6 +19,7 @@ import { MessageV2 } from "../session/message-v2" import { Mode } from "../session/mode" import { callTui, TuiRoute } from "./tui" import { Permission } from "../permission" +import { lazy } from "../util/lazy" const ERRORS = { 400: { @@ -48,7 +49,7 @@ export namespace Server { Connected: Bus.event("server.connected", z.object({})), } - function app() { + export const app = lazy(() => { const app = new Hono() const result = app @@ -1022,7 +1023,7 @@ export namespace Server { .route("/tui/control", TuiRoute) return result - } + }) export async function openapi() { const a = app() diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index d0685daee..970e1190b 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -41,6 +41,7 @@ import { LSP } from "../lsp" import { ReadTool } from "../tool/read" import { mergeDeep, pipe, splitWhen } from "remeda" import { ToolRegistry } from "../tool/registry" +import { Plugin } from "../plugin" export namespace Session { const log = Log.create({ service: "session" }) @@ -571,7 +572,14 @@ export namespace Session { text: PROMPT_PLAN, synthetic: true, }) - + await Plugin.trigger( + "chat.message", + {}, + { + message: userMsg, + parts: userParts, + }, + ) await updateMessage(userMsg) for (const part of userParts) { await updatePart(part) @@ -716,6 +724,17 @@ export namespace Session { description: item.description, inputSchema: item.parameters as ZodSchema, async execute(args, options) { + await Plugin.trigger( + "tool.execute.before", + { + tool: item.id, + sessionID: input.sessionID, + callID: options.toolCallId, + }, + { + args, + }, + ) await processor.track(options.toolCallId) const result = await item.execute(args, { sessionID: input.sessionID, @@ -740,6 +759,15 @@ export namespace Session { } }, }) + await Plugin.trigger( + "tool.execute.after", + { + tool: item.id, + sessionID: input.sessionID, + callID: options.toolCallId, + }, + result, + ) return result }, toModelOutput(result) { @@ -776,6 +804,21 @@ export namespace Session { tools[key] = item } + const params = { + temperature: model.info.temperature + ? (mode.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID)) + : undefined, + topP: mode.topP ?? ProviderTransform.topP(input.providerID, input.modelID), + } + await Plugin.trigger( + "chat.params", + { + model: model.info, + provider: await Provider.getProvider(input.providerID), + message: userMsg, + }, + params, + ) const stream = streamText({ onError(e) { log.error("streamText error", { @@ -835,6 +878,8 @@ export namespace Session { providerOptions: { [input.providerID]: model.info.options, }, + temperature: params.temperature, + topP: params.topP, messages: [ ...system.map( (x): ModelMessage => ({ @@ -844,10 +889,6 @@ export namespace Session { ), ...MessageV2.toModelMessage(msgs), ], - temperature: model.info.temperature - ? (mode.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID)) - : undefined, - topP: mode.topP ?? ProviderTransform.topP(input.providerID, input.modelID), tools: model.info.tool_call === false ? undefined : tools, model: wrapLanguageModel({ model: model.language, diff --git a/packages/opencode/tsconfig.json b/packages/opencode/tsconfig.json index 65fa6c7f3..3cb60a6ee 100644 --- a/packages/opencode/tsconfig.json +++ b/packages/opencode/tsconfig.json @@ -1,5 +1,9 @@ { "$schema": "https://json.schemastore.org/tsconfig", "extends": "@tsconfig/bun/tsconfig.json", - "compilerOptions": {} + "compilerOptions": { + "customConditions": [ + "development" + ] + } } diff --git a/packages/plugin/.gitignore b/packages/plugin/.gitignore new file mode 100644 index 000000000..1521c8b76 --- /dev/null +++ b/packages/plugin/.gitignore @@ -0,0 +1 @@ +dist diff --git a/packages/plugin/package.json b/packages/plugin/package.json new file mode 100644 index 000000000..b7e75af1c --- /dev/null +++ b/packages/plugin/package.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "@opencode-ai/plugin", + "version": "0.0.0", + "type": "module", + "scripts": { + "typecheck": "tsc --noEmit" + }, + "exports": { + ".": "./src/index.ts" + }, + "files": [ + "dist" + ], + "devDependencies": { + "typescript": "catalog:", + "@hey-api/openapi-ts": "0.80.1", + "@tsconfig/node22": "catalog:", + "@opencode-ai/sdk": "workspace:*" + } +} diff --git a/packages/plugin/script/publish.ts b/packages/plugin/script/publish.ts new file mode 100644 index 000000000..b984fd4f4 --- /dev/null +++ b/packages/plugin/script/publish.ts @@ -0,0 +1,18 @@ +#!/usr/bin/env bun + +const dir = new URL("..", import.meta.url).pathname +process.chdir(dir) + +import { $ } from "bun" + +const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true" + +await $`bun tsc` + +if (snapshot) { + await $`bun publish --tag snapshot --access public` + await $`git checkout package.json` +} +if (!snapshot) { + await $`bun publish --access public` +} diff --git a/packages/plugin/src/example.ts b/packages/plugin/src/example.ts new file mode 100644 index 000000000..ac8c0e344 --- /dev/null +++ b/packages/plugin/src/example.ts @@ -0,0 +1,7 @@ +import { Plugin } from "./index" + +export const ExamplePlugin: Plugin = async ({ app, client }) => { + return { + permission: {}, + } +} diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts new file mode 100644 index 000000000..9040fb517 --- /dev/null +++ b/packages/plugin/src/index.ts @@ -0,0 +1,56 @@ +import type { Event, createOpencodeClient, App, Model, Provider, Permission, UserMessage, Part } from "@opencode-ai/sdk" +import { $ } from "bun" + +export type PluginInput = { + client: ReturnType + app: App + $: $ +} +export type Plugin = (input: PluginInput) => Promise + +export interface Hooks { + event?: (input: { event: Event }) => Promise + chat?: { + /** + * Called when a new message is received + */ + message?: (input: {}, output: { message: UserMessage; parts: Part[] }) => Promise + /** + * Modify parameters sent to LLM + */ + params?: ( + input: { model: Model; provider: Provider; message: UserMessage }, + output: { temperature: number; topP: number }, + ) => Promise + } + permission?: { + /** + * Called when a permission is asked + */ + ask?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise + } + tool?: { + execute?: { + /** + * Called before a tool is executed + */ + before?: ( + input: { tool: string; sessionID: string; callID: string }, + output: { + args: any + }, + ) => Promise + /** + * Called after a tool is executed + */ + after?: ( + input: { tool: string; sessionID: string; callID: string }, + output: { + title: string + output: string + metadata: any + }, + ) => Promise + } + } +} diff --git a/packages/plugin/tsconfig.json b/packages/plugin/tsconfig.json new file mode 100644 index 000000000..34d4a8718 --- /dev/null +++ b/packages/plugin/tsconfig.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "@tsconfig/node22/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "module": "preserve", + "declaration": true, + "moduleResolution": "bundler", + "customConditions": [ + "development" + ] + }, + "include": [ + "src" + ] +} diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 502f2b7bb..9d12632ff 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,10 +1,16 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "0.0.0", + "version": "0.0.0-202508022246", "type": "module", + "scripts": { + "typecheck": "tsc --noEmit" + }, "exports": { - ".": "./dist/index.js" + ".": { + "development": "./src/index.ts", + "import": "./dist/index.js" + } }, "files": [ "dist" diff --git a/packages/sdk/js/script/generate.ts b/packages/sdk/js/script/generate.ts index 3f864682e..80fcf1095 100755 --- a/packages/sdk/js/script/generate.ts +++ b/packages/sdk/js/script/generate.ts @@ -36,6 +36,7 @@ await createClient({ }, ], }) +await $`bun prettier --write src/gen` await $`rm -rf dist` await $`bun tsc` diff --git a/packages/sdk/js/script/publish.ts b/packages/sdk/js/script/publish.ts index 39407f633..75120bc5c 100644 --- a/packages/sdk/js/script/publish.ts +++ b/packages/sdk/js/script/publish.ts @@ -5,20 +5,13 @@ 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 index 3bb22b24a..5566242bd 100644 --- a/packages/sdk/js/src/gen/client.gen.ts +++ b/packages/sdk/js/src/gen/client.gen.ts @@ -1,7 +1,7 @@ // 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'; +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 @@ -11,8 +11,12 @@ import { type Config, type ClientOptions as DefaultClientOptions, createClient, * `setConfig()`. This is useful for example if you're using Next.js * to ensure your client always has the correct values. */ -export type CreateClientConfig = (override?: Config) => Config & T>; +export type CreateClientConfig = ( + override?: Config, +) => Config & T> -export const client = createClient(createConfig({ - baseUrl: 'http://localhost:4096' -})); \ No newline at end of file +export const client = createClient( + createConfig({ + baseUrl: "http://localhost:4096", + }), +) diff --git a/packages/sdk/js/src/gen/client/client.ts b/packages/sdk/js/src/gen/client/client.ts index 89d1e3158..bc009574b 100644 --- a/packages/sdk/js/src/gen/client/client.ts +++ b/packages/sdk/js/src/gen/client/client.ts @@ -1,4 +1,4 @@ -import type { Client, Config, RequestOptions } from './types'; +import type { Client, Config, RequestOptions } from "./types" import { buildUrl, createConfig, @@ -7,189 +7,179 @@ import { mergeConfigs, mergeHeaders, setAuthParams, -} from './utils'; +} from "./utils" -type ReqInit = Omit & { - body?: any; - headers: ReturnType; -}; +type ReqInit = Omit & { + body?: any + headers: ReturnType +} export const createClient = (config: Config = {}): Client => { - let _config = mergeConfigs(createConfig(), config); + let _config = mergeConfigs(createConfig(), config) - const getConfig = (): Config => ({ ..._config }); + const getConfig = (): Config => ({ ..._config }) const setConfig = (config: Config): Config => { - _config = mergeConfigs(_config, config); - return getConfig(); - }; + _config = mergeConfigs(_config, config) + return getConfig() + } - const interceptors = createInterceptors< - Request, - Response, - unknown, - RequestOptions - >(); + const interceptors = createInterceptors() - const request: Client['request'] = async (options) => { + 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); + await opts.requestValidator(opts) } if (opts.body && opts.bodySerializer) { - opts.body = opts.bodySerializer(opts.body); + 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'); + if (opts.body === undefined || opts.body === "") { + opts.headers.delete("Content-Type") } - const url = buildUrl(opts); + const url = buildUrl(opts) const requestInit: ReqInit = { - redirect: 'follow', + redirect: "follow", ...opts, - }; + } - let request = new Request(url, requestInit); + let request = new Request(url, requestInit) for (const fn of interceptors.request._fns) { if (fn) { - request = await fn(request, opts); + 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); + const _fetch = opts.fetch! + let response = await _fetch(request) for (const fn of interceptors.response._fns) { if (fn) { - response = await fn(response, request, opts); + 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' + 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'; + (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json" - let data: any; + 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' + 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 (parseAs === "json") { if (opts.responseValidator) { - await opts.responseValidator(data); + await opts.responseValidator(data) } if (opts.responseTransformer) { - data = await opts.responseTransformer(data); + data = await opts.responseTransformer(data) } } - return opts.responseStyle === 'data' + return opts.responseStyle === "data" ? data : { data, ...result, - }; + } } - const textError = await response.text(); - let jsonError: unknown; + const textError = await response.text() + let jsonError: unknown try { - jsonError = JSON.parse(textError); + jsonError = JSON.parse(textError) } catch { // noop } - const error = jsonError ?? textError; - let finalError = error; + 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 = (await fn(error, response, request, opts)) as string } } - finalError = finalError || ({} as string); + finalError = finalError || ({} as string) if (opts.throwOnError) { - throw finalError; + throw finalError } // TODO: we probably want to return error and improve types - return opts.responseStyle === 'data' + 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' }), + 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' }), + 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' }), + 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' }), - }; -}; + 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 index 5da1f7aee..c6b869b86 100644 --- a/packages/sdk/js/src/gen/client/index.ts +++ b/packages/sdk/js/src/gen/client/index.ts @@ -1,12 +1,8 @@ -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 { 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, @@ -18,5 +14,5 @@ export type { RequestResult, ResponseStyle, TDataShape, -} from './types'; -export { createConfig, mergeHeaders } from './utils'; +} 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 index 85295df07..7f76fc517 100644 --- a/packages/sdk/js/src/gen/client/types.ts +++ b/packages/sdk/js/src/gen/client/types.ts @@ -1,33 +1,30 @@ -import type { Auth } from '../core/auth'; -import type { - Client as CoreClient, - Config as CoreConfig, -} from '../core/types'; -import type { Middleware } from './utils'; +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 type ResponseStyle = "data" | "fields" export interface Config - extends Omit, + extends Omit, CoreConfig { /** * Base URL for all requests made by this client. */ - baseUrl?: T['baseUrl']; + baseUrl?: T["baseUrl"] /** * Fetch API implementation. You can use this option to provide a custom * fetch instance. * * @default globalThis.fetch */ - fetch?: (request: Request) => ReturnType; + fetch?: (request: Request) => ReturnType /** * 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; + 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. @@ -36,135 +33,118 @@ export interface Config * * @default 'auto' */ - parseAs?: - | 'arrayBuffer' - | 'auto' - | 'blob' - | 'formData' - | 'json' - | 'stream' - | 'text'; + parseAs?: "arrayBuffer" | "auto" | "blob" | "formData" | "json" | "stream" | "text" /** * Should we return only data or multiple fields (data, error, response, etc.)? * * @default 'fields' */ - responseStyle?: ResponseStyle; + responseStyle?: ResponseStyle /** * Throw an error instead of returning it in the response? * * @default false */ - throwOnError?: T['throwOnError']; + throwOnError?: T["throwOnError"] } export interface RequestOptions< - TResponseStyle extends ResponseStyle = 'fields', + TResponseStyle extends ResponseStyle = "fields", ThrowOnError extends boolean = boolean, Url extends string = string, > extends Config<{ - responseStyle: TResponseStyle; - throwOnError: ThrowOnError; + 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; - query?: Record; + body?: unknown + path?: Record + query?: Record /** * Security mechanism(s) to use for the request. */ - security?: ReadonlyArray; - url: Url; + security?: ReadonlyArray + url: Url } export type RequestResult< TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean, - TResponseStyle extends ResponseStyle = 'fields', + TResponseStyle extends ResponseStyle = "fields", > = ThrowOnError extends true ? Promise< - TResponseStyle extends 'data' + TResponseStyle extends "data" ? TData extends Record ? TData[keyof TData] : TData : { - data: TData extends Record - ? TData[keyof TData] - : TData; - request: Request; - response: Response; + data: TData extends Record ? TData[keyof TData] : TData + request: Request + response: Response } > : Promise< - TResponseStyle extends 'data' - ? - | (TData extends Record - ? TData[keyof TData] - : TData) - | undefined + TResponseStyle extends "data" + ? (TData extends Record ? TData[keyof TData] : TData) | undefined : ( | { - data: TData extends Record - ? TData[keyof TData] - : TData; - error: undefined; + data: TData extends Record ? TData[keyof TData] : TData + error: undefined } | { - data: undefined; - error: TError extends Record - ? TError[keyof TError] - : TError; + data: undefined + error: TError extends Record ? TError[keyof TError] : TError } ) & { - request: Request; - response: Response; + request: Request + response: Response } - >; + > export interface ClientOptions { - baseUrl?: string; - responseStyle?: ResponseStyle; - throwOnError?: boolean; + baseUrl?: string + responseStyle?: ResponseStyle + throwOnError?: boolean } type MethodFn = < TData = unknown, TError = unknown, ThrowOnError extends boolean = false, - TResponseStyle extends ResponseStyle = 'fields', + TResponseStyle extends ResponseStyle = "fields", >( - options: Omit, 'method'>, -) => RequestResult; + options: Omit, "method">, +) => RequestResult type RequestFn = < TData = unknown, TError = unknown, ThrowOnError extends boolean = false, - TResponseStyle extends ResponseStyle = 'fields', + TResponseStyle extends ResponseStyle = "fields", >( - options: Omit, 'method'> & - Pick>, 'method'>, -) => RequestResult; + options: Omit, "method"> & + Pick>, "method">, +) => RequestResult type BuildUrlFn = < TData extends { - body?: unknown; - path?: Record; - query?: Record; - url: string; + body?: unknown + path?: Record + query?: Record + url: string }, >( - options: Pick & Options, -) => string; + options: Pick & Options, +) => string export type Client = CoreClient & { - interceptors: Middleware; -}; + interceptors: Middleware +} /** * The `createClientConfig()` function will be called on client initialization @@ -176,47 +156,36 @@ export type Client = CoreClient & { */ export type CreateClientConfig = ( override?: Config, -) => Config & T>; +) => Config & T> export interface TDataShape { - body?: unknown; - headers?: unknown; - path?: unknown; - query?: unknown; - url: string; + body?: unknown + headers?: unknown + path?: unknown + query?: unknown + url: string } -type OmitKeys = Pick>; +type OmitKeys = Pick> export type Options< TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, - TResponseStyle extends ResponseStyle = 'fields', -> = OmitKeys< - RequestOptions, - 'body' | 'path' | 'query' | 'url' -> & - Omit; + TResponseStyle extends ResponseStyle = "fields", +> = OmitKeys, "body" | "path" | "query" | "url"> & Omit export type OptionsLegacyParser< TData = unknown, ThrowOnError extends boolean = boolean, - TResponseStyle extends ResponseStyle = 'fields', + TResponseStyle extends ResponseStyle = "fields", > = TData extends { body?: any } ? TData extends { headers?: any } - ? OmitKeys< - RequestOptions, - 'body' | 'headers' | 'url' - > & - TData - : OmitKeys, 'body' | 'url'> & + ? OmitKeys, "body" | "headers" | "url"> & TData + : OmitKeys, "body" | "url"> & TData & - Pick, 'headers'> + Pick, "headers"> : TData extends { headers?: any } - ? OmitKeys< - RequestOptions, - 'headers' | 'url' - > & + ? OmitKeys, "headers" | "url"> & TData & - Pick, 'body'> - : OmitKeys, 'url'> & TData; + Pick, "body"> + : OmitKeys, "url"> & TData diff --git a/packages/sdk/js/src/gen/client/utils.ts b/packages/sdk/js/src/gen/client/utils.ts index a52e67292..7b7942633 100644 --- a/packages/sdk/js/src/gen/client/utils.ts +++ b/packages/sdk/js/src/gen/client/utils.ts @@ -1,64 +1,54 @@ -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'; +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; - url: string; + path: Record + url: string } -const PATH_PARAM_RE = /\{[^{}]+\}/g; +const PATH_PARAM_RE = /\{[^{}]+\}/g -type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; -type MatrixStyle = 'label' | 'matrix' | 'simple'; -type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +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); + 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'; + 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.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'; + if (name.startsWith(".")) { + name = name.substring(1) + style = "label" + } else if (name.startsWith(";")) { + name = name.substring(1) + style = "matrix" } - const value = path[name]; + const value = path[name] if (value === undefined || value === null) { - continue; + continue } if (Array.isArray(value)) { - url = url.replace( - match, - serializeArrayParam({ explode, name, style, value }), - ); - continue; + url = url.replace(match, serializeArrayParam({ explode, name, style, value })) + continue } - if (typeof value === 'object') { + if (typeof value === "object") { url = url.replace( match, serializeObjectParam({ @@ -68,43 +58,37 @@ const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { value: value as Record, valueOnly: true, }), - ); - continue; + ) + continue } - if (style === 'matrix') { + if (style === "matrix") { url = url.replace( match, `;${serializePrimitiveParam({ name, value: value as string, })}`, - ); - continue; + ) + continue } - const replaceValue = encodeURIComponent( - style === 'label' ? `.${value as string}` : (value as string), - ); - url = url.replace(match, replaceValue); + const replaceValue = encodeURIComponent(style === "label" ? `.${value as string}` : (value as string)) + url = url.replace(match, replaceValue) } } - return url; -}; + return url +} -export const createQuerySerializer = ({ - allowReserved, - array, - object, -}: QuerySerializerOptions = {}) => { +export const createQuerySerializer = ({ allowReserved, array, object }: QuerySerializerOptions = {}) => { const querySerializer = (queryParams: T) => { - const search: string[] = []; - if (queryParams && typeof queryParams === 'object') { + const search: string[] = [] + if (queryParams && typeof queryParams === "object") { for (const name in queryParams) { - const value = queryParams[name]; + const value = queryParams[name] if (value === undefined || value === null) { - continue; + continue } if (Array.isArray(value)) { @@ -112,129 +96,120 @@ export const createQuerySerializer = ({ allowReserved, explode: true, name, - style: 'form', + style: "form", value, ...array, - }); - if (serializedArray) search.push(serializedArray); - } else if (typeof value === 'object') { + }) + if (serializedArray) search.push(serializedArray) + } else if (typeof value === "object") { const serializedObject = serializeObjectParam({ allowReserved, explode: true, name, - style: 'deepObject', + style: "deepObject", value: value as Record, ...object, - }); - if (serializedObject) search.push(serializedObject); + }) + if (serializedObject) search.push(serializedObject) } else { const serializedPrimitive = serializePrimitiveParam({ allowReserved, name, value: value as string, - }); - if (serializedPrimitive) search.push(serializedPrimitive); + }) + if (serializedPrimitive) search.push(serializedPrimitive) } } } - return search.join('&'); - }; - return querySerializer; -}; + return search.join("&") + } + return querySerializer +} /** * Infers parseAs value from provided Content-Type header. */ -export const getParseAs = ( - contentType: string | null, -): Exclude => { +export const getParseAs = (contentType: string | null): Exclude => { 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'; + return "stream" } - const cleanContent = contentType.split(';')[0]?.trim(); + const cleanContent = contentType.split(";")[0]?.trim() if (!cleanContent) { - return; + return } - if ( - cleanContent.startsWith('application/json') || - cleanContent.endsWith('+json') - ) { - return 'json'; + if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) { + return "json" } - if (cleanContent === 'multipart/form-data') { - return 'formData'; + if (cleanContent === "multipart/form-data") { + return "formData" } - if ( - ['application/', 'audio/', 'image/', 'video/'].some((type) => - cleanContent.startsWith(type), - ) - ) { - return 'blob'; + if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) { + return "blob" } - if (cleanContent.startsWith('text/')) { - return 'text'; + if (cleanContent.startsWith("text/")) { + return "text" } - return; -}; + return +} export const setAuthParams = async ({ security, ...options -}: Pick, 'security'> & - Pick & { - headers: Headers; +}: Pick, "security"> & + Pick & { + headers: Headers }) => { for (const auth of security) { - const token = await getAuthToken(auth, options.auth); + const token = await getAuthToken(auth, options.auth) if (!token) { - continue; + continue } - const name = auth.name ?? 'Authorization'; + const name = auth.name ?? "Authorization" switch (auth.in) { - case 'query': + case "query": if (!options.query) { - options.query = {}; + options.query = {} } - options.query[name] = token; - break; - case 'cookie': - options.headers.append('Cookie', `${name}=${token}`); - break; - case 'header': + options.query[name] = token + break + case "cookie": + options.headers.append("Cookie", `${name}=${token}`) + break + case "header": default: - options.headers.set(name, token); - break; + options.headers.set(name, token) + break } - return; + return } -}; +} -export const buildUrl: Client['buildUrl'] = (options) => { +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' + typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer), url: options.url, - }); - return url; -}; + }) + return url +} export const getUrl = ({ baseUrl, @@ -243,144 +218,125 @@ export const getUrl = ({ querySerializer, url: _url, }: { - baseUrl?: string; - path?: Record; - query?: Record; - querySerializer: QuerySerializer; - url: string; + baseUrl?: string + path?: Record + query?: Record + querySerializer: QuerySerializer + url: string }) => { - const pathUrl = _url.startsWith('/') ? _url : `/${_url}`; - let url = (baseUrl ?? '') + pathUrl; + const pathUrl = _url.startsWith("/") ? _url : `/${_url}` + let url = (baseUrl ?? "") + pathUrl if (path) { - url = defaultPathSerializer({ path, url }); + url = defaultPathSerializer({ path, url }) } - let search = query ? querySerializer(query) : ''; - if (search.startsWith('?')) { - search = search.substring(1); + let search = query ? querySerializer(query) : "" + if (search.startsWith("?")) { + search = search.substring(1) } if (search) { - url += `?${search}`; + url += `?${search}` } - return url; -}; + 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); + 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; -}; + config.headers = mergeHeaders(a.headers, b.headers) + return config +} -export const mergeHeaders = ( - ...headers: Array['headers'] | undefined> -): Headers => { - const mergedHeaders = new Headers(); +export const mergeHeaders = (...headers: Array["headers"] | undefined>): Headers => { + const mergedHeaders = new Headers() for (const header of headers) { - if (!header || typeof header !== 'object') { - continue; + if (!header || typeof header !== "object") { + continue } - const iterator = - header instanceof Headers ? header.entries() : Object.entries(header); + const iterator = header instanceof Headers ? header.entries() : Object.entries(header) for (const [key, value] of iterator) { if (value === null) { - mergedHeaders.delete(key); + mergedHeaders.delete(key) } else if (Array.isArray(value)) { for (const v of value) { - mergedHeaders.append(key, v as string); + 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), - ); + mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : (value as string)) } } } - return mergedHeaders; -}; + return mergedHeaders +} type ErrInterceptor = ( error: Err, response: Res, request: Req, options: Options, -) => Err | Promise; +) => Err | Promise -type ReqInterceptor = ( - request: Req, - options: Options, -) => Req | Promise; +type ReqInterceptor = (request: Req, options: Options) => Req | Promise -type ResInterceptor = ( - response: Res, - request: Req, - options: Options, -) => Res | Promise; +type ResInterceptor = (response: Res, request: Req, options: Options) => Res | Promise class Interceptors { - _fns: (Interceptor | null)[]; + _fns: (Interceptor | null)[] constructor() { - this._fns = []; + this._fns = [] } clear() { - this._fns = []; + this._fns = [] } getInterceptorIndex(id: number | Interceptor): number { - if (typeof id === 'number') { - return this._fns[id] ? id : -1; + if (typeof id === "number") { + return this._fns[id] ? id : -1 } else { - return this._fns.indexOf(id); + return this._fns.indexOf(id) } } exists(id: number | Interceptor) { - const index = this.getInterceptorIndex(id); - return !!this._fns[index]; + const index = this.getInterceptorIndex(id) + return !!this._fns[index] } eject(id: number | Interceptor) { - const index = this.getInterceptorIndex(id); + const index = this.getInterceptorIndex(id) if (this._fns[index]) { - this._fns[index] = null; + this._fns[index] = null } } update(id: number | Interceptor, fn: Interceptor) { - const index = this.getInterceptorIndex(id); + const index = this.getInterceptorIndex(id) if (this._fns[index]) { - this._fns[index] = fn; - return id; + this._fns[index] = fn + return id } else { - return false; + return false } } use(fn: Interceptor) { - this._fns = [...this._fns, fn]; - return this._fns.length - 1; + 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 { - error: Pick< - Interceptors>, - 'eject' | 'use' - >; - request: Pick>, 'eject' | 'use'>; - response: Pick< - Interceptors>, - 'eject' | 'use' - >; + error: Pick>, "eject" | "use"> + request: Pick>, "eject" | "use"> + response: Pick>, "eject" | "use"> } // do not add `Middleware` as return type so we can use _fns internally @@ -388,30 +344,30 @@ export const createInterceptors = () => ({ error: new Interceptors>(), request: new Interceptors>(), response: new Interceptors>(), -}); +}) const defaultQuerySerializer = createQuerySerializer({ allowReserved: false, array: { explode: true, - style: 'form', + style: "form", }, object: { explode: true, - style: 'deepObject', + style: "deepObject", }, -}); +}) const defaultHeaders = { - 'Content-Type': 'application/json', -}; + "Content-Type": "application/json", +} export const createConfig = ( override: Config & T> = {}, ): Config & T> => ({ ...jsonBodySerializer, headers: defaultHeaders, - parseAs: 'auto', + 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 index 451c7f30f..e496d4557 100644 --- a/packages/sdk/js/src/gen/core/auth.ts +++ b/packages/sdk/js/src/gen/core/auth.ts @@ -1,4 +1,4 @@ -export type AuthToken = string | undefined; +export type AuthToken = string | undefined export interface Auth { /** @@ -6,35 +6,34 @@ export interface Auth { * * @default 'header' */ - in?: 'header' | 'query' | 'cookie'; + in?: "header" | "query" | "cookie" /** * Header or query parameter name. * * @default 'Authorization' */ - name?: string; - scheme?: 'basic' | 'bearer'; - type: 'apiKey' | 'http'; + name?: string + scheme?: "basic" | "bearer" + type: "apiKey" | "http" } export const getAuthToken = async ( auth: Auth, callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, ): Promise => { - const token = - typeof callback === 'function' ? await callback(auth) : callback; + const token = typeof callback === "function" ? await callback(auth) : callback if (!token) { - return; + return } - if (auth.scheme === 'bearer') { - return `Bearer ${token}`; + if (auth.scheme === "bearer") { + return `Bearer ${token}` } - if (auth.scheme === 'basic') { - return `Basic ${btoa(token)}`; + if (auth.scheme === "basic") { + return `Basic ${btoa(token)}` } - return token; -}; + return token +} diff --git a/packages/sdk/js/src/gen/core/bodySerializer.ts b/packages/sdk/js/src/gen/core/bodySerializer.ts index 98ce7791f..45b2e9943 100644 --- a/packages/sdk/js/src/gen/core/bodySerializer.ts +++ b/packages/sdk/js/src/gen/core/bodySerializer.ts @@ -1,88 +1,70 @@ -import type { - ArrayStyle, - ObjectStyle, - SerializerOptions, -} from './pathSerializer'; +import type { ArrayStyle, ObjectStyle, SerializerOptions } from "./pathSerializer" -export type QuerySerializer = (query: Record) => string; +export type QuerySerializer = (query: Record) => string -export type BodySerializer = (body: any) => any; +export type BodySerializer = (body: any) => any export interface QuerySerializerOptions { - allowReserved?: boolean; - array?: SerializerOptions; - object?: SerializerOptions; + allowReserved?: boolean + array?: SerializerOptions + object?: SerializerOptions } -const serializeFormDataPair = ( - data: FormData, - key: string, - value: unknown, -): void => { - if (typeof value === 'string' || value instanceof Blob) { - data.append(key, value); +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)); + data.append(key, JSON.stringify(value)) } -}; +} -const serializeUrlSearchParamsPair = ( - data: URLSearchParams, - key: string, - value: unknown, -): void => { - if (typeof value === 'string') { - data.append(key, 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)); + data.append(key, JSON.stringify(value)) } -}; +} export const formDataBodySerializer = { - bodySerializer: | Array>>( - body: T, - ): FormData => { - const data = new FormData(); + bodySerializer: | Array>>(body: T): FormData => { + const data = new FormData() Object.entries(body).forEach(([key, value]) => { if (value === undefined || value === null) { - return; + return } if (Array.isArray(value)) { - value.forEach((v) => serializeFormDataPair(data, key, v)); + value.forEach((v) => serializeFormDataPair(data, key, v)) } else { - serializeFormDataPair(data, key, value); + serializeFormDataPair(data, key, value) } - }); + }) - return data; + return data }, -}; +} export const jsonBodySerializer = { bodySerializer: (body: T): string => - JSON.stringify(body, (_key, value) => - typeof value === 'bigint' ? value.toString() : value, - ), -}; + JSON.stringify(body, (_key, value) => (typeof value === "bigint" ? value.toString() : value)), +} export const urlSearchParamsBodySerializer = { - bodySerializer: | Array>>( - body: T, - ): string => { - const data = new URLSearchParams(); + bodySerializer: | Array>>(body: T): string => { + const data = new URLSearchParams() Object.entries(body).forEach(([key, value]) => { if (value === undefined || value === null) { - return; + return } if (Array.isArray(value)) { - value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)) } else { - serializeUrlSearchParamsPair(data, key, value); + serializeUrlSearchParamsPair(data, key, value) } - }); + }) - return data.toString(); + return data.toString() }, -}; +} diff --git a/packages/sdk/js/src/gen/core/params.ts b/packages/sdk/js/src/gen/core/params.ts index ba35263d8..0a09619d1 100644 --- a/packages/sdk/js/src/gen/core/params.ts +++ b/packages/sdk/js/src/gen/core/params.ts @@ -1,142 +1,133 @@ -type Slot = 'body' | 'headers' | 'path' | 'query'; +type Slot = "body" | "headers" | "path" | "query" export type Field = | { - in: Exclude; + in: Exclude /** * Field name. This is the name we want the user to see and use. */ - key: string; + 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; + map?: string } | { - in: Extract; + in: Extract /** * Key isn't required for bodies. */ - key?: string; - map?: string; - }; + key?: string + map?: string + } export interface Fields { - allowExtra?: Partial>; - args?: ReadonlyArray; + allowExtra?: Partial> + args?: ReadonlyArray } -export type FieldsConfig = ReadonlyArray; +export type FieldsConfig = ReadonlyArray const extraPrefixesMap: Record = { - $body_: 'body', - $headers_: 'headers', - $path_: 'path', - $query_: 'query', -}; -const extraPrefixes = Object.entries(extraPrefixesMap); + $body_: "body", + $headers_: "headers", + $path_: "path", + $query_: "query", +} +const extraPrefixes = Object.entries(extraPrefixesMap) type KeyMap = Map< string, { - in: Slot; - map?: string; + in: Slot + map?: string } ->; +> const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { if (!map) { - map = new Map(); + map = new Map() } for (const config of fields) { - if ('in' in config) { + 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); + buildKeyMap(config.args, map) } } - return map; -}; + return map +} interface Params { - body: unknown; - headers: Record; - path: Record; - query: Record; + body: unknown + headers: Record + path: Record + query: Record } 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]; + if (value && typeof value === "object" && !Object.keys(value).length) { + delete params[slot as Slot] } } -}; +} -export const buildClientParams = ( - args: ReadonlyArray, - fields: FieldsConfig, -) => { +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { const params: Params = { body: {}, headers: {}, path: {}, query: {}, - }; + } - const map = buildKeyMap(fields); + const map = buildKeyMap(fields) - let config: FieldsConfig[number] | undefined; + let config: FieldsConfig[number] | undefined for (const [index, arg] of args.entries()) { if (fields[index]) { - config = fields[index]; + config = fields[index] } if (!config) { - continue; + continue } - if ('in' in config) { + if ("in" in config) { if (config.key) { - const field = map.get(config.key)!; - const name = field.map || config.key; - (params[field.in] as Record)[name] = arg; + const field = map.get(config.key)! + const name = field.map || config.key + ;(params[field.in] as Record)[name] = arg } else { - params.body = arg; + params.body = arg } } else { for (const [key, value] of Object.entries(arg ?? {})) { - const field = map.get(key); + const field = map.get(key) if (field) { - const name = field.map || key; - (params[field.in] as Record)[name] = value; + const name = field.map || key + ;(params[field.in] as Record)[name] = value } else { - const extra = extraPrefixes.find(([prefix]) => - key.startsWith(prefix), - ); + const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix)) if (extra) { - const [prefix, slot] = extra; - (params[slot] as Record)[ - key.slice(prefix.length) - ] = value; + const [prefix, slot] = extra + ;(params[slot] as Record)[key.slice(prefix.length)] = value } else { - for (const [slot, allowed] of Object.entries( - config.allowExtra ?? {}, - )) { + for (const [slot, allowed] of Object.entries(config.allowExtra ?? {})) { if (allowed) { - (params[slot as Slot] as Record)[key] = value; - break; + ;(params[slot as Slot] as Record)[key] = value + break } } } @@ -145,7 +136,7 @@ export const buildClientParams = ( } } - stripEmptySlots(params); + stripEmptySlots(params) - return params; -}; + return params +} diff --git a/packages/sdk/js/src/gen/core/pathSerializer.ts b/packages/sdk/js/src/gen/core/pathSerializer.ts index d692cf0a3..1e27c8d18 100644 --- a/packages/sdk/js/src/gen/core/pathSerializer.ts +++ b/packages/sdk/js/src/gen/core/pathSerializer.ts @@ -1,68 +1,66 @@ -interface SerializeOptions - extends SerializePrimitiveOptions, - SerializerOptions {} +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} interface SerializePrimitiveOptions { - allowReserved?: boolean; - name: string; + allowReserved?: boolean + name: string } export interface SerializerOptions { /** * @default true */ - explode: boolean; - style: T; + 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; +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; + value: string } export const separatorArrayExplode = (style: ArraySeparatorStyle) => { switch (style) { - case 'label': - return '.'; - case 'matrix': - return ';'; - case 'simple': - return ','; + case "label": + return "." + case "matrix": + return ";" + case "simple": + return "," default: - return '&'; + return "&" } -}; +} export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { switch (style) { - case 'form': - return ','; - case 'pipeDelimited': - return '|'; - case 'spaceDelimited': - return '%20'; + case "form": + return "," + case "pipeDelimited": + return "|" + case "spaceDelimited": + return "%20" default: - return ','; + return "," } -}; +} export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { switch (style) { - case 'label': - return '.'; - case 'matrix': - return ';'; - case 'simple': - return ','; + case "label": + return "." + case "matrix": + return ";" + case "simple": + return "," default: - return '&'; + return "&" } -}; +} export const serializeArrayParam = ({ allowReserved, @@ -71,60 +69,54 @@ export const serializeArrayParam = ({ style, value, }: SerializeOptions & { - value: unknown[]; + value: unknown[] }) => { if (!explode) { - const joinedValues = ( - allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) - ).join(separatorArrayNoExplode(style)); + 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; + case "label": + return `.${joinedValues}` + case "matrix": + return `;${name}=${joinedValues}` + case "simple": + return joinedValues default: - return `${name}=${joinedValues}`; + return `${name}=${joinedValues}` } } - const separator = separatorArrayExplode(style); + const separator = separatorArrayExplode(style) const joinedValues = value .map((v) => { - if (style === 'label' || style === 'simple') { - return allowReserved ? v : encodeURIComponent(v as string); + 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; -}; + .join(separator) + return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues +} -export const serializePrimitiveParam = ({ - allowReserved, - name, - value, -}: SerializePrimitiveParam) => { +export const serializePrimitiveParam = ({ allowReserved, name, value }: SerializePrimitiveParam) => { if (value === undefined || value === null) { - return ''; + return "" } - if (typeof value === 'object') { + if (typeof value === "object") { throw new Error( - 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', - ); + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.", + ) } - return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; -}; + return `${name}=${allowReserved ? value : encodeURIComponent(value)}` +} export const serializeObjectParam = ({ allowReserved, @@ -134,46 +126,40 @@ export const serializeObjectParam = ({ value, valueOnly, }: SerializeOptions & { - value: Record | Date; - valueOnly?: boolean; + value: Record | Date + valueOnly?: boolean }) => { if (value instanceof Date) { - return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}` } - if (style !== 'deepObject' && !explode) { - let values: string[] = []; + 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(','); + 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}`; + case "form": + return `${name}=${joinedValues}` + case "label": + return `.${joinedValues}` + case "matrix": + return `;${name}=${joinedValues}` default: - return joinedValues; + return joinedValues } } - const separator = separatorObjectExplode(style); + const separator = separatorObjectExplode(style) const joinedValues = Object.entries(value) .map(([key, v]) => serializePrimitiveParam({ allowReserved, - name: style === 'deepObject' ? `${name}[${key}]` : key, + name: style === "deepObject" ? `${name}[${key}]` : key, value: v as string, }), ) - .join(separator); - return style === 'label' || style === 'matrix' - ? separator + joinedValues - : joinedValues; -}; + .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 index 2dd4106fb..87cc8fec9 100644 --- a/packages/sdk/js/src/gen/core/types.ts +++ b/packages/sdk/js/src/gen/core/types.ts @@ -1,32 +1,23 @@ -import type { Auth, AuthToken } from './auth'; -import type { - BodySerializer, - QuerySerializer, - QuerySerializerOptions, -} from './bodySerializer'; +import type { Auth, AuthToken } from "./auth" +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer" -export interface Client< - RequestFn = never, - Config = unknown, - MethodFn = never, - BuildUrlFn = never, -> { +export interface Client { /** * 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; + 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 { @@ -34,12 +25,12 @@ 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; + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken /** * A function for serializing request body parameter. By default, * {@link JSON.stringify()} will be used. */ - bodySerializer?: BodySerializer | null; + bodySerializer?: BodySerializer | null /** * An object containing any HTTP headers that you want to pre-populate your * `Headers` object with. @@ -47,32 +38,14 @@ export interface Config { * {@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 - >; + | RequestInit["headers"] + | Record /** * 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'; + 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 @@ -83,24 +56,24 @@ export interface Config { * * {@link https://swagger.io/docs/specification/serialization/#query View examples} */ - querySerializer?: QuerySerializer | QuerySerializerOptions; + 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; + requestValidator?: (data: unknown) => Promise /** * 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; + responseTransformer?: (data: unknown) => Promise /** * 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; + responseValidator?: (data: unknown) => Promise } type IsExactlyNeverOrNeverUndefined = [T] extends [never] @@ -109,10 +82,8 @@ type IsExactlyNeverOrNeverUndefined = [T] extends [never] ? [undefined] extends [T] ? false : true - : false; + : false export type OmitNever> = { - [K in keyof T as IsExactlyNeverOrNeverUndefined extends true - ? never - : K]: T[K]; -}; + [K in keyof T as IsExactlyNeverOrNeverUndefined 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 index 23bc1f916..4ad7ff48b 100644 --- a/packages/sdk/js/src/gen/sdk.gen.ts +++ b/packages/sdk/js/src/gen/sdk.gen.ts @@ -1,426 +1,503 @@ // 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, SessionMessageData, SessionMessageResponses, SessionRevertData, SessionRevertResponses, SessionUnrevertData, SessionUnrevertResponses, PostSessionByIdPermissionsByPermissionIdData, PostSessionByIdPermissionsByPermissionIdResponses, ConfigProvidersData, ConfigProvidersResponses, FindTextData, FindTextResponses, FindFilesData, FindFilesResponses, FindSymbolsData, FindSymbolsResponses, FileReadData, FileReadResponses, FileStatusData, FileStatusResponses, AppLogData, AppLogResponses, AppModesData, AppModesResponses, TuiAppendPromptData, TuiAppendPromptResponses, TuiOpenHelpData, TuiOpenHelpResponses, TuiOpenSessionsData, TuiOpenSessionsResponses, TuiOpenThemesData, TuiOpenThemesResponses, TuiOpenModelsData, TuiOpenModelsResponses, TuiSubmitPromptData, TuiSubmitPromptResponses, TuiClearPromptData, TuiClearPromptResponses, TuiExecuteCommandData, TuiExecuteCommandResponses } from './types.gen'; -import { client as _heyApiClient } from './client.gen'; +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, + SessionMessageData, + SessionMessageResponses, + SessionRevertData, + SessionRevertResponses, + SessionUnrevertData, + SessionUnrevertResponses, + PostSessionByIdPermissionsByPermissionIdData, + PostSessionByIdPermissionsByPermissionIdResponses, + ConfigProvidersData, + ConfigProvidersResponses, + FindTextData, + FindTextResponses, + FindFilesData, + FindFilesResponses, + FindSymbolsData, + FindSymbolsResponses, + FileReadData, + FileReadResponses, + FileStatusData, + FileStatusResponses, + AppLogData, + AppLogResponses, + AppModesData, + AppModesResponses, + TuiAppendPromptData, + TuiAppendPromptResponses, + TuiOpenHelpData, + TuiOpenHelpResponses, + TuiOpenSessionsData, + TuiOpenSessionsResponses, + TuiOpenThemesData, + TuiOpenThemesResponses, + TuiOpenModelsData, + TuiOpenModelsResponses, + TuiSubmitPromptData, + TuiSubmitPromptResponses, + TuiClearPromptData, + TuiClearPromptResponses, + TuiExecuteCommandData, + TuiExecuteCommandResponses, +} from "./types.gen" +import { client as _heyApiClient } from "./client.gen" -export type Options = ClientOptions & { - /** - * 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; -}; +export type Options = 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 +} class _HeyApiClient { - protected _client: Client = _heyApiClient; - - constructor(args?: { - client?: Client; - }) { - if (args?.client) { - this._client = args.client; - } + protected _client: Client = _heyApiClient + + constructor(args?: { client?: Client }) { + if (args?.client) { + this._client = args.client } + } } class Event extends _HeyApiClient { - /** - * Get events - */ - public subscribe(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/event', - ...options - }); - } + /** + * Get events + */ + public subscribe(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/event", + ...options, + }) + } } class App extends _HeyApiClient { - /** - * Get app info - */ - public get(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/app', - ...options - }); - } - - /** - * Initialize the app - */ - public init(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/app/init', - ...options - }); - } - - /** - * Write a log entry to the server logs - */ - public log(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/log', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options?.headers - } - }); - } - - /** - * List all modes - */ - public modes(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/mode', - ...options - }); - } + /** + * Get app info + */ + public get(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/app", + ...options, + }) + } + + /** + * Initialize the app + */ + public init(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/app/init", + ...options, + }) + } + + /** + * Write a log entry to the server logs + */ + public log(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/log", + ...options, + headers: { + "Content-Type": "application/json", + ...options?.headers, + }, + }) + } + + /** + * List all modes + */ + public modes(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/mode", + ...options, + }) + } } class Config extends _HeyApiClient { - /** - * Get config info - */ - public get(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/config', - ...options - }); - } - - /** - * List all providers - */ - public providers(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/config/providers', - ...options - }); - } + /** + * Get config info + */ + public get(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/config", + ...options, + }) + } + + /** + * List all providers + */ + public providers(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/config/providers", + ...options, + }) + } } class Session extends _HeyApiClient { - /** - * List all sessions - */ - public list(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/session', - ...options - }); - } - - /** - * Create a new session - */ - public create(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/session', - ...options - }); - } - - /** - * Delete a session and all its data - */ - public delete(options: Options) { - return (options.client ?? this._client).delete({ - url: '/session/{id}', - ...options - }); - } - - /** - * Analyze the app and create an AGENTS.md file - */ - public init(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/init', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } - }); - } - - /** - * Abort a session - */ - public abort(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/abort', - ...options - }); - } - - /** - * Unshare the session - */ - public unshare(options: Options) { - return (options.client ?? this._client).delete({ - url: '/session/{id}/share', - ...options - }); - } - - /** - * Share a session - */ - public share(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/share', - ...options - }); - } - - /** - * Summarize the session - */ - public summarize(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/summarize', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } - }); - } - - /** - * List messages for a session - */ - public messages(options: Options) { - return (options.client ?? this._client).get({ - url: '/session/{id}/message', - ...options - }); - } - - /** - * Create and send a new message to a session - */ - public chat(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/message', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } - }); - } - - /** - * Get a message from a session - */ - public message(options: Options) { - return (options.client ?? this._client).get({ - url: '/session/{id}/message/{messageID}', - ...options - }); - } - - /** - * Revert a message - */ - public revert(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/revert', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } - }); - } - - /** - * Restore all reverted messages - */ - public unrevert(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/unrevert', - ...options - }); - } + /** + * List all sessions + */ + public list(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/session", + ...options, + }) + } + + /** + * Create a new session + */ + public create(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/session", + ...options, + }) + } + + /** + * Delete a session and all its data + */ + public delete(options: Options) { + return (options.client ?? this._client).delete({ + url: "/session/{id}", + ...options, + }) + } + + /** + * Analyze the app and create an AGENTS.md file + */ + public init(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/init", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }) + } + + /** + * Abort a session + */ + public abort(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/abort", + ...options, + }) + } + + /** + * Unshare the session + */ + public unshare(options: Options) { + return (options.client ?? this._client).delete({ + url: "/session/{id}/share", + ...options, + }) + } + + /** + * Share a session + */ + public share(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/share", + ...options, + }) + } + + /** + * Summarize the session + */ + public summarize(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/summarize", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }) + } + + /** + * List messages for a session + */ + public messages(options: Options) { + return (options.client ?? this._client).get({ + url: "/session/{id}/message", + ...options, + }) + } + + /** + * Create and send a new message to a session + */ + public chat(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/message", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }) + } + + /** + * Get a message from a session + */ + public message(options: Options) { + return (options.client ?? this._client).get({ + url: "/session/{id}/message/{messageID}", + ...options, + }) + } + + /** + * Revert a message + */ + public revert(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/revert", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }) + } + + /** + * Restore all reverted messages + */ + public unrevert(options: Options) { + return (options.client ?? this._client).post({ + url: "/session/{id}/unrevert", + ...options, + }) + } } class Find extends _HeyApiClient { - /** - * Find text in files - */ - public text(options: Options) { - return (options.client ?? this._client).get({ - url: '/find', - ...options - }); - } - - /** - * Find files - */ - public files(options: Options) { - return (options.client ?? this._client).get({ - url: '/find/file', - ...options - }); - } - - /** - * Find workspace symbols - */ - public symbols(options: Options) { - return (options.client ?? this._client).get({ - url: '/find/symbol', - ...options - }); - } + /** + * Find text in files + */ + public text(options: Options) { + return (options.client ?? this._client).get({ + url: "/find", + ...options, + }) + } + + /** + * Find files + */ + public files(options: Options) { + return (options.client ?? this._client).get({ + url: "/find/file", + ...options, + }) + } + + /** + * Find workspace symbols + */ + public symbols(options: Options) { + return (options.client ?? this._client).get({ + url: "/find/symbol", + ...options, + }) + } } class File extends _HeyApiClient { - /** - * Read a file - */ - public read(options: Options) { - return (options.client ?? this._client).get({ - url: '/file', - ...options - }); - } - - /** - * Get file status - */ - public status(options?: Options) { - return (options?.client ?? this._client).get({ - url: '/file/status', - ...options - }); - } + /** + * Read a file + */ + public read(options: Options) { + return (options.client ?? this._client).get({ + url: "/file", + ...options, + }) + } + + /** + * Get file status + */ + public status(options?: Options) { + return (options?.client ?? this._client).get({ + url: "/file/status", + ...options, + }) + } } class Tui extends _HeyApiClient { - /** - * Append prompt to the TUI - */ - public appendPrompt(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/append-prompt', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options?.headers - } - }); - } - - /** - * Open the help dialog - */ - public openHelp(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/open-help', - ...options - }); - } - - /** - * Open the session dialog - */ - public openSessions(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/open-sessions', - ...options - }); - } - - /** - * Open the theme dialog - */ - public openThemes(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/open-themes', - ...options - }); - } - - /** - * Open the model dialog - */ - public openModels(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/open-models', - ...options - }); - } - - /** - * Submit the prompt - */ - public submitPrompt(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/submit-prompt', - ...options - }); - } - - /** - * Clear the prompt - */ - public clearPrompt(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/clear-prompt', - ...options - }); - } - - /** - * Execute a TUI command (e.g. switch_mode) - */ - public executeCommand(options?: Options) { - return (options?.client ?? this._client).post({ - url: '/tui/execute-command', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options?.headers - } - }); - } + /** + * Append prompt to the TUI + */ + public appendPrompt(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/append-prompt", + ...options, + headers: { + "Content-Type": "application/json", + ...options?.headers, + }, + }) + } + + /** + * Open the help dialog + */ + public openHelp(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/open-help", + ...options, + }) + } + + /** + * Open the session dialog + */ + public openSessions(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/open-sessions", + ...options, + }) + } + + /** + * Open the theme dialog + */ + public openThemes(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/open-themes", + ...options, + }) + } + + /** + * Open the model dialog + */ + public openModels(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/open-models", + ...options, + }) + } + + /** + * Submit the prompt + */ + public submitPrompt(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/submit-prompt", + ...options, + }) + } + + /** + * Clear the prompt + */ + public clearPrompt(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/clear-prompt", + ...options, + }) + } + + /** + * Execute a TUI command (e.g. switch_mode) + */ + public executeCommand(options?: Options) { + return (options?.client ?? this._client).post({ + url: "/tui/execute-command", + ...options, + headers: { + "Content-Type": "application/json", + ...options?.headers, + }, + }) + } } export class OpencodeClient extends _HeyApiClient { - /** - * Respond to a permission request - */ - public postSessionByIdPermissionsByPermissionId(options: Options) { - return (options.client ?? this._client).post({ - url: '/session/{id}/permissions/{permissionID}', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } - }); - } - 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 + /** + * Respond to a permission request + */ + public postSessionByIdPermissionsByPermissionId( + options: Options, + ) { + return (options.client ?? this._client).post< + PostSessionByIdPermissionsByPermissionIdResponses, + unknown, + ThrowOnError + >({ + url: "/session/{id}/permissions/{permissionID}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, + }) + } + 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 }) +} diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 4d8fcadd2..74fa1a4fb 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -1,1639 +1,1690 @@ // 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: 'permission.replied'; -} & EventPermissionReplied) | ({ - 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 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: "file.edited" + } & EventFileEdited) + | ({ + type: "server.connected" + } & EventServerConnected) + | ({ + type: "permission.updated" + } & EventPermissionUpdated) + | ({ + type: "permission.replied" + } & EventPermissionReplied) + | ({ + type: "session.updated" + } & EventSessionUpdated) + | ({ + type: "session.deleted" + } & EventSessionDeleted) + | ({ + type: "session.idle" + } & EventSessionIdle) + | ({ + type: "session.error" + } & EventSessionError) + | ({ + type: "file.watcher.updated" + } & EventFileWatcherUpdated) + | ({ + type: "ide.installed" + } & EventIdeInstalled) export type EventInstallationUpdated = { - type: string; - properties: { - version: string; - }; -}; + type: string + properties: { + version: string + } +} export type EventLspClientDiagnostics = { - type: string; - properties: { - serverID: string; - path: string; - }; -}; + type: string + properties: { + serverID: string + path: string + } +} export type EventMessageUpdated = { - type: string; - properties: { - info: Message; - }; -}; + type: string + properties: { + info: Message + } +} -export type Message = ({ - role: 'user'; -} & UserMessage) | ({ - role: 'assistant'; -} & AssistantMessage); +export type Message = + | ({ + role: "user" + } & UserMessage) + | ({ + role: "assistant" + } & AssistantMessage) export type UserMessage = { - id: string; - sessionID: string; - role: string; - time: { - created: number; - }; -}; + 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; - 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; - }; - }; -}; + 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 + 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; - }; -}; + name: string + data: { + providerID: string + message: string + } +} export type UnknownError = { - name: string; - data: { - message: string; - }; -}; + name: string + data: { + message: string + } +} export type MessageOutputLengthError = { - name: string; - data: { - [key: string]: unknown; - }; -}; + name: string + data: { + [key: string]: unknown + } +} export type MessageAbortedError = { - name: string; - data: { - [key: string]: unknown; - }; -}; + name: string + data: { + [key: string]: unknown + } +} export type EventMessageRemoved = { - type: string; - properties: { - sessionID: string; - messageID: string; - }; -}; + type: string + properties: { + sessionID: string + messageID: string + } +} export type EventMessagePartUpdated = { - type: string; - properties: { - part: Part; - }; -}; + 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 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; - }; -}; + 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; -}; + 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 FilePartSource = + | ({ + type: "file" + } & FileSource) + | ({ + type: "symbol" + } & SymbolSource) export type FileSource = { - text: FilePartSourceText; - type: string; - path: string; -}; + text: FilePartSourceText + type: string + path: string +} export type FilePartSourceText = { - value: string; - start: number; - end: number; -}; + value: string + start: number + end: number +} export type SymbolSource = { - text: FilePartSourceText; - type: string; - path: string; - range: Range; - name: string; - kind: number; -}; + 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; - }; -}; + 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; -}; + 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 ToolState = + | ({ + status: "pending" + } & ToolStatePending) + | ({ + status: "running" + } & ToolStateRunning) + | ({ + status: "completed" + } & ToolStateCompleted) + | ({ + status: "error" + } & ToolStateError) export type ToolStatePending = { - status: string; -}; + status: string +} export type ToolStateRunning = { - status: string; - input?: unknown; - title?: string; - metadata?: { - [key: string]: unknown; - }; - time: { - start: number; - }; -}; + 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; - }; -}; + 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; - }; -}; + status: string + input: { + [key: string]: unknown + } + error: string + time: { + start: number + end: number + } +} export type StepStartPart = { - id: string; - sessionID: string; - messageID: string; - type: string; -}; + 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; - }; - }; -}; + 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; -}; + 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; -}; + id: string + sessionID: string + messageID: string + type: string + hash: string + files: Array +} export type EventMessagePartRemoved = { - type: string; - properties: { - sessionID: string; - messageID: string; - partID: string; - }; -}; + 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: Permission; -}; - -export type Permission = { - id: string; - type: string; - pattern?: string; - sessionID: string; - messageID: string; - callID?: string; - title: string; - metadata: { - [key: string]: unknown; - }; - time: { - created: number; - }; -}; - -export type EventPermissionReplied = { - type: string; - properties: { - sessionID: string; - permissionID: string; - response: string; - }; -}; + type: string + properties: { + key: string + content?: unknown + } +} 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); - }; -}; + type: string + properties: { + file: string + } +} export type EventServerConnected = { - type: string; - properties: { - [key: string]: unknown; - }; -}; + type: string + properties: { + [key: string]: unknown + } +} + +export type EventPermissionUpdated = { + type: string + properties: Permission +} + +export type Permission = { + id: string + type: string + pattern?: string + sessionID: string + messageID: string + callID?: string + title: string + metadata: { + [key: string]: unknown + } + time: { + created: number + } +} + +export type EventPermissionReplied = { + type: string + properties: { + sessionID: string + permissionID: string + response: 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 EventFileWatcherUpdated = { - type: string; - properties: { - file: string; - event: string; - }; -}; + type: string + properties: { + file: string + event: string + } +} export type EventIdeInstalled = { - type: string; - properties: { - ide: string; - }; -}; + 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; - }; -}; + 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; - /** - * 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?: { + /** + * JSON schema reference for configuration validation + */ + $schema?: string + /** + * Theme name to use for the interface + */ + theme?: string + keybinds?: KeybindsConfig + plugin?: Array + /** + * 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 + /** + * 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 + id?: string + npm?: string + models: { [key: string]: { - api?: string; - name?: string; - env?: Array; - 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); - }; - formatter?: { - [key: string]: { - disabled?: boolean; - command?: Array; - environment?: { - [key: string]: string; - }; - extensions?: Array; - }; - }; - lsp?: { - [key: string]: { - disabled: boolean; - } | { - command: Array; - extensions?: Array; - disabled?: boolean; - env?: { - [key: string]: string; - }; - initialization?: { - [key: string]: unknown; - }; - }; - }; - /** - * Additional instruction files or patterns to include - */ - instructions?: Array; - layout?: LayoutConfig; - permission?: { - edit?: string; - bash?: string | { - [key: string]: string; - }; - }; - experimental?: { - hook?: { - file_edited?: { - [key: string]: Array<{ - command: Array; - environment?: { - [key: string]: string; - }; - }>; - }; - session_completed?: Array<{ - command: Array; - environment?: { - [key: string]: 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) + } + formatter?: { + [key: string]: { + disabled?: boolean + command?: Array + environment?: { + [key: string]: string + } + extensions?: Array + } + } + lsp?: { + [key: string]: + | { + disabled: boolean + } + | { + command: Array + extensions?: Array + disabled?: boolean + env?: { + [key: string]: string + } + initialization?: { + [key: string]: unknown + } + } + } + /** + * Additional instruction files or patterns to include + */ + instructions?: Array + layout?: LayoutConfig + permission?: { + edit?: string + bash?: + | string + | { + [key: string]: string + } + } + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array + environment?: { + [key: string]: string + } + }> + } + session_completed?: Array<{ + command: Array + 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; -}; + /** + * 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; - top_p?: number; - prompt?: string; - tools?: { - [key: string]: boolean; - }; - disable?: boolean; -}; + model?: string + temperature?: number + top_p?: number + prompt?: string + tools?: { + [key: string]: boolean + } + disable?: boolean +} export type AgentConfig = ModeConfig & { - description: string; -}; + description: string +} export type Provider = { - api?: string; - name: string; - env: Array; - id: string; - npm?: string; - models: { - [key: string]: Model; - }; -}; + api?: string + name: string + env: Array + 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; - }; -}; + 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; - /** - * Environment variables to set when running the MCP server - */ - environment?: { - [key: string]: string; - }; - /** - * Enable or disable the MCP server on startup - */ - enabled?: boolean; -}; + /** + * Type of MCP server connection + */ + type: string + /** + * Command and arguments to run the MCP server + */ + command: Array + /** + * 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; - }; -}; + /** + * 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 LayoutConfig = "auto" | "stretch" export type _Error = { - data: { - [key: string]: unknown; - }; -}; + data: { + [key: string]: unknown + } +} export type TextPartInput = { - id?: string; - type: string; - text: string; - synthetic?: boolean; - time?: { - start: number; - end?: number; - }; -}; + 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; -}; + id?: string + type: string + mime: string + filename?: string + url: string + source?: FilePartSource +} export type Symbol = { - name: string; - kind: number; - location: { - uri: string; - range: Range; - }; -}; + name: string + kind: number + location: { + uri: string + range: Range + } +} export type File = { - path: string; - added: number; - removed: number; - status: 'added' | 'deleted' | 'modified'; -}; + path: string + added: number + removed: number + status: "added" | "deleted" | "modified" +} export type Mode = { - name: string; - temperature?: number; - topP?: number; - model?: { - modelID: string; - providerID: string; - }; - prompt?: string; - tools: { - [key: string]: boolean; - }; -}; + name: string + temperature?: number + topP?: number + model?: { + modelID: string + providerID: string + } + prompt?: string + tools: { + [key: string]: boolean + } +} export type EventSubscribeData = { - body?: never; - path?: never; - query?: never; - url: '/event'; -}; + body?: never + path?: never + query?: never + url: "/event" +} export type EventSubscribeResponses = { - /** - * Event stream - */ - 200: Event; -}; + /** + * Event stream + */ + 200: Event +} -export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses]; +export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses] export type AppGetData = { - body?: never; - path?: never; - query?: never; - url: '/app'; -}; + body?: never + path?: never + query?: never + url: "/app" +} export type AppGetResponses = { - /** - * 200 - */ - 200: App; -}; + /** + * 200 + */ + 200: App +} -export type AppGetResponse = AppGetResponses[keyof AppGetResponses]; +export type AppGetResponse = AppGetResponses[keyof AppGetResponses] export type AppInitData = { - body?: never; - path?: never; - query?: never; - url: '/app/init'; -}; + body?: never + path?: never + query?: never + url: "/app/init" +} export type AppInitResponses = { - /** - * Initialize the app - */ - 200: boolean; -}; + /** + * Initialize the app + */ + 200: boolean +} -export type AppInitResponse = AppInitResponses[keyof AppInitResponses]; +export type AppInitResponse = AppInitResponses[keyof AppInitResponses] export type ConfigGetData = { - body?: never; - path?: never; - query?: never; - url: '/config'; -}; + body?: never + path?: never + query?: never + url: "/config" +} export type ConfigGetResponses = { - /** - * Get config info - */ - 200: Config; -}; + /** + * Get config info + */ + 200: Config +} -export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses]; +export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses] export type SessionListData = { - body?: never; - path?: never; - query?: never; - url: '/session'; -}; + body?: never + path?: never + query?: never + url: "/session" +} export type SessionListResponses = { - /** - * List of sessions - */ - 200: Array; -}; + /** + * List of sessions + */ + 200: Array +} -export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; +export type SessionListResponse = SessionListResponses[keyof SessionListResponses] export type SessionCreateData = { - body?: never; - path?: never; - query?: never; - url: '/session'; -}; + body?: never + path?: never + query?: never + url: "/session" +} export type SessionCreateErrors = { - /** - * Bad request - */ - 400: _Error; -}; + /** + * Bad request + */ + 400: _Error +} -export type SessionCreateError = SessionCreateErrors[keyof SessionCreateErrors]; +export type SessionCreateError = SessionCreateErrors[keyof SessionCreateErrors] export type SessionCreateResponses = { - /** - * Successfully created session - */ - 200: Session; -}; + /** + * Successfully created session + */ + 200: Session +} -export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses]; +export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses] export type SessionDeleteData = { - body?: never; - path: { - id: string; - }; - query?: never; - url: '/session/{id}'; -}; + body?: never + path: { + id: string + } + query?: never + url: "/session/{id}" +} export type SessionDeleteResponses = { - /** - * Successfully deleted session - */ - 200: boolean; -}; + /** + * Successfully deleted session + */ + 200: boolean +} -export type SessionDeleteResponse = SessionDeleteResponses[keyof SessionDeleteResponses]; +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'; -}; + body?: { + messageID: string + providerID: string + modelID: string + } + path: { + /** + * Session ID + */ + id: string + } + query?: never + url: "/session/{id}/init" +} export type SessionInitResponses = { - /** - * 200 - */ - 200: boolean; -}; + /** + * 200 + */ + 200: boolean +} -export type SessionInitResponse = SessionInitResponses[keyof SessionInitResponses]; +export type SessionInitResponse = SessionInitResponses[keyof SessionInitResponses] export type SessionAbortData = { - body?: never; - path: { - id: string; - }; - query?: never; - url: '/session/{id}/abort'; -}; + body?: never + path: { + id: string + } + query?: never + url: "/session/{id}/abort" +} export type SessionAbortResponses = { - /** - * Aborted session - */ - 200: boolean; -}; + /** + * Aborted session + */ + 200: boolean +} -export type SessionAbortResponse = SessionAbortResponses[keyof SessionAbortResponses]; +export type SessionAbortResponse = SessionAbortResponses[keyof SessionAbortResponses] export type SessionUnshareData = { - body?: never; - path: { - id: string; - }; - query?: never; - url: '/session/{id}/share'; -}; + body?: never + path: { + id: string + } + query?: never + url: "/session/{id}/share" +} export type SessionUnshareResponses = { - /** - * Successfully unshared session - */ - 200: Session; -}; + /** + * Successfully unshared session + */ + 200: Session +} -export type SessionUnshareResponse = SessionUnshareResponses[keyof SessionUnshareResponses]; +export type SessionUnshareResponse = SessionUnshareResponses[keyof SessionUnshareResponses] export type SessionShareData = { - body?: never; - path: { - id: string; - }; - query?: never; - url: '/session/{id}/share'; -}; + body?: never + path: { + id: string + } + query?: never + url: "/session/{id}/share" +} export type SessionShareResponses = { - /** - * Successfully shared session - */ - 200: Session; -}; + /** + * Successfully shared session + */ + 200: Session +} -export type SessionShareResponse = SessionShareResponses[keyof SessionShareResponses]; +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'; -}; + body?: { + providerID: string + modelID: string + } + path: { + /** + * Session ID + */ + id: string + } + query?: never + url: "/session/{id}/summarize" +} export type SessionSummarizeResponses = { - /** - * Summarized session - */ - 200: boolean; -}; + /** + * Summarized session + */ + 200: boolean +} -export type SessionSummarizeResponse = SessionSummarizeResponses[keyof SessionSummarizeResponses]; +export type SessionSummarizeResponse = SessionSummarizeResponses[keyof SessionSummarizeResponses] export type SessionMessagesData = { - body?: never; - path: { - /** - * Session ID - */ - id: string; - }; - query?: never; - url: '/session/{id}/message'; -}; + 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; - }>; -}; + /** + * List of messages + */ + 200: Array<{ + info: Message + parts: Array + }> +} -export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; +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'; -}; + 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; -}; + /** + * Created message + */ + 200: AssistantMessage +} -export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses]; +export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses] export type SessionMessageData = { - body?: never; - path: { - /** - * Session ID - */ - id: string; - /** - * Message ID - */ - messageID: string; - }; - query?: never; - url: '/session/{id}/message/{messageID}'; -}; + body?: never + path: { + /** + * Session ID + */ + id: string + /** + * Message ID + */ + messageID: string + } + query?: never + url: "/session/{id}/message/{messageID}" +} export type SessionMessageResponses = { - /** - * Message - */ - 200: { - info: Message; - parts: Array; - }; -}; + /** + * Message + */ + 200: { + info: Message + parts: Array + } +} -export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses]; +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses] export type SessionRevertData = { - body?: { - messageID: string; - partID?: string; - }; - path: { - id: string; - }; - query?: never; - url: '/session/{id}/revert'; -}; + body?: { + messageID: string + partID?: string + } + path: { + id: string + } + query?: never + url: "/session/{id}/revert" +} export type SessionRevertResponses = { - /** - * Updated session - */ - 200: Session; -}; + /** + * Updated session + */ + 200: Session +} -export type SessionRevertResponse = SessionRevertResponses[keyof SessionRevertResponses]; +export type SessionRevertResponse = SessionRevertResponses[keyof SessionRevertResponses] export type SessionUnrevertData = { - body?: never; - path: { - id: string; - }; - query?: never; - url: '/session/{id}/unrevert'; -}; + body?: never + path: { + id: string + } + query?: never + url: "/session/{id}/unrevert" +} export type SessionUnrevertResponses = { - /** - * Updated session - */ - 200: Session; -}; + /** + * Updated session + */ + 200: Session +} -export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses]; +export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses] export type PostSessionByIdPermissionsByPermissionIdData = { - body?: { - response: 'once' | 'always' | 'reject'; - }; - path: { - id: string; - permissionID: string; - }; - query?: never; - url: '/session/{id}/permissions/{permissionID}'; -}; + body?: { + response: "once" | "always" | "reject" + } + path: { + id: string + permissionID: string + } + query?: never + url: "/session/{id}/permissions/{permissionID}" +} export type PostSessionByIdPermissionsByPermissionIdResponses = { - /** - * Permission processed successfully - */ - 200: boolean; -}; + /** + * Permission processed successfully + */ + 200: boolean +} -export type PostSessionByIdPermissionsByPermissionIdResponse = PostSessionByIdPermissionsByPermissionIdResponses[keyof PostSessionByIdPermissionsByPermissionIdResponses]; +export type PostSessionByIdPermissionsByPermissionIdResponse = + PostSessionByIdPermissionsByPermissionIdResponses[keyof PostSessionByIdPermissionsByPermissionIdResponses] export type ConfigProvidersData = { - body?: never; - path?: never; - query?: never; - url: '/config/providers'; -}; + body?: never + path?: never + query?: never + url: "/config/providers" +} export type ConfigProvidersResponses = { - /** - * List of providers - */ - 200: { - providers: Array; - default: { - [key: string]: string; - }; - }; -}; + /** + * List of providers + */ + 200: { + providers: Array + default: { + [key: string]: string + } + } +} -export type ConfigProvidersResponse = ConfigProvidersResponses[keyof ConfigProvidersResponses]; +export type ConfigProvidersResponse = ConfigProvidersResponses[keyof ConfigProvidersResponses] export type FindTextData = { - body?: never; - path?: never; - query: { - pattern: string; - }; - url: '/find'; -}; + 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; - }>; - }>; -}; + /** + * 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 FindTextResponse = FindTextResponses[keyof FindTextResponses] export type FindFilesData = { - body?: never; - path?: never; - query: { - query: string; - }; - url: '/find/file'; -}; + body?: never + path?: never + query: { + query: string + } + url: "/find/file" +} export type FindFilesResponses = { - /** - * File paths - */ - 200: Array; -}; + /** + * File paths + */ + 200: Array +} -export type FindFilesResponse = FindFilesResponses[keyof FindFilesResponses]; +export type FindFilesResponse = FindFilesResponses[keyof FindFilesResponses] export type FindSymbolsData = { - body?: never; - path?: never; - query: { - query: string; - }; - url: '/find/symbol'; -}; + body?: never + path?: never + query: { + query: string + } + url: "/find/symbol" +} export type FindSymbolsResponses = { - /** - * Symbols - */ - 200: Array; -}; + /** + * Symbols + */ + 200: Array +} -export type FindSymbolsResponse = FindSymbolsResponses[keyof FindSymbolsResponses]; +export type FindSymbolsResponse = FindSymbolsResponses[keyof FindSymbolsResponses] export type FileReadData = { - body?: never; - path?: never; - query: { - path: string; - }; - url: '/file'; -}; + body?: never + path?: never + query: { + path: string + } + url: "/file" +} export type FileReadResponses = { - /** - * File content - */ - 200: { - type: 'raw' | 'patch'; - content: string; - }; -}; + /** + * File content + */ + 200: { + type: "raw" | "patch" + content: string + } +} -export type FileReadResponse = FileReadResponses[keyof FileReadResponses]; +export type FileReadResponse = FileReadResponses[keyof FileReadResponses] export type FileStatusData = { - body?: never; - path?: never; - query?: never; - url: '/file/status'; -}; + body?: never + path?: never + query?: never + url: "/file/status" +} export type FileStatusResponses = { - /** - * File status - */ - 200: Array; -}; + /** + * File status + */ + 200: Array +} -export type FileStatusResponse = FileStatusResponses[keyof FileStatusResponses]; +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'; -}; + 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; -}; + /** + * Log entry written successfully + */ + 200: boolean +} -export type AppLogResponse = AppLogResponses[keyof AppLogResponses]; +export type AppLogResponse = AppLogResponses[keyof AppLogResponses] export type AppModesData = { - body?: never; - path?: never; - query?: never; - url: '/mode'; -}; + body?: never + path?: never + query?: never + url: "/mode" +} export type AppModesResponses = { - /** - * List of modes - */ - 200: Array; -}; + /** + * List of modes + */ + 200: Array +} -export type AppModesResponse = AppModesResponses[keyof AppModesResponses]; +export type AppModesResponse = AppModesResponses[keyof AppModesResponses] export type TuiAppendPromptData = { - body?: { - text: string; - }; - path?: never; - query?: never; - url: '/tui/append-prompt'; -}; + body?: { + text: string + } + path?: never + query?: never + url: "/tui/append-prompt" +} export type TuiAppendPromptResponses = { - /** - * Prompt processed successfully - */ - 200: boolean; -}; + /** + * Prompt processed successfully + */ + 200: boolean +} -export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPromptResponses]; +export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPromptResponses] export type TuiOpenHelpData = { - body?: never; - path?: never; - query?: never; - url: '/tui/open-help'; -}; + body?: never + path?: never + query?: never + url: "/tui/open-help" +} export type TuiOpenHelpResponses = { - /** - * Help dialog opened successfully - */ - 200: boolean; -}; + /** + * Help dialog opened successfully + */ + 200: boolean +} -export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponses]; +export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponses] export type TuiOpenSessionsData = { - body?: never; - path?: never; - query?: never; - url: '/tui/open-sessions'; -}; + body?: never + path?: never + query?: never + url: "/tui/open-sessions" +} export type TuiOpenSessionsResponses = { - /** - * Session dialog opened successfully - */ - 200: boolean; -}; + /** + * Session dialog opened successfully + */ + 200: boolean +} -export type TuiOpenSessionsResponse = TuiOpenSessionsResponses[keyof TuiOpenSessionsResponses]; +export type TuiOpenSessionsResponse = TuiOpenSessionsResponses[keyof TuiOpenSessionsResponses] export type TuiOpenThemesData = { - body?: never; - path?: never; - query?: never; - url: '/tui/open-themes'; -}; + body?: never + path?: never + query?: never + url: "/tui/open-themes" +} export type TuiOpenThemesResponses = { - /** - * Theme dialog opened successfully - */ - 200: boolean; -}; + /** + * Theme dialog opened successfully + */ + 200: boolean +} -export type TuiOpenThemesResponse = TuiOpenThemesResponses[keyof TuiOpenThemesResponses]; +export type TuiOpenThemesResponse = TuiOpenThemesResponses[keyof TuiOpenThemesResponses] export type TuiOpenModelsData = { - body?: never; - path?: never; - query?: never; - url: '/tui/open-models'; -}; + body?: never + path?: never + query?: never + url: "/tui/open-models" +} export type TuiOpenModelsResponses = { - /** - * Model dialog opened successfully - */ - 200: boolean; -}; + /** + * Model dialog opened successfully + */ + 200: boolean +} -export type TuiOpenModelsResponse = TuiOpenModelsResponses[keyof TuiOpenModelsResponses]; +export type TuiOpenModelsResponse = TuiOpenModelsResponses[keyof TuiOpenModelsResponses] export type TuiSubmitPromptData = { - body?: never; - path?: never; - query?: never; - url: '/tui/submit-prompt'; -}; + body?: never + path?: never + query?: never + url: "/tui/submit-prompt" +} export type TuiSubmitPromptResponses = { - /** - * Prompt submitted successfully - */ - 200: boolean; -}; + /** + * Prompt submitted successfully + */ + 200: boolean +} -export type TuiSubmitPromptResponse = TuiSubmitPromptResponses[keyof TuiSubmitPromptResponses]; +export type TuiSubmitPromptResponse = TuiSubmitPromptResponses[keyof TuiSubmitPromptResponses] export type TuiClearPromptData = { - body?: never; - path?: never; - query?: never; - url: '/tui/clear-prompt'; -}; + body?: never + path?: never + query?: never + url: "/tui/clear-prompt" +} export type TuiClearPromptResponses = { - /** - * Prompt cleared successfully - */ - 200: boolean; -}; + /** + * Prompt cleared successfully + */ + 200: boolean +} -export type TuiClearPromptResponse = TuiClearPromptResponses[keyof TuiClearPromptResponses]; +export type TuiClearPromptResponse = TuiClearPromptResponses[keyof TuiClearPromptResponses] export type TuiExecuteCommandData = { - body?: { - command: string; - }; - path?: never; - query?: never; - url: '/tui/execute-command'; -}; + body?: { + command: string + } + path?: never + query?: never + url: "/tui/execute-command" +} export type TuiExecuteCommandResponses = { - /** - * Command executed successfully - */ - 200: boolean; -}; + /** + * Command executed successfully + */ + 200: boolean +} -export type TuiExecuteCommandResponse = TuiExecuteCommandResponses[keyof TuiExecuteCommandResponses]; +export type TuiExecuteCommandResponse = TuiExecuteCommandResponses[keyof TuiExecuteCommandResponses] export type ClientOptions = { - baseUrl: `${string}://${string}` | (string & {}); -}; \ No newline at end of file + baseUrl: `${string}://${string}` | (string & {}) +} diff --git a/packages/sdk/js/src/index.ts b/packages/sdk/js/src/index.ts index bdabf5f43..d133609f3 100644 --- a/packages/sdk/js/src/index.ts +++ b/packages/sdk/js/src/index.ts @@ -1,6 +1,7 @@ import { createClient } from "./gen/client/client" import { type Config } from "./gen/client/types" import { OpencodeClient } from "./gen/sdk.gen" +export * from "./gen/types.gen" export function createOpencodeClient(config?: Config) { const client = createClient(config) diff --git a/packages/sdk/js/tsconfig.json b/packages/sdk/js/tsconfig.json index dbd7732e5..78b4df451 100644 --- a/packages/sdk/js/tsconfig.json +++ b/packages/sdk/js/tsconfig.json @@ -5,7 +5,12 @@ "outDir": "dist", "module": "preserve", "declaration": true, - "moduleResolution": "bundler" + "moduleResolution": "bundler", + "lib": [ + "es2022", + "dom", + "dom.iterable" + ] }, "include": [ "src" diff --git a/packages/web/package.json b/packages/web/package.json index 548c84c39..eba66ad69 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode/web", "type": "module", - "version": "0.0.1", + "version": "0.0.0-202508022246", "scripts": { "dev": "astro dev", "dev:remote": "sst shell --stage=dev --target=Web astro dev", diff --git a/script/publish.ts b/script/publish.ts index fd498d42c..d9b08f36e 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -11,18 +11,39 @@ if (!version) { } process.env["OPENCODE_VERSION"] = version -await import(`../packages/opencode/script/publish.ts`) +const pkgjsons = await Array.fromAsync( + new Bun.Glob("**/package.json").scan({ + absolute: true, + }), +) + +const tree = await $`git add . && git write-tree`.text().then((x) => x.trim()) +for await (const file of new Bun.Glob("**/package.json").scan({ + absolute: true, +})) { + let pkg = await Bun.file(file).text() + pkg = pkg.replaceAll(/"version": "[^"]+"/g, `"version": "${version}"`) + await Bun.file(file).write(pkg) +} + +// await import(`../packages/opencode/script/publish.ts`) await import(`../packages/sdk/js/script/publish.ts`) +await import(`../packages/plugin/script/publish.ts`) // await import(`../packages/sdk/stainless/generate.ts`) if (!snapshot) { await $`git commit -am "release: v${version}"` await $`git tag v${version}` - await $`git push origin HEAD --tags` + await $`git push origin HEAD --tags --no-verify` } if (snapshot) { await $`git commit --allow-empty -m "Snapshot release v${version}"` await $`git tag v${version}` - await $`git push origin v${version}` + await $`git push origin v${version} --no-verify` await $`git reset --soft HEAD~1` + for await (const file of new Bun.Glob("**/package.json").scan({ + absolute: true, + })) { + $`await git checkout ${tree} ${file}` + } } diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index b42723729..7710444ca 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "0.0.0", + "version": "0.0.0-202508022246", "publisher": "sst-dev", "repository": { "type": "git",