diff options
| author | Dax <[email protected]> | 2025-12-07 19:04:14 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-07 19:04:14 -0500 |
| commit | ea7ec60f51f9fe3c6382f644c328188a43545b7b (patch) | |
| tree | 5204cbc059fe10b87c54ffd25782ad83710bdcdb /packages | |
| parent | 6667856ba5dac3e5dd77c7008cee2d09be894472 (diff) | |
| download | opencode-ea7ec60f51f9fe3c6382f644c328188a43545b7b.tar.gz opencode-ea7ec60f51f9fe3c6382f644c328188a43545b7b.zip | |
v2 SDK (#5216)
Co-authored-by: GitHub Action <[email protected]>
Diffstat (limited to 'packages')
57 files changed, 11141 insertions, 1057 deletions
diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx index a311ae763..dd1e00c6f 100644 --- a/packages/desktop/src/components/prompt-input.tsx +++ b/packages/desktop/src/components/prompt-input.tsx @@ -235,9 +235,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => { const abort = () => sdk.client.session.abort({ - path: { - id: session.id!, - }, + sessionID: session.id!, }) const handleKeyDown = (event: KeyboardEvent) => { @@ -329,21 +327,19 @@ export const PromptInput: Component<PromptInputProps> = (props) => { session.prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) sdk.client.session.prompt({ - path: { id: existing.id }, - body: { - agent: local.agent.current()!.name, - model: { - modelID: local.model.current()!.id, - providerID: local.model.current()!.provider.id, - }, - parts: [ - { - type: "text", - text, - }, - ...attachmentParts, - ], + sessionID: existing.id, + agent: local.agent.current()!.name, + model: { + modelID: local.model.current()!.id, + providerID: local.model.current()!.provider.id, }, + parts: [ + { + type: "text", + text, + }, + ...attachmentParts, + ], }) } diff --git a/packages/desktop/src/components/terminal.tsx b/packages/desktop/src/components/terminal.tsx index b312c3589..15302f152 100644 --- a/packages/desktop/src/components/terminal.tsx +++ b/packages/desktop/src/components/terminal.tsx @@ -74,12 +74,10 @@ export const Terminal = (props: TerminalProps) => { term.onResize(async (size) => { if (ws && ws.readyState === WebSocket.OPEN) { await sdk.client.pty.update({ - path: { id: local.pty.id }, - body: { - size: { - cols: size.cols, - rows: size.rows, - }, + ptyID: local.pty.id, + size: { + cols: size.cols, + rows: size.rows, }, }) } @@ -100,12 +98,10 @@ export const Terminal = (props: TerminalProps) => { ws.addEventListener("open", () => { console.log("WebSocket connected") sdk.client.pty.update({ - path: { id: local.pty.id }, - body: { - size: { - cols: term.cols, - rows: term.rows, - }, + ptyID: local.pty.id, + size: { + cols: term.cols, + rows: term.rows, }, }) }) diff --git a/packages/desktop/src/context/global-sdk.tsx b/packages/desktop/src/context/global-sdk.tsx index b9c72afcb..85b9e7584 100644 --- a/packages/desktop/src/context/global-sdk.tsx +++ b/packages/desktop/src/context/global-sdk.tsx @@ -1,4 +1,4 @@ -import { createOpencodeClient, type Event } from "@opencode-ai/sdk/client" +import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2/client" import { createSimpleContext } from "@opencode-ai/ui/context" import { createGlobalEmitter } from "@solid-primitives/event-bus" import { onCleanup } from "solid-js" diff --git a/packages/desktop/src/context/global-sync.tsx b/packages/desktop/src/context/global-sync.tsx index a8a6b9937..9f795cded 100644 --- a/packages/desktop/src/context/global-sync.tsx +++ b/packages/desktop/src/context/global-sync.tsx @@ -12,7 +12,7 @@ import type { FileDiff, Todo, SessionStatus, -} from "@opencode-ai/sdk" +} from "@opencode-ai/sdk/v2" import { createStore, produce, reconcile } from "solid-js/store" import { Binary } from "@opencode-ai/util/binary" import { createSimpleContext } from "@opencode-ai/ui/context" diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx index 68da03438..de4202d9a 100644 --- a/packages/desktop/src/context/local.tsx +++ b/packages/desktop/src/context/local.tsx @@ -1,7 +1,7 @@ import { createStore, produce, reconcile } from "solid-js/store" import { batch, createEffect, createMemo } from "solid-js" import { uniqueBy } from "remeda" -import type { FileContent, FileNode, Model, Provider, File as FileStatus } from "@opencode-ai/sdk" +import type { FileContent, FileNode, Model, Provider, File as FileStatus } from "@opencode-ai/sdk/v2" import { createSimpleContext } from "@opencode-ai/ui/context" import { useSDK } from "./sdk" import { useSync } from "./sync" @@ -257,7 +257,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const load = async (path: string) => { const relativePath = relative(path) - sdk.client.file.read({ query: { path: relativePath } }).then((x) => { + sdk.client.file.read({ path: relativePath }).then((x) => { setStore( "node", relativePath, @@ -305,7 +305,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } const list = async (path: string) => { - return sdk.client.file.list({ query: { path: path + "/" } }).then((x) => { + return sdk.client.file.list({ path: path + "/" }).then((x) => { setStore( "node", produce((draft) => { @@ -318,10 +318,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ }) } - const searchFiles = (query: string) => - sdk.client.find.files({ query: { query, dirs: "false" } }).then((x) => x.data!) + const searchFiles = (query: string) => sdk.client.find.files({ query, dirs: "false" }).then((x) => x.data!) const searchFilesAndDirectories = (query: string) => - sdk.client.find.files({ query: { query, dirs: "true" } }).then((x) => x.data!) + sdk.client.find.files({ query, dirs: "true" }).then((x) => x.data!) sdk.event.listen((e) => { const event = e.details diff --git a/packages/desktop/src/context/sdk.tsx b/packages/desktop/src/context/sdk.tsx index 144202ee2..764b01f8a 100644 --- a/packages/desktop/src/context/sdk.tsx +++ b/packages/desktop/src/context/sdk.tsx @@ -1,4 +1,4 @@ -import { createOpencodeClient, type Event } from "@opencode-ai/sdk/client" +import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2/client" import { createSimpleContext } from "@opencode-ai/ui/context" import { createGlobalEmitter } from "@solid-primitives/event-bus" import { onCleanup } from "solid-js" diff --git a/packages/desktop/src/context/session.tsx b/packages/desktop/src/context/session.tsx index b5972f3e3..5c0bad98a 100644 --- a/packages/desktop/src/context/session.tsx +++ b/packages/desktop/src/context/session.tsx @@ -5,7 +5,7 @@ import { useSync } from "./sync" import { makePersisted } from "@solid-primitives/storage" import { TextSelection } from "./local" import { pipe, sumBy } from "remeda" -import { AssistantMessage, UserMessage } from "@opencode-ai/sdk" +import { AssistantMessage, UserMessage } from "@opencode-ai/sdk/v2" import { useParams } from "@solidjs/router" import { base64Encode } from "@/utils" import { useSDK } from "./sdk" @@ -198,7 +198,7 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex all: createMemo(() => Object.values(store.terminals.all)), active: createMemo(() => store.terminals.active), new() { - sdk.client.pty.create({ body: { title: `Terminal ${store.terminals.all.length + 1}` } }).then((pty) => { + sdk.client.pty.create({ title: `Terminal ${store.terminals.all.length + 1}` }).then((pty) => { const id = pty.data?.id if (!id) return setStore("terminals", "all", [ @@ -214,8 +214,9 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex update(pty: Partial<LocalPTY> & { id: string }) { setStore("terminals", "all", (x) => x.map((x) => (x.id === pty.id ? { ...x, ...pty } : x))) sdk.client.pty.update({ - path: { id: pty.id }, - body: { title: pty.title, size: pty.cols && pty.rows ? { rows: pty.rows, cols: pty.cols } : undefined }, + ptyID: pty.id, + title: pty.title, + size: pty.cols && pty.rows ? { rows: pty.rows, cols: pty.cols } : undefined, }) }, async clone(id: string) { @@ -223,9 +224,7 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex const pty = store.terminals.all[index] if (!pty) return const clone = await sdk.client.pty.create({ - body: { - title: pty.title, - }, + title: pty.title, }) if (!clone.data) return setStore("terminals", "all", index, { @@ -252,7 +251,7 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex setStore("terminals", "active", previous) } }) - await sdk.client.pty.remove({ path: { id } }) + await sdk.client.pty.remove({ ptyID: id }) }, move(id: string, to: number) { const index = store.terminals.all.findIndex((f) => f.id === id) diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx index 3eb921a31..d8d7c7b95 100644 --- a/packages/desktop/src/context/sync.tsx +++ b/packages/desktop/src/context/sync.tsx @@ -28,7 +28,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ status: () => sdk.client.session.status().then((x) => setStore("session_status", x.data!)), config: () => sdk.client.config.get().then((x) => setStore("config", x.data!)), changes: () => sdk.client.file.status().then((x) => setStore("changes", x.data!)), - node: () => sdk.client.file.list({ query: { path: "/" } }).then((x) => setStore("node", x.data!)), + node: () => sdk.client.file.list({ path: "/" }).then((x) => setStore("node", x.data!)), } Promise.all(Object.values(load).map((p) => p())).then(() => setStore("ready", true)) @@ -49,10 +49,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ }, async sync(sessionID: string, _isRetry = false) { const [session, messages, todo, diff] = await Promise.all([ - sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }), - sdk.client.session.messages({ path: { id: sessionID }, query: { limit: 100 } }), - sdk.client.session.todo({ path: { id: sessionID } }), - sdk.client.session.diff({ path: { id: sessionID } }), + sdk.client.session.get({ sessionID }, { throwOnError: true }), + sdk.client.session.messages({ sessionID, limit: 100 }), + sdk.client.session.todo({ sessionID }), + sdk.client.session.diff({ sessionID }), ]) setStore( produce((draft) => { diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 29083cf6c..94ff4dd04 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -13,7 +13,7 @@ import { Collapsible } from "@opencode-ai/ui/collapsible" import { DiffChanges } from "@opencode-ai/ui/diff-changes" import { getFilename } from "@opencode-ai/util/path" import { Select } from "@opencode-ai/ui/select" -import { Session } from "@opencode-ai/sdk/client" +import { Session } from "@opencode-ai/sdk/v2/client" export default function Layout(props: ParentProps) { const navigate = useNavigate() diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index ff71b0453..0db8671c5 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -29,7 +29,7 @@ import { MCP } from "@/mcp" import { Todo } from "@/session/todo" import { z } from "zod" import { LoadAPIKeyError } from "ai" -import type { OpencodeClient } from "@opencode-ai/sdk" +import type { OpencodeClient } from "@opencode-ai/sdk/v2" export namespace ACP { const log = Log.create({ service: "acp-agent" }) @@ -68,7 +68,7 @@ export namespace ACP { { optionId: "always", kind: "allow_always", name: "Always allow" }, { optionId: "reject", kind: "reject_once", name: "Reject" }, ] - this.config.sdk.event.subscribe({ query: { directory } }).then(async (events) => { + this.config.sdk.event.subscribe({ directory }).then(async (events) => { for await (const event of events.stream) { switch (event.type) { case "permission.updated": @@ -93,32 +93,29 @@ export namespace ACP { permissionID: permission.id, sessionID: permission.sessionID, }) - await this.config.sdk.postSessionIdPermissionsPermissionId({ - path: { id: permission.sessionID, permissionID: permission.id }, - body: { - response: "reject", - }, - query: { directory }, + await this.config.sdk.permission.respond({ + sessionID: permission.sessionID, + permissionID: permission.id, + response: "reject", + directory, }) return }) if (!res) return if (res.outcome.outcome !== "selected") { - await this.config.sdk.postSessionIdPermissionsPermissionId({ - path: { id: permission.sessionID, permissionID: permission.id }, - body: { - response: "reject", - }, - query: { directory }, + await this.config.sdk.permission.respond({ + sessionID: permission.sessionID, + permissionID: permission.id, + response: "reject", + directory, }) return } - await this.config.sdk.postSessionIdPermissionsPermissionId({ - path: { id: permission.sessionID, permissionID: permission.id }, - body: { - response: res.outcome.optionId as "once" | "always" | "reject", - }, - query: { directory }, + await this.config.sdk.permission.respond({ + sessionID: permission.sessionID, + permissionID: permission.id, + response: res.outcome.optionId as "once" | "always" | "reject", + directory, }) } catch (err) { log.error("unexpected error when handling permission", { error: err }) @@ -133,14 +130,14 @@ export namespace ACP { const { part } = props const message = await this.config.sdk.session - .message({ - throwOnError: true, - path: { - id: part.sessionID, + .message( + { + sessionID: part.sessionID, messageID: part.messageID, + directory, }, - query: { directory }, - }) + { throwOnError: true }, + ) .then((x) => x.data) .catch((err) => { log.error("unexpected error when fetching message", { error: err }) @@ -420,9 +417,7 @@ export namespace ACP { const model = await defaultModel(this.config, directory) const sessionId = params.sessionId - const providers = await this.sdk.config - .providers({ throwOnError: true, query: { directory } }) - .then((x) => x.data.providers) + const providers = await this.sdk.config.providers({ directory }).then((x) => x.data!.providers) const entries = providers.sort((a, b) => { const nameA = a.name.toLowerCase() const nameB = b.name.toLowerCase() @@ -439,22 +434,22 @@ export namespace ACP { }) const agents = await this.config.sdk.app - .agents({ - throwOnError: true, - query: { + .agents( + { directory, }, - }) - .then((resp) => resp.data) + { throwOnError: true }, + ) + .then((resp) => resp.data!) const commands = await this.config.sdk.command - .list({ - throwOnError: true, - query: { + .list( + { directory, }, - }) - .then((resp) => resp.data) + { throwOnError: true }, + ) + .then((resp) => resp.data!) const availableCommands = commands.map((command) => ({ name: command.name, @@ -503,14 +498,14 @@ export namespace ACP { await Promise.all( Object.entries(mcpServers).map(async ([key, mcp]) => { await this.sdk.mcp - .add({ - throwOnError: true, - query: { directory }, - body: { + .add( + { + directory, name: key, config: mcp, }, - }) + { throwOnError: true }, + ) .catch((error) => { log.error("failed to add mcp server", { name: key, error }) }) @@ -559,7 +554,7 @@ export namespace ACP { async setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse | void> { this.sessionManager.get(params.sessionId) await this.config.sdk.app - .agents({ throwOnError: true }) + .agents({}, { throwOnError: true }) .then((x) => x.data) .then((agent) => { if (!agent) throw new Error(`Agent not found: ${params.modeId}`) @@ -651,50 +646,42 @@ export namespace ACP { if (!cmd) { await this.sdk.session.prompt({ - path: { id: sessionID }, - body: { - model: { - providerID: model.providerID, - modelID: model.modelID, - }, - parts, - agent, - }, - query: { - directory, + sessionID, + model: { + providerID: model.providerID, + modelID: model.modelID, }, + parts, + agent, + directory, }) return done } const command = await this.config.sdk.command - .list({ throwOnError: true, query: { directory } }) - .then((x) => x.data.find((c) => c.name === cmd.name)) + .list({ directory }, { throwOnError: true }) + .then((x) => x.data!.find((c) => c.name === cmd.name)) if (command) { await this.sdk.session.command({ - path: { id: sessionID }, - body: { - command: command.name, - arguments: cmd.args, - model: model.providerID + "/" + model.modelID, - agent, - }, - query: { - directory, - }, + sessionID, + command: command.name, + arguments: cmd.args, + model: model.providerID + "/" + model.modelID, + agent, + directory, }) return done } switch (cmd.name) { case "compact": - await this.config.sdk.session.summarize({ - path: { id: sessionID }, - throwOnError: true, - query: { + await this.config.sdk.session.summarize( + { + sessionID, directory, }, - }) + { throwOnError: true }, + ) break } @@ -703,13 +690,13 @@ export namespace ACP { async cancel(params: CancelNotification) { const session = this.sessionManager.get(params.sessionId) - await this.config.sdk.session.abort({ - path: { id: params.sessionId }, - throwOnError: true, - query: { + await this.config.sdk.session.abort( + { + sessionID: params.sessionId, directory: session.cwd, }, - }) + { throwOnError: true }, + ) } } @@ -766,10 +753,10 @@ export namespace ACP { if (configured) return configured const model = await sdk.config - .get({ throwOnError: true, query: { directory: cwd } }) + .get({ directory: cwd }, { throwOnError: true }) .then((resp) => { const cfg = resp.data - if (!cfg.model) return undefined + if (!cfg || !cfg.model) return undefined const parsed = Provider.parseModel(cfg.model) return { providerID: parsed.providerID, diff --git a/packages/opencode/src/acp/session.ts b/packages/opencode/src/acp/session.ts index 63948a8c1..6658e4203 100644 --- a/packages/opencode/src/acp/session.ts +++ b/packages/opencode/src/acp/session.ts @@ -1,7 +1,7 @@ import { RequestError, type McpServer } from "@agentclientprotocol/sdk" import type { ACPSessionState } from "./types" import { Log } from "@/util/log" -import type { OpencodeClient } from "@opencode-ai/sdk" +import type { OpencodeClient } from "@opencode-ai/sdk/v2" const log = Log.create({ service: "acp-session-manager" }) @@ -15,16 +15,14 @@ export class ACPSessionManager { async create(cwd: string, mcpServers: McpServer[], model?: ACPSessionState["model"]): Promise<ACPSessionState> { const session = await this.sdk.session - .create({ - body: { + .create( + { title: `ACP Session ${crypto.randomUUID()}`, - }, - query: { directory: cwd, }, - throwOnError: true, - }) - .then((x) => x.data) + { throwOnError: true }, + ) + .then((x) => x.data!) const sessionId = session.id const resolvedModel = model diff --git a/packages/opencode/src/acp/types.ts b/packages/opencode/src/acp/types.ts index 8507228ed..42b230912 100644 --- a/packages/opencode/src/acp/types.ts +++ b/packages/opencode/src/acp/types.ts @@ -1,5 +1,5 @@ import type { McpServer } from "@agentclientprotocol/sdk" -import type { OpencodeClient } from "@opencode-ai/sdk" +import type { OpencodeClient } from "@opencode-ai/sdk/v2" export interface ACPSessionState { id: string diff --git a/packages/opencode/src/cli/cmd/acp.ts b/packages/opencode/src/cli/cmd/acp.ts index 38e4b921a..c607e5f5b 100644 --- a/packages/opencode/src/cli/cmd/acp.ts +++ b/packages/opencode/src/cli/cmd/acp.ts @@ -4,7 +4,7 @@ import { cmd } from "./cmd" import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk" import { ACP } from "@/acp/agent" import { Server } from "@/server/server" -import { createOpencodeClient } from "@opencode-ai/sdk" +import { createOpencodeClient } from "@opencode-ai/sdk/v2" const log = Log.create({ service: "acp-command" }) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 847b19adb..c57711b4c 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -7,7 +7,7 @@ import { bootstrap } from "../bootstrap" import { Command } from "../../command" import { EOL } from "os" import { select } from "@clack/prompts" -import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk" +import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk/v2" import { Server } from "../../server/server" import { Provider } from "../../provider/provider" @@ -212,9 +212,10 @@ export const RunCommand = cmd({ initialValue: "once", }).catch(() => "reject") const response = (result.toString().includes("cancel") ? "reject" : result) as "once" | "always" | "reject" - await sdk.postSessionIdPermissionsPermissionId({ - path: { id: sessionID, permissionID: permission.id }, - body: { response }, + await sdk.permission.respond({ + sessionID, + permissionID: permission.id, + response, }) } } @@ -222,23 +223,19 @@ export const RunCommand = cmd({ if (args.command) { await sdk.session.command({ - path: { id: sessionID }, - body: { - agent: args.agent || "build", - model: args.model, - command: args.command, - arguments: message, - }, + sessionID, + agent: args.agent || "build", + model: args.model, + command: args.command, + arguments: message, }) } else { const modelParam = args.model ? Provider.parseModel(args.model) : undefined await sdk.session.prompt({ - path: { id: sessionID }, - body: { - agent: args.agent || "build", - model: modelParam, - parts: [...fileParts, { type: "text", text: message }], - }, + sessionID, + agent: args.agent || "build", + model: modelParam, + parts: [...fileParts, { type: "text", text: message }], }) } @@ -263,7 +260,7 @@ export const RunCommand = cmd({ : args.title : undefined - const result = await sdk.session.create({ body: title ? { title } : {} }) + const result = await sdk.session.create(title ? { title } : {}) return result.data?.id })() @@ -274,7 +271,7 @@ export const RunCommand = cmd({ const cfgResult = await sdk.config.get() if (cfgResult.data && (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share)) { - const shareResult = await sdk.session.share({ path: { id: sessionID } }).catch((error) => { + const shareResult = await sdk.session.share({ sessionID }).catch((error) => { if (error instanceof Error && error.message.includes("disabled")) { UI.println(UI.Style.TEXT_DANGER_BOLD + "! " + error.message) } @@ -315,7 +312,7 @@ export const RunCommand = cmd({ : args.title : undefined - const result = await sdk.session.create({ body: title ? { title } : {} }) + const result = await sdk.session.create(title ? { title } : {}) return result.data?.id })() @@ -327,7 +324,7 @@ export const RunCommand = cmd({ const cfgResult = await sdk.config.get() if (cfgResult.data && (cfgResult.data.share === "auto" || Flag.OPENCODE_AUTO_SHARE || args.share)) { - const shareResult = await sdk.session.share({ path: { id: sessionID } }).catch((error) => { + const shareResult = await sdk.session.share({ sessionID }).catch((error) => { if (error instanceof Error && error.message.includes("disabled")) { UI.println(UI.Style.TEXT_DANGER_BOLD + "! " + error.message) } diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx index 06b52863d..d2130488e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx @@ -11,7 +11,7 @@ import { } from "solid-js" import { useKeyboard } from "@opentui/solid" import { useKeybind } from "@tui/context/keybind" -import type { KeybindsConfig } from "@opencode-ai/sdk" +import type { KeybindsConfig } from "@opencode-ai/sdk/v2" type Context = ReturnType<typeof init> const ctx = createContext<Context>() diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx index b96fc2d09..0af7034db 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx @@ -7,7 +7,7 @@ import { useSDK } from "../context/sdk" import { DialogPrompt } from "../ui/dialog-prompt" import { useTheme } from "../context/theme" import { TextAttributes } from "@opentui/core" -import type { ProviderAuthAuthorization } from "@opencode-ai/sdk" +import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2" import { DialogModel } from "./dialog-model" const PROVIDER_PRIORITY: Record<string, number> = { @@ -64,12 +64,8 @@ export function createDialogProviderOptions() { const method = methods[index] if (method.type === "oauth") { const result = await sdk.client.provider.oauth.authorize({ - path: { - id: provider.id, - }, - body: { - method: index, - }, + providerID: provider.id, + method: index, }) if (result.data?.method === "code") { dialog.replace(() => ( @@ -111,12 +107,8 @@ function AutoMethod(props: AutoMethodProps) { onMount(async () => { const result = await sdk.client.provider.oauth.callback({ - path: { - id: props.providerID, - }, - body: { - method: props.index, - }, + providerID: props.providerID, + method: props.index, }) if (result.error) { dialog.clear() @@ -161,13 +153,9 @@ function CodeMethod(props: CodeMethodProps) { placeholder="Authorization code" onConfirm={async (value) => { const { error } = await sdk.client.provider.oauth.callback({ - path: { - id: props.providerID, - }, - body: { - method: props.index, - code: value, - }, + providerID: props.providerID, + method: props.index, + code: value, }) if (!error) { await sdk.client.instance.dispose() @@ -219,10 +207,8 @@ function ApiMethod(props: ApiMethodProps) { onConfirm={async (value) => { if (!value) return sdk.client.auth.set({ - path: { - id: props.providerID, - }, - body: { + providerID: props.providerID, + auth: { type: "api", key: value, }, diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 5e0095a8d..fa2ff7ba9 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -74,9 +74,7 @@ export function DialogSessionList() { onTrigger: async (option) => { if (toDelete() === option.value) { sdk.client.session.delete({ - path: { - id: option.value, - }, + sessionID: option.value, }) setToDelete(undefined) // dialog.clear() diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx index aaf033200..141340d55 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-rename.tsx @@ -20,12 +20,8 @@ export function DialogSessionRename(props: DialogSessionRenameProps) { value={session()?.title} onConfirm={(value) => { sdk.client.session.update({ - path: { - id: props.session, - }, - body: { - title: value, - }, + sessionID: props.session, + title: value, }) dialog.clear() }} diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx index 78eeded24..6d6c62450 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx @@ -16,9 +16,7 @@ export function DialogTag(props: { onSelect?: (value: string) => void }) { () => [store.filter], async () => { const result = await sdk.client.find.files({ - query: { - query: store.filter, - }, + query: store.filter, }) if (result.error) return [] const sliced = (result.data ?? []).slice(0, 5) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 7db1b85af..7ef465368 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -140,9 +140,7 @@ export function Autocomplete(props: { // Get files from SDK const result = await sdk.client.find.files({ - query: { - query: query ?? "", - }, + query: query ?? "", }) const options: AutocompleteOption[] = [] diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx index 4fd60dd36..e55479c02 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/history.tsx @@ -5,7 +5,7 @@ import { createStore, produce } from "solid-js/store" import { clone } from "remeda" import { createSimpleContext } from "../../context/helper" import { appendFile, writeFile } from "fs/promises" -import type { AgentPart, FilePart, TextPart } from "@opencode-ai/sdk" +import type { AgentPart, FilePart, TextPart } from "@opencode-ai/sdk/v2" export type PromptInfo = { input: string diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index b7a02b850..7d5bbb9f0 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -17,7 +17,7 @@ import { useRenderer } from "@opentui/solid" import { Editor } from "@tui/util/editor" import { useExit } from "../../context/exit" import { Clipboard } from "../../util/clipboard" -import type { FilePart } from "@opencode-ai/sdk" +import type { FilePart } from "@opencode-ai/sdk/v2" import { TuiEvent } from "../../event" import { iife } from "@/util/iife" import { Locale } from "@/util/locale" @@ -170,9 +170,7 @@ export function Prompt(props: PromptProps) { if (store.interrupt >= 2) { sdk.client.session.abort({ - path: { - id: props.sessionID, - }, + sessionID: props.sessionID, }) setStore("interrupt", 0) } @@ -447,17 +445,13 @@ export function Prompt(props: PromptProps) { if (store.mode === "shell") { sdk.client.session.shell({ - path: { - id: sessionID, - }, - body: { - agent: local.agent.current().name, - model: { - providerID: selectedModel.providerID, - modelID: selectedModel.modelID, - }, - command: inputText, + sessionID, + agent: local.agent.current().name, + model: { + providerID: selectedModel.providerID, + modelID: selectedModel.modelID, }, + command: inputText, }) setStore("mode", "normal") } else if ( @@ -470,39 +464,31 @@ export function Prompt(props: PromptProps) { ) { let [command, ...args] = inputText.split(" ") sdk.client.session.command({ - path: { - id: sessionID, - }, - body: { - command: command.slice(1), - arguments: args.join(" "), - agent: local.agent.current().name, - model: `${selectedModel.providerID}/${selectedModel.modelID}`, - messageID, - }, + sessionID, + command: command.slice(1), + arguments: args.join(" "), + agent: local.agent.current().name, + model: `${selectedModel.providerID}/${selectedModel.modelID}`, + messageID, }) } else { sdk.client.session.prompt({ - path: { - id: sessionID, - }, - body: { - ...selectedModel, - messageID, - agent: local.agent.current().name, - model: selectedModel, - parts: [ - { - id: Identifier.ascending("part"), - type: "text", - text: inputText, - }, - ...nonTextParts.map((x) => ({ - id: Identifier.ascending("part"), - ...x, - })), - ], - }, + sessionID, + ...selectedModel, + messageID, + agent: local.agent.current().name, + model: selectedModel, + parts: [ + { + id: Identifier.ascending("part"), + type: "text", + text: inputText, + }, + ...nonTextParts.map((x) => ({ + id: Identifier.ascending("part"), + ...x, + })), + ], }) } history.append(store.prompt) diff --git a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx index 5baab6d1a..50a29d2c5 100644 --- a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx @@ -2,7 +2,7 @@ import { createMemo } from "solid-js" import { useSync } from "@tui/context/sync" import { Keybind } from "@/util/keybind" import { pipe, mapValues } from "remeda" -import type { KeybindsConfig } from "@opencode-ai/sdk" +import type { KeybindsConfig } from "@opencode-ai/sdk/v2" import type { ParsedKey, Renderable } from "@opentui/core" import { createStore } from "solid-js/store" import { useKeyboard, useRenderer } from "@opentui/solid" diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx index 401a53ab4..b283f672f 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx @@ -1,4 +1,4 @@ -import { createOpencodeClient, type Event } from "@opencode-ai/sdk" +import { createOpencodeClient, type Event } from "@opencode-ai/sdk/v2" import { createSimpleContext } from "./helper" import { createGlobalEmitter } from "@solid-primitives/event-bus" import { batch, onCleanup, onMount } from "solid-js" @@ -20,9 +20,12 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ onMount(async () => { while (true) { if (abort.signal.aborted) break - const events = await sdk.event.subscribe({ - signal: abort.signal, - }) + const events = await sdk.event.subscribe( + {}, + { + signal: abort.signal, + }, + ) let queue: Event[] = [] let timer: Timer | undefined let last = 0 diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index b7ef8a221..28ea60a67 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -15,7 +15,7 @@ import type { ProviderListResponse, ProviderAuthMethod, VcsInfo, -} from "@opencode-ai/sdk" +} from "@opencode-ai/sdk/v2" import { createStore, produce, reconcile } from "solid-js/store" import { useSDK } from "@tui/context/sdk" import { Binary } from "@opencode-ai/util/binary" @@ -255,19 +255,19 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ async function bootstrap() { // blocking await Promise.all([ - sdk.client.config.providers({ throwOnError: true }).then((x) => { + sdk.client.config.providers({}, { throwOnError: true }).then((x) => { batch(() => { setStore("provider", x.data!.providers) setStore("provider_default", x.data!.default) }) }), - sdk.client.provider.list({ throwOnError: true }).then((x) => { + sdk.client.provider.list({}, { throwOnError: true }).then((x) => { batch(() => { setStore("provider_next", x.data!) }) }), - sdk.client.app.agents({ throwOnError: true }).then((x) => setStore("agent", x.data ?? [])), - sdk.client.config.get({ throwOnError: true }).then((x) => setStore("config", x.data!)), + sdk.client.app.agents({}, { throwOnError: true }).then((x) => setStore("agent", x.data ?? [])), + sdk.client.config.get({}, { throwOnError: true }).then((x) => setStore("config", x.data!)), ]) .then(() => { if (store.status !== "complete") setStore("status", "partial") @@ -333,10 +333,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ async sync(sessionID: string) { if (fullSyncedSessions.has(sessionID)) return const [session, messages, todo, diff] = await Promise.all([ - sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }), - sdk.client.session.messages({ path: { id: sessionID }, query: { limit: 100 } }), - sdk.client.session.todo({ path: { id: sessionID } }), - sdk.client.session.diff({ path: { id: sessionID } }), + sdk.client.session.get({ sessionID }, { throwOnError: true }), + sdk.client.session.messages({ sessionID, limit: 100 }), + sdk.client.session.todo({ sessionID }), + sdk.client.session.diff({ sessionID }), ]) setStore( produce((draft) => { diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx index 07e1a1eb4..b9e6632ac 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-message.tsx @@ -29,12 +29,8 @@ export function DialogMessage(props: { if (!msg) return sdk.client.session.revert({ - path: { - id: props.sessionID, - }, - body: { - messageID: msg.id, - }, + sessionID: props.sessionID, + messageID: msg.id, }) if (props.setPrompt) { @@ -81,12 +77,8 @@ export function DialogMessage(props: { description: "create a new session", onSelect: async (dialog) => { const result = await sdk.client.session.fork({ - path: { - id: props.sessionID, - }, - body: { - messageID: props.messageID, - }, + sessionID: props.sessionID, + messageID: props.messageID, }) route.navigate({ sessionID: result.data!.id, diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx index f5976cdf0..8c8576cc0 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/dialog-timeline.tsx @@ -1,7 +1,7 @@ import { createMemo, onMount } from "solid-js" import { useSync } from "@tui/context/sync" import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select" -import type { TextPart } from "@opencode-ai/sdk" +import type { TextPart } from "@opencode-ai/sdk/v2" import { Locale } from "@/util/locale" import { DialogMessage } from "./dialog-message" import { useDialog } from "../../ui/dialog" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx index d024bb5f5..bfdbfa51b 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/header.tsx @@ -4,7 +4,7 @@ import { useSync } from "@tui/context/sync" import { pipe, sumBy } from "remeda" import { useTheme } from "@tui/context/theme" import { SplitBorder, EmptyBorder } from "@tui/component/border" -import type { AssistantMessage, Session } from "@opencode-ai/sdk" +import type { AssistantMessage, Session } from "@opencode-ai/sdk/v2" import { useDirectory } from "../../context/directory" import { useKeybind } from "../../context/keybind" diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 74dfff1e8..5d3dc3601 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -25,7 +25,7 @@ import { type ScrollAcceleration, } from "@opentui/core" import { Prompt, type PromptRef } from "@tui/component/prompt" -import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk" +import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk/v2" import { useLocal } from "@tui/context/local" import { Locale } from "@/util/locale" import type { Tool } from "@/tool/tool" @@ -150,7 +150,8 @@ export function Session() { .then(() => { if (scroll) scroll.scrollBy(100_000) }) - .catch(() => { + .catch((e) => { + console.error(e) toast.show({ message: `Session not found: ${route.sessionID}`, variant: "error", @@ -202,14 +203,10 @@ export function Session() { return }) if (response) { - sdk.client.postSessionIdPermissionsPermissionId({ - path: { - permissionID: first.id, - id: route.sessionID, - }, - body: { - response: response, - }, + sdk.client.permission.respond({ + permissionID: first.id, + sessionID: route.sessionID, + response: response, }) } } @@ -254,9 +251,7 @@ export function Session() { onSelect: async (dialog: any) => { await sdk.client.session .share({ - path: { - id: route.sessionID, - }, + sessionID: route.sessionID, }) .then((res) => Clipboard.copy(res.data!.share!.url).catch(() => @@ -314,13 +309,9 @@ export function Session() { return } sdk.client.session.summarize({ - path: { - id: route.sessionID, - }, - body: { - modelID: selectedModel.modelID, - providerID: selectedModel.providerID, - }, + sessionID: route.sessionID, + modelID: selectedModel.modelID, + providerID: selectedModel.providerID, }) dialog.clear() }, @@ -333,9 +324,7 @@ export function Session() { category: "Session", onSelect: (dialog) => { sdk.client.session.unshare({ - path: { - id: route.sessionID, - }, + sessionID: route.sessionID, }) dialog.clear() }, @@ -347,18 +336,14 @@ export function Session() { category: "Session", onSelect: async (dialog) => { const status = sync.data.session_status[route.sessionID] - if (status?.type !== "idle") await sdk.client.session.abort({ path: { id: route.sessionID } }).catch(() => {}) + if (status?.type !== "idle") await sdk.client.session.abort({ sessionID: route.sessionID }).catch(() => {}) const revert = session().revert?.messageID const message = messages().findLast((x) => (!revert || x.id < revert) && x.role === "user") if (!message) return sdk.client.session .revert({ - path: { - id: route.sessionID, - }, - body: { - messageID: message.id, - }, + sessionID: route.sessionID, + messageID: message.id, }) .then(() => { toBottom() @@ -392,20 +377,14 @@ export function Session() { const message = messages().find((x) => x.role === "user" && x.id > messageID) if (!message) { sdk.client.session.unrevert({ - path: { - id: route.sessionID, - }, + sessionID: route.sessionID, }) prompt.set({ input: "", parts: [] }) return } sdk.client.session.revert({ - path: { - id: route.sessionID, - }, - body: { - messageID: message.id, - }, + sessionID: route.sessionID, + messageID: message.id, }) }, }, @@ -1066,7 +1045,7 @@ function UserMessage(props: { </box> </Show> <text fg={theme.textMuted}> - {ctx.usernameVisible() ? `${sync.data.config.username ?? "You"}` : "You"} + {ctx.usernameVisible() ? `${sync.data.config.username ?? "You "}` : "You "} <Show when={queued()} fallback={ diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index e734fdc48..0f9b0bbfd 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -4,7 +4,7 @@ import { createStore } from "solid-js/store" import { useTheme } from "../../context/theme" import { Locale } from "@/util/locale" import path from "path" -import type { AssistantMessage } from "@opencode-ai/sdk" +import type { AssistantMessage } from "@opencode-ai/sdk/v2" import { Global } from "@/global" import { Installation } from "@/installation" import { useKeybind } from "../../context/keybind" diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index 9571a6348..af5698220 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -61,10 +61,14 @@ export namespace Plugin { for (const hook of await state().then((x) => x.hooks)) { const fn = hook[name] if (!fn) continue - // @ts-expect-error if you feel adventurous, please fix the typing, make sure to bump the try-counter if you - // give up. - // try-counter: 2 - await fn(input, output) + try { + // @ts-expect-error if you feel adventurous, please fix the typing, make sure to bump the try-counter if you + // give up. + // try-counter: 2 + await fn(input, output) + } catch (e) { + log.error("failed to trigger hook", { name, error: e }) + } } return output } diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 1a71410f8..5c0d9afdb 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -209,7 +209,7 @@ export namespace Server { }, ) .get( - "/pty/:id", + "/pty/:ptyID", describeRoute({ description: "Get PTY session info", operationId: "pty.get", @@ -225,9 +225,9 @@ export namespace Server { ...errors(404), }, }), - validator("param", z.object({ id: z.string() })), + validator("param", z.object({ ptyID: z.string() })), async (c) => { - const info = Pty.get(c.req.valid("param").id) + const info = Pty.get(c.req.valid("param").ptyID) if (!info) { throw new Storage.NotFoundError({ message: "Session not found" }) } @@ -235,7 +235,7 @@ export namespace Server { }, ) .put( - "/pty/:id", + "/pty/:ptyID", describeRoute({ description: "Update PTY session", operationId: "pty.update", @@ -251,15 +251,15 @@ export namespace Server { ...errors(400), }, }), - validator("param", z.object({ id: z.string() })), + validator("param", z.object({ ptyID: z.string() })), validator("json", Pty.UpdateInput), async (c) => { - const info = await Pty.update(c.req.valid("param").id, c.req.valid("json")) + const info = await Pty.update(c.req.valid("param").ptyID, c.req.valid("json")) return c.json(info) }, ) .delete( - "/pty/:id", + "/pty/:ptyID", describeRoute({ description: "Remove a PTY session", operationId: "pty.remove", @@ -275,14 +275,14 @@ export namespace Server { ...errors(404), }, }), - validator("param", z.object({ id: z.string() })), + validator("param", z.object({ ptyID: z.string() })), async (c) => { - await Pty.remove(c.req.valid("param").id) + await Pty.remove(c.req.valid("param").ptyID) return c.json(true) }, ) .get( - "/pty/:id/connect", + "/pty/:ptyID/connect", describeRoute({ description: "Connect to a PTY session", operationId: "pty.connect", @@ -298,9 +298,9 @@ export namespace Server { ...errors(404), }, }), - validator("param", z.object({ id: z.string() })), + validator("param", z.object({ ptyID: z.string() })), upgradeWebSocket((c) => { - const id = c.req.param("id") + const id = c.req.param("ptyID") let handler: ReturnType<typeof Pty.connect> if (!Pty.get(id)) throw new Error("Session not found") return { @@ -557,7 +557,7 @@ export namespace Server { }, ) .get( - "/session/:id", + "/session/:sessionID", describeRoute({ description: "Get session", operationId: "session.get", @@ -576,17 +576,18 @@ export namespace Server { validator( "param", z.object({ - id: Session.get.schema, + sessionID: Session.get.schema, }), ), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID + log.info("SEARCH", { url: c.req.url }) const session = await Session.get(sessionID) return c.json(session) }, ) .get( - "/session/:id/children", + "/session/:sessionID/children", describeRoute({ description: "Get a session's children", operationId: "session.children", @@ -605,17 +606,17 @@ export namespace Server { validator( "param", z.object({ - id: Session.children.schema, + sessionID: Session.children.schema, }), ), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const session = await Session.children(sessionID) return c.json(session) }, ) .get( - "/session/:id/todo", + "/session/:sessionID/todo", describeRoute({ description: "Get the todo list for a session", operationId: "session.todo", @@ -634,11 +635,11 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const todos = await Todo.get(sessionID) return c.json(todos) }, @@ -668,7 +669,7 @@ export namespace Server { }, ) .delete( - "/session/:id", + "/session/:sessionID", describeRoute({ description: "Delete a session and all its data", operationId: "session.delete", @@ -687,11 +688,11 @@ export namespace Server { validator( "param", z.object({ - id: Session.remove.schema, + sessionID: Session.remove.schema, }), ), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID await Session.remove(sessionID) await Bus.publish(TuiEvent.CommandExecute, { command: "session.list", @@ -700,7 +701,7 @@ export namespace Server { }, ) .patch( - "/session/:id", + "/session/:sessionID", describeRoute({ description: "Update session properties", operationId: "session.update", @@ -719,7 +720,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), }), ), validator( @@ -729,7 +730,7 @@ export namespace Server { }), ), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const updates = c.req.valid("json") const updatedSession = await Session.update(sessionID, (session) => { @@ -742,7 +743,7 @@ export namespace Server { }, ) .post( - "/session/:id/init", + "/session/:sessionID/init", describeRoute({ description: "Analyze the app and create an AGENTS.md file", operationId: "session.init", @@ -761,19 +762,19 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator("json", Session.initialize.schema.omit({ sessionID: true })), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") await Session.initialize({ ...body, sessionID }) return c.json(true) }, ) .post( - "/session/:id/fork", + "/session/:sessionID/fork", describeRoute({ description: "Fork an existing session at a specific message", operationId: "session.fork", @@ -791,19 +792,19 @@ export namespace Server { validator( "param", z.object({ - id: Session.fork.schema.shape.sessionID, + sessionID: Session.fork.schema.shape.sessionID, }), ), validator("json", Session.fork.schema.omit({ sessionID: true })), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") const result = await Session.fork({ ...body, sessionID }) return c.json(result) }, ) .post( - "/session/:id/abort", + "/session/:sessionID/abort", describeRoute({ description: "Abort a session", operationId: "session.abort", @@ -822,16 +823,16 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), }), ), async (c) => { - SessionPrompt.cancel(c.req.valid("param").id) + SessionPrompt.cancel(c.req.valid("param").sessionID) return c.json(true) }, ) .post( - "/session/:id/share", + "/session/:sessionID/share", describeRoute({ description: "Share a session", operationId: "session.share", @@ -850,18 +851,18 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), }), ), async (c) => { - const id = c.req.valid("param").id - await Session.share(id) - const session = await Session.get(id) + const sessionID = c.req.valid("param").sessionID + await Session.share(sessionID) + const session = await Session.get(sessionID) return c.json(session) }, ) .get( - "/session/:id/diff", + "/session/:sessionID/diff", describeRoute({ description: "Get the diff that resulted from this user message", operationId: "session.diff", @@ -879,7 +880,7 @@ export namespace Server { validator( "param", z.object({ - id: SessionSummary.diff.schema.shape.sessionID, + sessionID: SessionSummary.diff.schema.shape.sessionID, }), ), validator( @@ -892,14 +893,14 @@ export namespace Server { const query = c.req.valid("query") const params = c.req.valid("param") const result = await SessionSummary.diff({ - sessionID: params.id, + sessionID: params.sessionID, messageID: query.messageID, }) return c.json(result) }, ) .delete( - "/session/:id/share", + "/session/:sessionID/share", describeRoute({ description: "Unshare the session", operationId: "session.unshare", @@ -918,18 +919,18 @@ export namespace Server { validator( "param", z.object({ - id: Session.unshare.schema, + sessionID: Session.unshare.schema, }), ), async (c) => { - const id = c.req.valid("param").id - await Session.unshare(id) - const session = await Session.get(id) + const sessionID = c.req.valid("param").sessionID + await Session.unshare(sessionID) + const session = await Session.get(sessionID) return c.json(session) }, ) .post( - "/session/:id/summarize", + "/session/:sessionID/summarize", describeRoute({ description: "Summarize the session", operationId: "session.summarize", @@ -948,7 +949,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator( @@ -959,9 +960,9 @@ export namespace Server { }), ), async (c) => { - const id = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") - const msgs = await Session.messages({ sessionID: id }) + const msgs = await Session.messages({ sessionID }) let currentAgent = "build" for (let i = msgs.length - 1; i >= 0; i--) { const info = msgs[i].info @@ -971,7 +972,7 @@ export namespace Server { } } await SessionCompaction.create({ - sessionID: id, + sessionID, agent: currentAgent, model: { providerID: body.providerID, @@ -979,12 +980,12 @@ export namespace Server { }, auto: false, }) - await SessionPrompt.loop(id) + await SessionPrompt.loop(sessionID) return c.json(true) }, ) .get( - "/session/:id/message", + "/session/:sessionID/message", describeRoute({ description: "List messages for a session", operationId: "session.messages", @@ -1003,7 +1004,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator( @@ -1015,14 +1016,14 @@ export namespace Server { async (c) => { const query = c.req.valid("query") const messages = await Session.messages({ - sessionID: c.req.valid("param").id, + sessionID: c.req.valid("param").sessionID, limit: query.limit, }) return c.json(messages) }, ) .get( - "/session/:id/diff", + "/session/:sessionID/diff", describeRoute({ description: "Get the diff for this session", operationId: "session.diff", @@ -1041,16 +1042,16 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), async (c) => { - const diff = await Session.diff(c.req.valid("param").id) + const diff = await Session.diff(c.req.valid("param").sessionID) return c.json(diff) }, ) .get( - "/session/:id/message/:messageID", + "/session/:sessionID/message/:messageID", describeRoute({ description: "Get a message from a session", operationId: "session.message", @@ -1074,21 +1075,21 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), messageID: z.string().meta({ description: "Message ID" }), }), ), async (c) => { const params = c.req.valid("param") const message = await MessageV2.get({ - sessionID: params.id, + sessionID: params.sessionID, messageID: params.messageID, }) return c.json(message) }, ) .post( - "/session/:id/message", + "/session/:sessionID/message", describeRoute({ description: "Create and send a new message to a session", operationId: "session.prompt", @@ -1112,7 +1113,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator("json", SessionPrompt.PromptInput.omit({ sessionID: true })), @@ -1120,7 +1121,7 @@ export namespace Server { c.status(200) c.header("Content-Type", "application/json") return stream(c, async (stream) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") const msg = await SessionPrompt.prompt({ ...body, sessionID }) stream.write(JSON.stringify(msg)) @@ -1128,7 +1129,7 @@ export namespace Server { }, ) .post( - "/session/:id/prompt_async", + "/session/:sessionID/prompt_async", describeRoute({ description: "Create and send a new message to a session, start if needed and return immediately", operationId: "session.prompt_async", @@ -1142,7 +1143,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator("json", SessionPrompt.PromptInput.omit({ sessionID: true })), @@ -1150,14 +1151,14 @@ export namespace Server { c.status(204) c.header("Content-Type", "application/json") return stream(c, async () => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") SessionPrompt.prompt({ ...body, sessionID }) }) }, ) .post( - "/session/:id/command", + "/session/:sessionID/command", describeRoute({ description: "Send a new command to a session", operationId: "session.command", @@ -1181,19 +1182,19 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator("json", SessionPrompt.CommandInput.omit({ sessionID: true })), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") const msg = await SessionPrompt.command({ ...body, sessionID }) return c.json(msg) }, ) .post( - "/session/:id/shell", + "/session/:sessionID/shell", describeRoute({ description: "Run a shell command", operationId: "session.shell", @@ -1212,19 +1213,19 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Session ID" }), + sessionID: z.string().meta({ description: "Session ID" }), }), ), validator("json", SessionPrompt.ShellInput.omit({ sessionID: true })), async (c) => { - const sessionID = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID const body = c.req.valid("json") const msg = await SessionPrompt.shell({ ...body, sessionID }) return c.json(msg) }, ) .post( - "/session/:id/revert", + "/session/:sessionID/revert", describeRoute({ description: "Revert a message", operationId: "session.revert", @@ -1243,22 +1244,22 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), }), ), validator("json", SessionRevert.RevertInput.omit({ sessionID: true })), async (c) => { - const id = c.req.valid("param").id + const sessionID = c.req.valid("param").sessionID log.info("revert", c.req.valid("json")) const session = await SessionRevert.revert({ - sessionID: id, + sessionID, ...c.req.valid("json"), }) return c.json(session) }, ) .post( - "/session/:id/unrevert", + "/session/:sessionID/unrevert", describeRoute({ description: "Restore all reverted messages", operationId: "session.unrevert", @@ -1277,19 +1278,20 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), }), ), async (c) => { - const id = c.req.valid("param").id - const session = await SessionRevert.unrevert({ sessionID: id }) + const sessionID = c.req.valid("param").sessionID + const session = await SessionRevert.unrevert({ sessionID }) return c.json(session) }, ) .post( - "/session/:id/permissions/:permissionID", + "/session/:sessionID/permissions/:permissionID", describeRoute({ description: "Respond to a permission request", + operationId: "permission.respond", responses: { 200: { description: "Permission processed successfully", @@ -1305,17 +1307,17 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + sessionID: z.string(), permissionID: z.string(), }), ), validator("json", z.object({ response: Permission.Response })), async (c) => { const params = c.req.valid("param") - const id = params.id + const sessionID = params.sessionID const permissionID = params.permissionID Permission.respond({ - sessionID: id, + sessionID, permissionID, response: c.req.valid("json").response, }) @@ -1429,7 +1431,7 @@ export namespace Server { }, ) .post( - "/provider/:id/oauth/authorize", + "/provider/:providerID/oauth/authorize", describeRoute({ description: "Authorize a provider using OAuth", operationId: "provider.oauth.authorize", @@ -1448,7 +1450,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Provider ID" }), + providerID: z.string().meta({ description: "Provider ID" }), }), ), validator( @@ -1458,17 +1460,17 @@ export namespace Server { }), ), async (c) => { - const id = c.req.valid("param").id + const providerID = c.req.valid("param").providerID const { method } = c.req.valid("json") const result = await ProviderAuth.authorize({ - providerID: id, + providerID, method, }) return c.json(result) }, ) .post( - "/provider/:id/oauth/callback", + "/provider/:providerID/oauth/callback", describeRoute({ description: "Handle OAuth callback for a provider", operationId: "provider.oauth.callback", @@ -1487,7 +1489,7 @@ export namespace Server { validator( "param", z.object({ - id: z.string().meta({ description: "Provider ID" }), + providerID: z.string().meta({ description: "Provider ID" }), }), ), validator( @@ -1498,10 +1500,10 @@ export namespace Server { }), ), async (c) => { - const id = c.req.valid("param").id + const providerID = c.req.valid("param").providerID const { method, code } = c.req.valid("json") await ProviderAuth.callback({ - providerID: id, + providerID, method, code, }) @@ -2215,7 +2217,7 @@ export namespace Server { ) .route("/tui/control", TuiRoute) .put( - "/auth/:id", + "/auth/:providerID", describeRoute({ description: "Set authentication credentials", operationId: "auth.set", @@ -2234,14 +2236,14 @@ export namespace Server { validator( "param", z.object({ - id: z.string(), + providerID: z.string(), }), ), validator("json", Auth.Info), async (c) => { - const id = c.req.valid("param").id + const providerID = c.req.valid("param").providerID const info = c.req.valid("json") - await Auth.set(id, info) + await Auth.set(providerID, info) return c.json(true) }, ) diff --git a/packages/opencode/src/share/share-next.ts b/packages/opencode/src/share/share-next.ts index 996400280..5196aeb98 100644 --- a/packages/opencode/src/share/share-next.ts +++ b/packages/opencode/src/share/share-next.ts @@ -6,7 +6,7 @@ import { Session } from "@/session" import { MessageV2 } from "@/session/message-v2" import { Storage } from "@/storage/storage" import { Log } from "@/util/log" -import type * as SDK from "@opencode-ai/sdk" +import type * as SDK from "@opencode-ai/sdk/v2" export namespace ShareNext { const log = Log.create({ service: "share-next" }) diff --git a/packages/sdk/js/openapi.json b/packages/sdk/js/openapi.json index 96675912d..b74f1a034 100644 --- a/packages/sdk/js/openapi.json +++ b/packages/sdk/js/openapi.json @@ -181,7 +181,7 @@ } } }, - "/pty/{id}": { + "/pty/{ptyID}": { "get": { "operationId": "pty.get", "parameters": [ @@ -194,7 +194,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -237,7 +237,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -286,7 +286,10 @@ "type": "number" } }, - "required": ["rows", "cols"] + "required": [ + "rows", + "cols" + ] } } } @@ -306,7 +309,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -338,7 +341,7 @@ } } }, - "/pty/{id}/connect": { + "/pty/{ptyID}/connect": { "get": { "operationId": "pty.connect", "parameters": [ @@ -351,7 +354,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -751,7 +754,7 @@ } } }, - "/session/{id}": { + "/session/{sessionID}": { "get": { "operationId": "session.get", "parameters": [ @@ -764,7 +767,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -818,7 +821,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -872,7 +875,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -928,7 +931,7 @@ } } }, - "/session/{id}/children": { + "/session/{sessionID}/children": { "get": { "operationId": "session.children", "parameters": [ @@ -941,7 +944,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -987,7 +990,7 @@ } } }, - "/session/{id}/todo": { + "/session/{sessionID}/todo": { "get": { "operationId": "session.todo", "parameters": [ @@ -1000,7 +1003,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1046,7 +1049,7 @@ } } }, - "/session/{id}/init": { + "/session/{sessionID}/init": { "post": { "operationId": "session.init", "parameters": [ @@ -1059,7 +1062,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1117,14 +1120,18 @@ "pattern": "^msg.*" } }, - "required": ["modelID", "providerID", "messageID"] + "required": [ + "modelID", + "providerID", + "messageID" + ] } } } } } }, - "/session/{id}/fork": { + "/session/{sessionID}/fork": { "post": { "operationId": "session.fork", "parameters": [ @@ -1137,7 +1144,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -1175,7 +1182,7 @@ } } }, - "/session/{id}/abort": { + "/session/{sessionID}/abort": { "post": { "operationId": "session.abort", "parameters": [ @@ -1188,7 +1195,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1230,7 +1237,7 @@ } } }, - "/session/{id}/share": { + "/session/{sessionID}/share": { "post": { "operationId": "session.share", "parameters": [ @@ -1243,7 +1250,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1296,7 +1303,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -1339,7 +1346,7 @@ } } }, - "/session/{id}/diff": { + "/session/{sessionID}/diff": { "get": { "operationId": "session.diff", "parameters": [ @@ -1352,7 +1359,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1406,7 +1413,7 @@ } } }, - "/session/{id}/summarize": { + "/session/{sessionID}/summarize": { "post": { "operationId": "session.summarize", "parameters": [ @@ -1419,7 +1426,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1473,14 +1480,17 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] } } } } } }, - "/session/{id}/message": { + "/session/{sessionID}/message": { "get": { "operationId": "session.messages", "parameters": [ @@ -1493,7 +1503,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1529,7 +1539,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1569,7 +1582,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1596,7 +1609,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1642,7 +1658,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "agent": { "type": "string" @@ -1682,14 +1701,16 @@ } } }, - "required": ["parts"] + "required": [ + "parts" + ] } } } } } }, - "/session/{id}/message/{messageID}": { + "/session/{sessionID}/message/{messageID}": { "get": { "operationId": "session.message", "parameters": [ @@ -1702,7 +1723,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1738,7 +1759,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1766,7 +1790,7 @@ } } }, - "/session/{id}/prompt_async": { + "/session/{sessionID}/prompt_async": { "post": { "operationId": "session.prompt_async", "parameters": [ @@ -1779,7 +1803,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1833,7 +1857,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "agent": { "type": "string" @@ -1873,14 +1900,16 @@ } } }, - "required": ["parts"] + "required": [ + "parts" + ] } } } } } }, - "/session/{id}/command": { + "/session/{sessionID}/command": { "post": { "operationId": "session.command", "parameters": [ @@ -1893,7 +1922,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1920,7 +1949,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1969,14 +2001,17 @@ "type": "string" } }, - "required": ["arguments", "command"] + "required": [ + "arguments", + "command" + ] } } } } } }, - "/session/{id}/shell": { + "/session/{sessionID}/shell": { "post": { "operationId": "session.shell", "parameters": [ @@ -1989,7 +2024,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2049,20 +2084,26 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "command": { "type": "string" } }, - "required": ["agent", "command"] + "required": [ + "agent", + "command" + ] } } } } } }, - "/session/{id}/revert": { + "/session/{sessionID}/revert": { "post": { "operationId": "session.revert", "parameters": [ @@ -2075,7 +2116,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2130,14 +2171,16 @@ "pattern": "^prt.*" } }, - "required": ["messageID"] + "required": [ + "messageID" + ] } } } } } }, - "/session/{id}/unrevert": { + "/session/{sessionID}/unrevert": { "post": { "operationId": "session.unrevert", "parameters": [ @@ -2150,7 +2193,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2192,9 +2235,9 @@ } } }, - "/session/{id}/permissions/{permissionID}": { + "/session/{sessionID}/permissions/{permissionID}": { "post": { - "operationId": "postSession:idPermissions:permissionID", + "operationId": "permission.respond", "parameters": [ { "in": "query", @@ -2205,7 +2248,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2261,10 +2304,16 @@ "properties": { "response": { "type": "string", - "enum": ["once", "always", "reject"] + "enum": [ + "once", + "always", + "reject" + ] } }, - "required": ["response"] + "required": [ + "response" + ] } } } @@ -2338,7 +2387,10 @@ } } }, - "required": ["providers", "default"] + "required": [ + "providers", + "default" + ] } } } @@ -2450,10 +2502,16 @@ "type": "number" } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "limit": { "type": "object", @@ -2465,7 +2523,10 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "modalities": { "type": "object", @@ -2474,25 +2535,44 @@ "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, "output": { "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "experimental": { "type": "boolean" }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated"] + "enum": [ + "alpha", + "beta", + "deprecated" + ] }, "options": { "type": "object", @@ -2517,7 +2597,9 @@ "type": "string" } }, - "required": ["npm"] + "required": [ + "npm" + ] } }, "required": [ @@ -2534,7 +2616,12 @@ } } }, - "required": ["name", "env", "id", "models"] + "required": [ + "name", + "env", + "id", + "models" + ] } }, "default": { @@ -2553,7 +2640,11 @@ } } }, - "required": ["all", "default", "connected"] + "required": [ + "all", + "default", + "connected" + ] } } } @@ -2597,7 +2688,7 @@ } } }, - "/provider/{id}/oauth/authorize": { + "/provider/{providerID}/oauth/authorize": { "post": { "operationId": "provider.oauth.authorize", "parameters": [ @@ -2610,7 +2701,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -2652,14 +2743,16 @@ "type": "number" } }, - "required": ["method"] + "required": [ + "method" + ] } } } } } }, - "/provider/{id}/oauth/callback": { + "/provider/{providerID}/oauth/callback": { "post": { "operationId": "provider.oauth.callback", "parameters": [ @@ -2672,7 +2765,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -2718,7 +2811,9 @@ "type": "string" } }, - "required": ["method"] + "required": [ + "method" + ] } } } @@ -2763,7 +2858,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "lines": { "type": "object", @@ -2772,7 +2869,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "line_number": { "type": "number" @@ -2792,7 +2891,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "start": { "type": "number" @@ -2801,11 +2902,21 @@ "type": "number" } }, - "required": ["match", "start", "end"] + "required": [ + "match", + "start", + "end" + ] } } }, - "required": ["path", "lines", "line_number", "absolute_offset", "submatches"] + "required": [ + "path", + "lines", + "line_number", + "absolute_offset", + "submatches" + ] } } } @@ -2838,7 +2949,10 @@ "name": "dirs", "schema": { "type": "string", - "enum": ["true", "false"] + "enum": [ + "true", + "false" + ] } } ], @@ -3049,7 +3163,12 @@ "level": { "description": "Log level", "type": "string", - "enum": ["debug", "info", "error", "warn"] + "enum": [ + "debug", + "info", + "error", + "warn" + ] }, "message": { "description": "Log message", @@ -3064,7 +3183,11 @@ "additionalProperties": {} } }, - "required": ["service", "level", "message"] + "required": [ + "service", + "level", + "message" + ] } } } @@ -3193,7 +3316,10 @@ ] } }, - "required": ["name", "config"] + "required": [ + "name", + "config" + ] } } } @@ -3234,7 +3360,9 @@ "type": "string" } }, - "required": ["authorizationUrl"] + "required": [ + "authorizationUrl" + ] } } } @@ -3294,7 +3422,9 @@ "const": true } }, - "required": ["success"] + "required": [ + "success" + ] } } } @@ -3376,7 +3506,9 @@ "type": "string" } }, - "required": ["code"] + "required": [ + "code" + ] } } } @@ -3543,7 +3675,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] } } } @@ -3757,7 +3891,9 @@ "type": "string" } }, - "required": ["command"] + "required": [ + "command" + ] } } } @@ -3803,7 +3939,12 @@ }, "variant": { "type": "string", - "enum": ["info", "success", "warning", "error"] + "enum": [ + "info", + "success", + "warning", + "error" + ] }, "duration": { "description": "Duration in milliseconds", @@ -3811,7 +3952,10 @@ "type": "number" } }, - "required": ["message", "variant"] + "required": [ + "message", + "variant" + ] } } } @@ -3900,7 +4044,10 @@ }, "body": {} }, - "required": ["path", "body"] + "required": [ + "path", + "body" + ] } } } @@ -3942,7 +4089,7 @@ } } }, - "/auth/{id}": { + "/auth/{providerID}": { "put": { "operationId": "auth.set", "parameters": [ @@ -3955,7 +4102,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -4040,10 +4187,15 @@ "type": "string" } }, - "required": ["directory"] + "required": [ + "directory" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.installation.updated": { "type": "object", @@ -4059,10 +4211,15 @@ "type": "string" } }, - "required": ["version"] + "required": [ + "version" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.installation.update-available": { "type": "object", @@ -4078,10 +4235,15 @@ "type": "string" } }, - "required": ["version"] + "required": [ + "version" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.lsp.client.diagnostics": { "type": "object", @@ -4100,10 +4262,16 @@ "type": "string" } }, - "required": ["serverID", "path"] + "required": [ + "serverID", + "path" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.lsp.updated": { "type": "object", @@ -4117,7 +4285,10 @@ "properties": {} } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "FileDiff": { "type": "object", @@ -4138,7 +4309,13 @@ "type": "number" } }, - "required": ["file", "before", "after", "additions", "deletions"] + "required": [ + "file", + "before", + "after", + "additions", + "deletions" + ] }, "UserMessage": { "type": "object", @@ -4160,7 +4337,9 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] }, "summary": { "type": "object", @@ -4178,7 +4357,9 @@ } } }, - "required": ["diffs"] + "required": [ + "diffs" + ] }, "agent": { "type": "string" @@ -4193,7 +4374,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "system": { "type": "string" @@ -4208,7 +4392,14 @@ } } }, - "required": ["id", "sessionID", "role", "time", "agent", "model"] + "required": [ + "id", + "sessionID", + "role", + "time", + "agent", + "model" + ] }, "ProviderAuthError": { "type": "object", @@ -4227,10 +4418,16 @@ "type": "string" } }, - "required": ["providerID", "message"] + "required": [ + "providerID", + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "UnknownError": { "type": "object", @@ -4246,10 +4443,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "MessageOutputLengthError": { "type": "object", @@ -4263,7 +4465,10 @@ "properties": {} } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "MessageAbortedError": { "type": "object", @@ -4279,10 +4484,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "APIError": { "type": "object", @@ -4316,10 +4526,16 @@ "type": "string" } }, - "required": ["message", "isRetryable"] + "required": [ + "message", + "isRetryable" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "AssistantMessage": { "type": "object", @@ -4344,7 +4560,9 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] }, "error": { "anyOf": [ @@ -4387,7 +4605,10 @@ "type": "string" } }, - "required": ["cwd", "root"] + "required": [ + "cwd", + "root" + ] }, "summary": { "type": "boolean" @@ -4417,10 +4638,18 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "reasoning", "cache"] + "required": [ + "input", + "output", + "reasoning", + "cache" + ] }, "finish": { "type": "string" @@ -4464,10 +4693,15 @@ "$ref": "#/components/schemas/Message" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.message.removed": { "type": "object", @@ -4486,10 +4720,16 @@ "type": "string" } }, - "required": ["sessionID", "messageID"] + "required": [ + "sessionID", + "messageID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "TextPart": { "type": "object", @@ -4526,7 +4766,9 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] }, "metadata": { "type": "object", @@ -4536,7 +4778,13 @@ "additionalProperties": {} } }, - "required": ["id", "sessionID", "messageID", "type", "text"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "text" + ] }, "ReasoningPart": { "type": "object", @@ -4574,10 +4822,19 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "text", "time"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "text", + "time" + ] }, "FilePartSourceText": { "type": "object", @@ -4596,7 +4853,11 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] }, "FileSource": { "type": "object", @@ -4612,7 +4873,11 @@ "type": "string" } }, - "required": ["text", "type", "path"] + "required": [ + "text", + "type", + "path" + ] }, "Range": { "type": "object", @@ -4627,7 +4892,10 @@ "type": "number" } }, - "required": ["line", "character"] + "required": [ + "line", + "character" + ] }, "end": { "type": "object", @@ -4639,10 +4907,16 @@ "type": "number" } }, - "required": ["line", "character"] + "required": [ + "line", + "character" + ] } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] }, "SymbolSource": { "type": "object", @@ -4669,7 +4943,14 @@ "maximum": 9007199254740991 } }, - "required": ["text", "type", "path", "range", "name", "kind"] + "required": [ + "text", + "type", + "path", + "range", + "name", + "kind" + ] }, "FilePartSource": { "anyOf": [ @@ -4710,7 +4991,14 @@ "$ref": "#/components/schemas/FilePartSource" } }, - "required": ["id", "sessionID", "messageID", "type", "mime", "url"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "mime", + "url" + ] }, "ToolStatePending": { "type": "object", @@ -4730,7 +5018,11 @@ "type": "string" } }, - "required": ["status", "input", "raw"] + "required": [ + "status", + "input", + "raw" + ] }, "ToolStateRunning": { "type": "object", @@ -4763,10 +5055,16 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] } }, - "required": ["status", "input", "time"] + "required": [ + "status", + "input", + "time" + ] }, "ToolStateCompleted": { "type": "object", @@ -4808,7 +5106,10 @@ "type": "number" } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] }, "attachments": { "type": "array", @@ -4817,7 +5118,14 @@ } } }, - "required": ["status", "input", "output", "title", "metadata", "time"] + "required": [ + "status", + "input", + "output", + "title", + "metadata", + "time" + ] }, "ToolStateError": { "type": "object", @@ -4853,10 +5161,18 @@ "type": "number" } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] } }, - "required": ["status", "input", "error", "time"] + "required": [ + "status", + "input", + "error", + "time" + ] }, "ToolState": { "anyOf": [ @@ -4907,7 +5223,15 @@ "additionalProperties": {} } }, - "required": ["id", "sessionID", "messageID", "type", "callID", "tool", "state"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "callID", + "tool", + "state" + ] }, "StepStartPart": { "type": "object", @@ -4929,7 +5253,12 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type"] + "required": [ + "id", + "sessionID", + "messageID", + "type" + ] }, "StepFinishPart": { "type": "object", @@ -4978,13 +5307,29 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "reasoning", "cache"] + "required": [ + "input", + "output", + "reasoning", + "cache" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "reason", "cost", "tokens"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "reason", + "cost", + "tokens" + ] }, "SnapshotPart": { "type": "object", @@ -5006,7 +5351,13 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type", "snapshot"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "snapshot" + ] }, "PatchPart": { "type": "object", @@ -5034,7 +5385,14 @@ } } }, - "required": ["id", "sessionID", "messageID", "type", "hash", "files"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "hash", + "files" + ] }, "AgentPart": { "type": "object", @@ -5072,10 +5430,20 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "name"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "name" + ] }, "RetryPart": { "type": "object", @@ -5106,10 +5474,20 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "attempt", "error", "time"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "attempt", + "error", + "time" + ] }, "CompactionPart": { "type": "object", @@ -5131,7 +5509,13 @@ "type": "boolean" } }, - "required": ["id", "sessionID", "messageID", "type", "auto"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "auto" + ] }, "Part": { "anyOf": [ @@ -5164,7 +5548,15 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type", "prompt", "description", "agent"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "prompt", + "description", + "agent" + ] }, { "$ref": "#/components/schemas/ReasoningPart" @@ -5215,10 +5607,15 @@ "type": "string" } }, - "required": ["part"] + "required": [ + "part" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.message.part.removed": { "type": "object", @@ -5240,10 +5637,17 @@ "type": "string" } }, - "required": ["sessionID", "messageID", "partID"] + "required": [ + "sessionID", + "messageID", + "partID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Permission": { "type": "object", @@ -5293,10 +5697,20 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "type", "sessionID", "messageID", "title", "metadata", "time"] + "required": [ + "id", + "type", + "sessionID", + "messageID", + "title", + "metadata", + "time" + ] }, "Event.permission.updated": { "type": "object", @@ -5309,7 +5723,10 @@ "$ref": "#/components/schemas/Permission" } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.permission.replied": { "type": "object", @@ -5331,10 +5748,17 @@ "type": "string" } }, - "required": ["sessionID", "permissionID", "response"] + "required": [ + "sessionID", + "permissionID", + "response" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "SessionStatus": { "anyOf": [ @@ -5346,7 +5770,9 @@ "const": "idle" } }, - "required": ["type"] + "required": [ + "type" + ] }, { "type": "object", @@ -5365,7 +5791,12 @@ "type": "number" } }, - "required": ["type", "attempt", "message", "next"] + "required": [ + "type", + "attempt", + "message", + "next" + ] }, { "type": "object", @@ -5375,7 +5806,9 @@ "const": "busy" } }, - "required": ["type"] + "required": [ + "type" + ] } ] }, @@ -5396,10 +5829,16 @@ "$ref": "#/components/schemas/SessionStatus" } }, - "required": ["sessionID", "status"] + "required": [ + "sessionID", + "status" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.idle": { "type": "object", @@ -5415,10 +5854,15 @@ "type": "string" } }, - "required": ["sessionID"] + "required": [ + "sessionID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.compacted": { "type": "object", @@ -5434,10 +5878,15 @@ "type": "string" } }, - "required": ["sessionID"] + "required": [ + "sessionID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.file.edited": { "type": "object", @@ -5453,10 +5902,15 @@ "type": "string" } }, - "required": ["file"] + "required": [ + "file" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Todo": { "type": "object", @@ -5478,7 +5932,12 @@ "type": "string" } }, - "required": ["content", "status", "priority", "id"] + "required": [ + "content", + "status", + "priority", + "id" + ] }, "Event.todo.updated": { "type": "object", @@ -5500,10 +5959,16 @@ } } }, - "required": ["sessionID", "todos"] + "required": [ + "sessionID", + "todos" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.command.executed": { "type": "object", @@ -5530,10 +5995,18 @@ "pattern": "^msg.*" } }, - "required": ["name", "sessionID", "arguments", "messageID"] + "required": [ + "name", + "sessionID", + "arguments", + "messageID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Session": { "type": "object", @@ -5571,7 +6044,11 @@ } } }, - "required": ["additions", "deletions", "files"] + "required": [ + "additions", + "deletions", + "files" + ] }, "share": { "type": "object", @@ -5580,7 +6057,9 @@ "type": "string" } }, - "required": ["url"] + "required": [ + "url" + ] }, "title": { "type": "string" @@ -5601,7 +6080,10 @@ "type": "number" } }, - "required": ["created", "updated"] + "required": [ + "created", + "updated" + ] }, "revert": { "type": "object", @@ -5619,10 +6101,19 @@ "type": "string" } }, - "required": ["messageID"] + "required": [ + "messageID" + ] } }, - "required": ["id", "projectID", "directory", "title", "version", "time"] + "required": [ + "id", + "projectID", + "directory", + "title", + "version", + "time" + ] }, "Event.session.created": { "type": "object", @@ -5638,10 +6129,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.updated": { "type": "object", @@ -5657,10 +6153,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.deleted": { "type": "object", @@ -5676,10 +6177,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.diff": { "type": "object", @@ -5701,10 +6207,16 @@ } } }, - "required": ["sessionID", "diff"] + "required": [ + "sessionID", + "diff" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.error": { "type": "object", @@ -5741,7 +6253,10 @@ } } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.file.watcher.updated": { "type": "object", @@ -5773,10 +6288,16 @@ ] } }, - "required": ["file", "event"] + "required": [ + "file", + "event" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.vcs.branch.updated": { "type": "object", @@ -5794,7 +6315,10 @@ } } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.prompt.append": { "type": "object", @@ -5810,10 +6334,15 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.command.execute": { "type": "object", @@ -5852,10 +6381,15 @@ ] } }, - "required": ["command"] + "required": [ + "command" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.toast.show": { "type": "object", @@ -5875,7 +6409,12 @@ }, "variant": { "type": "string", - "enum": ["info", "success", "warning", "error"] + "enum": [ + "info", + "success", + "warning", + "error" + ] }, "duration": { "description": "Duration in milliseconds", @@ -5883,10 +6422,16 @@ "type": "number" } }, - "required": ["message", "variant"] + "required": [ + "message", + "variant" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Pty": { "type": "object", @@ -5912,13 +6457,24 @@ }, "status": { "type": "string", - "enum": ["running", "exited"] + "enum": [ + "running", + "exited" + ] }, "pid": { "type": "number" } }, - "required": ["id", "title", "command", "args", "cwd", "status", "pid"] + "required": [ + "id", + "title", + "command", + "args", + "cwd", + "status", + "pid" + ] }, "Event.pty.created": { "type": "object", @@ -5934,10 +6490,15 @@ "$ref": "#/components/schemas/Pty" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.updated": { "type": "object", @@ -5953,10 +6514,15 @@ "$ref": "#/components/schemas/Pty" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.exited": { "type": "object", @@ -5976,10 +6542,16 @@ "type": "number" } }, - "required": ["id", "exitCode"] + "required": [ + "id", + "exitCode" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.deleted": { "type": "object", @@ -5996,10 +6568,15 @@ "pattern": "^pty.*" } }, - "required": ["id"] + "required": [ + "id" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.server.connected": { "type": "object", @@ -6013,7 +6590,10 @@ "properties": {} } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event": { "anyOf": [ @@ -6125,7 +6705,10 @@ "$ref": "#/components/schemas/Event" } }, - "required": ["directory", "payload"] + "required": [ + "directory", + "payload" + ] }, "Project": { "type": "object", @@ -6153,10 +6736,16 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "worktree", "time"] + "required": [ + "id", + "worktree", + "time" + ] }, "BadRequestError": { "type": "object", @@ -6177,7 +6766,11 @@ "const": false } }, - "required": ["data", "errors", "success"] + "required": [ + "data", + "errors", + "success" + ] }, "NotFoundError": { "type": "object", @@ -6193,10 +6786,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "KeybindsConfig": { "description": "Custom keybind configurations", @@ -6463,7 +7061,11 @@ }, "mode": { "type": "string", - "enum": ["subagent", "primary", "all"] + "enum": [ + "subagent", + "primary", + "all" + ] }, "color": { "description": "Hex color code for the agent (e.g., #FF5733)", @@ -6481,13 +7083,21 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "anyOf": [ { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, { "type": "object", @@ -6496,22 +7106,38 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } ] }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } } @@ -6599,10 +7225,16 @@ "type": "number" } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "limit": { "type": "object", @@ -6614,7 +7246,10 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "modalities": { "type": "object", @@ -6623,25 +7258,44 @@ "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, "output": { "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "experimental": { "type": "boolean" }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated"] + "enum": [ + "alpha", + "beta", + "deprecated" + ] }, "options": { "type": "object", @@ -6666,7 +7320,9 @@ "type": "string" } }, - "required": ["npm"] + "required": [ + "npm" + ] } } } @@ -6758,7 +7414,10 @@ "maximum": 9007199254740991 } }, - "required": ["type", "command"], + "required": [ + "type", + "command" + ], "additionalProperties": false }, "McpOAuthConfig": { @@ -6824,13 +7483,19 @@ "maximum": 9007199254740991 } }, - "required": ["type", "url"], + "required": [ + "type", + "url" + ], "additionalProperties": false }, "LayoutConfig": { "description": "@deprecated Always uses stretch layout.", "type": "string", - "enum": ["auto", "stretch"] + "enum": [ + "auto", + "stretch" + ] }, "Config": { "type": "object", @@ -6864,12 +7529,17 @@ "type": "boolean" } }, - "required": ["enabled"] + "required": [ + "enabled" + ] }, "diff_style": { "description": "Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column", "type": "string", - "enum": ["auto", "stacked"] + "enum": [ + "auto", + "stacked" + ] } } }, @@ -6898,7 +7568,9 @@ "type": "boolean" } }, - "required": ["template"] + "required": [ + "template" + ] } }, "watcher": { @@ -6924,7 +7596,11 @@ "share": { "description": "Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing", "type": "string", - "enum": ["manual", "auto", "disabled"] + "enum": [ + "manual", + "auto", + "disabled" + ] }, "autoshare": { "description": "@deprecated Use 'share' field instead. Share newly created sessions automatically", @@ -7095,7 +7771,9 @@ "const": true } }, - "required": ["disabled"] + "required": [ + "disabled" + ] }, { "type": "object", @@ -7132,7 +7810,9 @@ "additionalProperties": {} } }, - "required": ["command"] + "required": [ + "command" + ] } ] } @@ -7154,13 +7834,21 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "anyOf": [ { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, { "type": "object", @@ -7169,22 +7857,38 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } ] }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } }, @@ -7238,7 +7942,9 @@ } } }, - "required": ["command"] + "required": [ + "command" + ] } } }, @@ -7263,7 +7969,9 @@ } } }, - "required": ["command"] + "required": [ + "command" + ] } } } @@ -7312,7 +8020,11 @@ }, "parameters": {} }, - "required": ["id", "description", "parameters"] + "required": [ + "id", + "description", + "parameters" + ] }, "ToolList": { "type": "array", @@ -7336,7 +8048,12 @@ "type": "string" } }, - "required": ["state", "config", "worktree", "directory"] + "required": [ + "state", + "config", + "worktree", + "directory" + ] }, "VcsInfo": { "type": "object", @@ -7345,7 +8062,9 @@ "type": "string" } }, - "required": ["branch"] + "required": [ + "branch" + ] }, "TextPartInput": { "type": "object", @@ -7376,7 +8095,9 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] }, "metadata": { "type": "object", @@ -7386,7 +8107,10 @@ "additionalProperties": {} } }, - "required": ["type", "text"] + "required": [ + "type", + "text" + ] }, "FilePartInput": { "type": "object", @@ -7411,7 +8135,11 @@ "$ref": "#/components/schemas/FilePartSource" } }, - "required": ["type", "mime", "url"] + "required": [ + "type", + "mime", + "url" + ] }, "AgentPartInput": { "type": "object", @@ -7443,10 +8171,17 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] } }, - "required": ["type", "name"] + "required": [ + "type", + "name" + ] }, "SubtaskPartInput": { "type": "object", @@ -7468,7 +8203,12 @@ "type": "string" } }, - "required": ["type", "prompt", "description", "agent"] + "required": [ + "type", + "prompt", + "description", + "agent" + ] }, "Command": { "type": "object", @@ -7492,7 +8232,10 @@ "type": "boolean" } }, - "required": ["name", "template"] + "required": [ + "name", + "template" + ] }, "Model": { "type": "object", @@ -7516,7 +8259,11 @@ "type": "string" } }, - "required": ["id", "url", "npm"] + "required": [ + "id", + "url", + "npm" + ] }, "name": { "type": "string" @@ -7555,7 +8302,13 @@ "type": "boolean" } }, - "required": ["text", "audio", "image", "video", "pdf"] + "required": [ + "text", + "audio", + "image", + "video", + "pdf" + ] }, "output": { "type": "object", @@ -7576,10 +8329,23 @@ "type": "boolean" } }, - "required": ["text", "audio", "image", "video", "pdf"] + "required": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, - "required": ["temperature", "reasoning", "attachment", "toolcall", "input", "output"] + "required": [ + "temperature", + "reasoning", + "attachment", + "toolcall", + "input", + "output" + ] }, "cost": { "type": "object", @@ -7600,7 +8366,10 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] }, "experimentalOver200K": { "type": "object", @@ -7621,13 +8390,24 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "cache"] + "required": [ + "input", + "output", + "cache" + ] } }, - "required": ["input", "output", "cache"] + "required": [ + "input", + "output", + "cache" + ] }, "limit": { "type": "object", @@ -7639,11 +8419,19 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated", "active"] + "enum": [ + "alpha", + "beta", + "deprecated", + "active" + ] }, "options": { "type": "object", @@ -7662,7 +8450,18 @@ } } }, - "required": ["id", "providerID", "api", "name", "capabilities", "cost", "limit", "status", "options", "headers"] + "required": [ + "id", + "providerID", + "api", + "name", + "capabilities", + "cost", + "limit", + "status", + "options", + "headers" + ] }, "Provider": { "type": "object", @@ -7675,7 +8474,12 @@ }, "source": { "type": "string", - "enum": ["env", "config", "custom", "api"] + "enum": [ + "env", + "config", + "custom", + "api" + ] }, "env": { "type": "array", @@ -7703,7 +8507,14 @@ } } }, - "required": ["id", "name", "source", "env", "options", "models"] + "required": [ + "id", + "name", + "source", + "env", + "options", + "models" + ] }, "ProviderAuthMethod": { "type": "object", @@ -7724,7 +8535,10 @@ "type": "string" } }, - "required": ["type", "label"] + "required": [ + "type", + "label" + ] }, "ProviderAuthAuthorization": { "type": "object", @@ -7748,7 +8562,11 @@ "type": "string" } }, - "required": ["url", "method", "instructions"] + "required": [ + "url", + "method", + "instructions" + ] }, "Symbol": { "type": "object", @@ -7769,10 +8587,17 @@ "$ref": "#/components/schemas/Range" } }, - "required": ["uri", "range"] + "required": [ + "uri", + "range" + ] } }, - "required": ["name", "kind", "location"] + "required": [ + "name", + "kind", + "location" + ] }, "FileNode": { "type": "object", @@ -7788,13 +8613,22 @@ }, "type": { "type": "string", - "enum": ["file", "directory"] + "enum": [ + "file", + "directory" + ] }, "ignored": { "type": "boolean" } }, - "required": ["name", "path", "absolute", "type", "ignored"] + "required": [ + "name", + "path", + "absolute", + "type", + "ignored" + ] }, "FileContent": { "type": "object", @@ -7848,14 +8682,24 @@ } } }, - "required": ["oldStart", "oldLines", "newStart", "newLines", "lines"] + "required": [ + "oldStart", + "oldLines", + "newStart", + "newLines", + "lines" + ] } }, "index": { "type": "string" } }, - "required": ["oldFileName", "newFileName", "hunks"] + "required": [ + "oldFileName", + "newFileName", + "hunks" + ] }, "encoding": { "type": "string", @@ -7865,7 +8709,10 @@ "type": "string" } }, - "required": ["type", "content"] + "required": [ + "type", + "content" + ] }, "File": { "type": "object", @@ -7885,10 +8732,19 @@ }, "status": { "type": "string", - "enum": ["added", "deleted", "modified"] + "enum": [ + "added", + "deleted", + "modified" + ] } }, - "required": ["path", "added", "removed", "status"] + "required": [ + "path", + "added", + "removed", + "status" + ] }, "Agent": { "type": "object", @@ -7901,7 +8757,11 @@ }, "mode": { "type": "string", - "enum": ["subagent", "primary", "all"] + "enum": [ + "subagent", + "primary", + "all" + ] }, "builtIn": { "type": "boolean" @@ -7920,7 +8780,11 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "type": "object", @@ -7929,23 +8793,42 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } }, - "required": ["edit", "bash"] + "required": [ + "edit", + "bash" + ] }, "model": { "type": "object", @@ -7957,7 +8840,10 @@ "type": "string" } }, - "required": ["modelID", "providerID"] + "required": [ + "modelID", + "providerID" + ] }, "prompt": { "type": "string" @@ -7984,7 +8870,14 @@ "maximum": 9007199254740991 } }, - "required": ["name", "mode", "builtIn", "permission", "tools", "options"] + "required": [ + "name", + "mode", + "builtIn", + "permission", + "tools", + "options" + ] }, "MCPStatusConnected": { "type": "object", @@ -7994,7 +8887,9 @@ "const": "connected" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusDisabled": { "type": "object", @@ -8004,7 +8899,9 @@ "const": "disabled" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusFailed": { "type": "object", @@ -8017,7 +8914,10 @@ "type": "string" } }, - "required": ["status", "error"] + "required": [ + "status", + "error" + ] }, "MCPStatusNeedsAuth": { "type": "object", @@ -8027,7 +8927,9 @@ "const": "needs_auth" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusNeedsClientRegistration": { "type": "object", @@ -8040,7 +8942,10 @@ "type": "string" } }, - "required": ["status", "error"] + "required": [ + "status", + "error" + ] }, "MCPStatus": { "anyOf": [ @@ -8086,7 +8991,12 @@ ] } }, - "required": ["id", "name", "root", "status"] + "required": [ + "id", + "name", + "root", + "status" + ] }, "FormatterStatus": { "type": "object", @@ -8104,7 +9014,11 @@ "type": "boolean" } }, - "required": ["name", "extensions", "enabled"] + "required": [ + "name", + "extensions", + "enabled" + ] }, "OAuth": { "type": "object", @@ -8126,7 +9040,12 @@ "type": "string" } }, - "required": ["type", "refresh", "access", "expires"] + "required": [ + "type", + "refresh", + "access", + "expires" + ] }, "ApiAuth": { "type": "object", @@ -8139,7 +9058,10 @@ "type": "string" } }, - "required": ["type", "key"] + "required": [ + "type", + "key" + ] }, "WellKnownAuth": { "type": "object", @@ -8155,7 +9077,11 @@ "type": "string" } }, - "required": ["type", "key", "token"] + "required": [ + "type", + "key", + "token" + ] }, "Auth": { "anyOf": [ @@ -8172,4 +9098,4 @@ } } } -} +}
\ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 86edfeb0d..ab9a18b0b 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -10,13 +10,16 @@ "exports": { ".": "./src/index.ts", "./client": "./src/client.ts", - "./server": "./src/server.ts" + "./server": "./src/server.ts", + "./v2": "./src/v2/index.ts", + "./v2/client": "./src/v2/client.ts", + "./v2/server": "./src/v2/server.ts" }, "files": [ "dist" ], "devDependencies": { - "@hey-api/openapi-ts": "0.81.0", + "@hey-api/openapi-ts": "0.88.1", "@tsconfig/node22": "catalog:", "@types/node": "catalog:", "typescript": "catalog:", diff --git a/packages/sdk/js/script/build.ts b/packages/sdk/js/script/build.ts index c1fe0f423..7a6371691 100755 --- a/packages/sdk/js/script/build.ts +++ b/packages/sdk/js/script/build.ts @@ -10,13 +10,12 @@ import { createClient } from "@hey-api/openapi-ts" await $`bun dev generate > ${dir}/openapi.json`.cwd(path.resolve(dir, "../../opencode")) -await $`rm -rf src/gen` - await createClient({ input: "./openapi.json", output: { - path: "./src/gen", + path: "./src/v2/gen", tsConfigPath: path.join(dir, "tsconfig.json"), + clean: true, }, plugins: [ { @@ -28,6 +27,7 @@ await createClient({ instance: "OpencodeClient", exportFromIndex: false, auth: false, + paramsStructure: "flat", }, { name: "@hey-api/client-fetch", @@ -36,6 +36,8 @@ await createClient({ }, ], }) + await $`bun prettier --write src/gen` +await $`bun prettier --write src/v2` await $`rm -rf dist` await $`bun tsc` diff --git a/packages/sdk/js/src/client.ts b/packages/sdk/js/src/client.ts index ab4b75b5b..806ad26e5 100644 --- a/packages/sdk/js/src/client.ts +++ b/packages/sdk/js/src/client.ts @@ -1,19 +1,20 @@ export * from "./gen/types.gen.js" -export { type Config as OpencodeClientConfig, OpencodeClient } import { createClient } from "./gen/client/client.gen.js" import { type Config } from "./gen/client/types.gen.js" import { OpencodeClient } from "./gen/sdk.gen.js" +export { type Config as OpencodeClientConfig, OpencodeClient } export function createOpencodeClient(config?: Config & { directory?: string }) { if (!config?.fetch) { + const customFetch: any = (req: any) => { + // @ts-ignore + req.timeout = false + return fetch(req) + } config = { ...config, - fetch: (req) => { - // @ts-ignore - req.timeout = false - return fetch(req) - }, + fetch: customFetch, } } diff --git a/packages/sdk/js/src/gen/core/queryKeySerializer.gen.ts b/packages/sdk/js/src/gen/core/queryKeySerializer.gen.ts new file mode 100644 index 000000000..320204aef --- /dev/null +++ b/packages/sdk/js/src/gen/core/queryKeySerializer.gen.ts @@ -0,0 +1,111 @@ +// This file is auto-generated by @hey-api/openapi-ts + +/** + * JSON-friendly union that mirrors what Pinia Colada can hash. + */ +export type JsonValue = null | string | number | boolean | JsonValue[] | { [key: string]: JsonValue } + +/** + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. + */ +export const queryKeyJsonReplacer = (_key: string, value: unknown) => { + if (value === undefined || typeof value === "function" || typeof value === "symbol") { + return undefined + } + if (typeof value === "bigint") { + return value.toString() + } + if (value instanceof Date) { + return value.toISOString() + } + return value +} + +/** + * Safely stringifies a value and parses it back into a JsonValue. + */ +export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { + try { + const json = JSON.stringify(input, queryKeyJsonReplacer) + if (json === undefined) { + return undefined + } + return JSON.parse(json) as JsonValue + } catch { + return undefined + } +} + +/** + * Detects plain objects (including objects with a null prototype). + */ +const isPlainObject = (value: unknown): value is Record<string, unknown> => { + if (value === null || typeof value !== "object") { + return false + } + const prototype = Object.getPrototypeOf(value as object) + return prototype === Object.prototype || prototype === null +} + +/** + * Turns URLSearchParams into a sorted JSON object for deterministic keys. + */ +const serializeSearchParams = (params: URLSearchParams): JsonValue => { + const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b)) + const result: Record<string, JsonValue> = {} + + for (const [key, value] of entries) { + const existing = result[key] + if (existing === undefined) { + result[key] = value + continue + } + + if (Array.isArray(existing)) { + ;(existing as string[]).push(value) + } else { + result[key] = [existing, value] + } + } + + return result +} + +/** + * Normalizes any accepted value into a JSON-friendly shape for query keys. + */ +export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => { + if (value === null) { + return null + } + + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + return value + } + + if (value === undefined || typeof value === "function" || typeof value === "symbol") { + return undefined + } + + if (typeof value === "bigint") { + return value.toString() + } + + if (value instanceof Date) { + return value.toISOString() + } + + if (Array.isArray(value)) { + return stringifyToJsonValue(value) + } + + if (typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams) { + return serializeSearchParams(value) + } + + if (isPlainObject(value)) { + return stringifyToJsonValue(value) + } + + return undefined +} diff --git a/packages/sdk/js/src/v2/client.ts b/packages/sdk/js/src/v2/client.ts new file mode 100644 index 000000000..806ad26e5 --- /dev/null +++ b/packages/sdk/js/src/v2/client.ts @@ -0,0 +1,30 @@ +export * from "./gen/types.gen.js" + +import { createClient } from "./gen/client/client.gen.js" +import { type Config } from "./gen/client/types.gen.js" +import { OpencodeClient } from "./gen/sdk.gen.js" +export { type Config as OpencodeClientConfig, OpencodeClient } + +export function createOpencodeClient(config?: Config & { directory?: string }) { + if (!config?.fetch) { + const customFetch: any = (req: any) => { + // @ts-ignore + req.timeout = false + return fetch(req) + } + config = { + ...config, + fetch: customFetch, + } + } + + if (config?.directory) { + config.headers = { + ...config.headers, + "x-opencode-directory": config.directory, + } + } + + const client = createClient(config) + return new OpencodeClient({ client }) +} diff --git a/packages/sdk/js/src/v2/gen/client.gen.ts b/packages/sdk/js/src/v2/gen/client.gen.ts new file mode 100644 index 000000000..0c110eca3 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/client.gen.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from "./client/index.js" +import type { ClientOptions as ClientOptions2 } from "./types.gen.js" + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = ( + override?: Config<ClientOptions & T>, +) => Config<Required<ClientOptions> & T> + +export const client = createClient(createConfig<ClientOptions2>({ baseUrl: "http://localhost:4096" })) diff --git a/packages/sdk/js/src/v2/gen/client/client.gen.ts b/packages/sdk/js/src/v2/gen/client/client.gen.ts new file mode 100644 index 000000000..47f140342 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/client/client.gen.ts @@ -0,0 +1,278 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from "../core/serverSentEvents.gen.js" +import type { HttpMethod } from "../core/types.gen.js" +import { getValidRequestBody } from "../core/utils.gen.js" +import type { Client, Config, RequestOptions, ResolvedRequestOptions } from "./types.gen.js" +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from "./utils.gen.js" + +type ReqInit = Omit<RequestInit, "body" | "headers"> & { + body?: any + headers: ReturnType<typeof mergeHeaders> +} + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config) + + const getConfig = (): Config => ({ ..._config }) + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config) + return getConfig() + } + + const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>() + + const beforeRequest = async (options: RequestOptions) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined, + } + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }) + } + + if (opts.requestValidator) { + await opts.requestValidator(opts) + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body) + } + + // remove Content-Type header if body is empty to avoid sending invalid requests + if (opts.body === undefined || opts.serializedBody === "") { + opts.headers.delete("Content-Type") + } + + const url = buildUrl(opts) + + return { opts, url } + } + + const request: Client["request"] = async (options) => { + // @ts-expect-error + const { opts, url } = await beforeRequest(options) + const requestInit: ReqInit = { + redirect: "follow", + ...opts, + body: getValidRequestBody(opts), + } + + let request = new Request(url, requestInit) + + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts) + } + } + + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = opts.fetch! + let response: Response + + try { + response = await _fetch(request) + } catch (error) { + // Handle fetch exceptions (AbortError, network errors, etc.) + let finalError = error + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn(error, undefined as any, request, opts)) as unknown + } + } + + finalError = finalError || ({} as unknown) + + if (opts.throwOnError) { + throw finalError + } + + // Return error response + return opts.responseStyle === "data" + ? undefined + : { + error: finalError, + request, + response: undefined as any, + } + } + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts) + } + } + + const result = { + request, + response, + } + + if (response.ok) { + const parseAs = + (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json" + + if (response.status === 204 || response.headers.get("Content-Length") === "0") { + let emptyData: any + switch (parseAs) { + case "arrayBuffer": + case "blob": + case "text": + emptyData = await response[parseAs]() + break + case "formData": + emptyData = new FormData() + break + case "stream": + emptyData = response.body + break + case "json": + default: + emptyData = {} + break + } + return opts.responseStyle === "data" + ? emptyData + : { + data: emptyData, + ...result, + } + } + + let data: any + switch (parseAs) { + case "arrayBuffer": + case "blob": + case "formData": + case "json": + case "text": + data = await response[parseAs]() + break + case "stream": + return opts.responseStyle === "data" + ? response.body + : { + data: response.body, + ...result, + } + } + + if (parseAs === "json") { + if (opts.responseValidator) { + await opts.responseValidator(data) + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data) + } + } + + return opts.responseStyle === "data" + ? data + : { + data, + ...result, + } + } + + const textError = await response.text() + let jsonError: unknown + + try { + jsonError = JSON.parse(textError) + } catch { + // noop + } + + const error = jsonError ?? textError + let finalError = error + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn(error, response, request, opts)) as string + } + } + + finalError = finalError || ({} as string) + + if (opts.throwOnError) { + throw finalError + } + + // TODO: we probably want to return error and improve types + return opts.responseStyle === "data" + ? undefined + : { + error: finalError, + ...result, + } + } + + const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) => request({ ...options, method }) + + const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options) + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + headers: opts.headers as unknown as Record<string, string>, + method, + onRequest: async (url, init) => { + let request = new Request(url, init) + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts) + } + } + return request + }, + url, + }) + } + + return { + buildUrl, + connect: makeMethodFn("CONNECT"), + delete: makeMethodFn("DELETE"), + get: makeMethodFn("GET"), + getConfig, + head: makeMethodFn("HEAD"), + interceptors, + options: makeMethodFn("OPTIONS"), + patch: makeMethodFn("PATCH"), + post: makeMethodFn("POST"), + put: makeMethodFn("PUT"), + request, + setConfig, + sse: { + connect: makeSseFn("CONNECT"), + delete: makeSseFn("DELETE"), + get: makeSseFn("GET"), + head: makeSseFn("HEAD"), + options: makeSseFn("OPTIONS"), + patch: makeSseFn("PATCH"), + post: makeSseFn("POST"), + put: makeSseFn("PUT"), + trace: makeSseFn("TRACE"), + }, + trace: makeMethodFn("TRACE"), + } as Client +} diff --git a/packages/sdk/js/src/v2/gen/client/index.ts b/packages/sdk/js/src/v2/gen/client/index.ts new file mode 100644 index 000000000..0af63f330 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from "../core/auth.gen.js" +export type { QuerySerializerOptions } from "../core/bodySerializer.gen.js" +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from "../core/bodySerializer.gen.js" +export { buildClientParams } from "../core/params.gen.js" +export { serializeQueryKeyValue } from "../core/queryKeySerializer.gen.js" +export { createClient } from "./client.gen.js" +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from "./types.gen.js" +export { createConfig, mergeHeaders } from "./utils.gen.js" diff --git a/packages/sdk/js/src/v2/gen/client/types.gen.ts b/packages/sdk/js/src/v2/gen/client/types.gen.ts new file mode 100644 index 000000000..e053aa406 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/client/types.gen.ts @@ -0,0 +1,202 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from "../core/auth.gen.js" +import type { ServerSentEventsOptions, ServerSentEventsResult } from "../core/serverSentEvents.gen.js" +import type { Client as CoreClient, Config as CoreConfig } from "../core/types.gen.js" +import type { Middleware } from "./utils.gen.js" + +export type ResponseStyle = "data" | "fields" + +export interface Config<T extends ClientOptions = ClientOptions> + extends Omit<RequestInit, "body" | "headers" | "method">, + CoreConfig { + /** + * Base URL for all requests made by this client. + */ + baseUrl?: T["baseUrl"] + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch + /** + * Please don't use the Fetch client for Next.js applications. The `next` + * options won't have any effect. + * + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. + */ + next?: never + /** + * Return the response data parsed in a specified format. By default, `auto` + * will infer the appropriate method from the `Content-Type` response header. + * You can override this behavior with any of the {@link Body} methods. + * Select `stream` if you don't want to parse response data at all. + * + * @default 'auto' + */ + parseAs?: "arrayBuffer" | "auto" | "blob" | "formData" | "json" | "stream" | "text" + /** + * Should we return only data or multiple fields (data, error, response, etc.)? + * + * @default 'fields' + */ + responseStyle?: ResponseStyle + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T["throwOnError"] +} + +export interface RequestOptions< + TData = unknown, + TResponseStyle extends ResponseStyle = "fields", + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends Config<{ + responseStyle: TResponseStyle + throwOnError: ThrowOnError + }>, + Pick< + ServerSentEventsOptions<TData>, + "onSseError" | "onSseEvent" | "sseDefaultRetryDelay" | "sseMaxRetryAttempts" | "sseMaxRetryDelay" + > { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown + path?: Record<string, unknown> + query?: Record<string, unknown> + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray<Auth> + url: Url +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = "fields", + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> { + serializedBody?: string +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = "fields", +> = ThrowOnError extends true + ? Promise< + TResponseStyle extends "data" + ? TData extends Record<string, unknown> + ? TData[keyof TData] + : TData + : { + data: TData extends Record<string, unknown> ? TData[keyof TData] : TData + request: Request + response: Response + } + > + : Promise< + TResponseStyle extends "data" + ? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined + : ( + | { + data: TData extends Record<string, unknown> ? TData[keyof TData] : TData + error: undefined + } + | { + data: undefined + error: TError extends Record<string, unknown> ? TError[keyof TError] : TError + } + ) & { + request: Request + response: Response + } + > + +export interface ClientOptions { + baseUrl?: string + responseStyle?: ResponseStyle + throwOnError?: boolean +} + +type MethodFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">, +) => RequestResult<TData, TError, ThrowOnError, TResponseStyle> + +type SseFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">, +) => Promise<ServerSentEventsResult<TData, TError>> + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = "fields", +>( + options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method"> & + Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, "method">, +) => RequestResult<TData, TError, ThrowOnError, TResponseStyle> + +type BuildUrlFn = < + TData extends { + body?: unknown + path?: Record<string, unknown> + query?: Record<string, unknown> + url: string + }, +>( + options: TData & Options<TData>, +) => string + +export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & { + interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions> +} + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig<T extends ClientOptions = ClientOptions> = ( + override?: Config<ClientOptions & T>, +) => Config<Required<ClientOptions> & T> + +export interface TDataShape { + body?: unknown + headers?: unknown + path?: unknown + query?: unknown + url: string +} + +type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>> + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = "fields", +> = OmitKeys<RequestOptions<TResponse, TResponseStyle, ThrowOnError>, "body" | "path" | "query" | "url"> & + ([TData] extends [never] ? unknown : Omit<TData, "url">) diff --git a/packages/sdk/js/src/v2/gen/client/utils.gen.ts b/packages/sdk/js/src/v2/gen/client/utils.gen.ts new file mode 100644 index 000000000..3b1dfb787 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/client/utils.gen.ts @@ -0,0 +1,289 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from "../core/auth.gen.js" +import type { QuerySerializerOptions } from "../core/bodySerializer.gen.js" +import { jsonBodySerializer } from "../core/bodySerializer.gen.js" +import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from "../core/pathSerializer.gen.js" +import { getUrl } from "../core/utils.gen.js" +import type { Client, ClientOptions, Config, RequestOptions } from "./types.gen.js" + +export const createQuerySerializer = <T = unknown>({ parameters = {}, ...args }: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = [] + if (queryParams && typeof queryParams === "object") { + for (const name in queryParams) { + const value = queryParams[name] + + if (value === undefined || value === null) { + continue + } + + const options = parameters[name] || args + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: "form", + value, + ...options.array, + }) + if (serializedArray) search.push(serializedArray) + } else if (typeof value === "object") { + const serializedObject = serializeObjectParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: "deepObject", + value: value as Record<string, unknown>, + ...options.object, + }) + if (serializedObject) search.push(serializedObject) + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved: options.allowReserved, + name, + value: value as string, + }) + if (serializedPrimitive) search.push(serializedPrimitive) + } + } + } + return search.join("&") + } + return querySerializer +} + +/** + * Infers parseAs value from provided Content-Type header. + */ +export const getParseAs = (contentType: string | null): Exclude<Config["parseAs"], "auto"> => { + if (!contentType) { + // If no Content-Type header is provided, the best we can do is return the raw response body, + // which is effectively the same as the 'stream' option. + return "stream" + } + + const cleanContent = contentType.split(";")[0]?.trim() + + if (!cleanContent) { + return + } + + if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) { + return "json" + } + + if (cleanContent === "multipart/form-data") { + return "formData" + } + + if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) { + return "blob" + } + + if (cleanContent.startsWith("text/")) { + return "text" + } + + return +} + +const checkForExistence = ( + options: Pick<RequestOptions, "auth" | "query"> & { + headers: Headers + }, + name?: string, +): boolean => { + if (!name) { + return false + } + if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) { + return true + } + return false +} + +export const setAuthParams = async ({ + security, + ...options +}: Pick<Required<RequestOptions>, "security"> & + Pick<RequestOptions, "auth" | "query"> & { + headers: Headers + }) => { + for (const auth of security) { + if (checkForExistence(options, auth.name)) { + continue + } + + const token = await getAuthToken(auth, options.auth) + + if (!token) { + continue + } + + const name = auth.name ?? "Authorization" + + switch (auth.in) { + case "query": + if (!options.query) { + options.query = {} + } + options.query[name] = token + break + case "cookie": + options.headers.append("Cookie", `${name}=${token}`) + break + case "header": + default: + options.headers.set(name, token) + break + } + } +} + +export const buildUrl: Client["buildUrl"] = (options) => + getUrl({ + baseUrl: options.baseUrl as string, + path: options.path, + query: options.query, + querySerializer: + typeof options.querySerializer === "function" + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }) + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b } + if (config.baseUrl?.endsWith("/")) { + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1) + } + config.headers = mergeHeaders(a.headers, b.headers) + return config +} + +const headersEntries = (headers: Headers): Array<[string, string]> => { + const entries: Array<[string, string]> = [] + headers.forEach((value, key) => { + entries.push([key, value]) + }) + return entries +} + +export const mergeHeaders = (...headers: Array<Required<Config>["headers"] | undefined>): Headers => { + const mergedHeaders = new Headers() + for (const header of headers) { + if (!header) { + continue + } + + const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header) + + for (const [key, value] of iterator) { + if (value === null) { + mergedHeaders.delete(key) + } else if (Array.isArray(value)) { + for (const v of value) { + mergedHeaders.append(key, v as string) + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : (value as string)) + } + } + } + return mergedHeaders +} + +type ErrInterceptor<Err, Res, Req, Options> = ( + error: Err, + response: Res, + request: Req, + options: Options, +) => Err | Promise<Err> + +type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req> + +type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res> + +class Interceptors<Interceptor> { + fns: Array<Interceptor | null> = [] + + clear(): void { + this.fns = [] + } + + eject(id: number | Interceptor): void { + const index = this.getInterceptorIndex(id) + if (this.fns[index]) { + this.fns[index] = null + } + } + + exists(id: number | Interceptor): boolean { + const index = this.getInterceptorIndex(id) + return Boolean(this.fns[index]) + } + + getInterceptorIndex(id: number | Interceptor): number { + if (typeof id === "number") { + return this.fns[id] ? id : -1 + } + return this.fns.indexOf(id) + } + + update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false { + const index = this.getInterceptorIndex(id) + if (this.fns[index]) { + this.fns[index] = fn + return id + } + return false + } + + use(fn: Interceptor): number { + this.fns.push(fn) + return this.fns.length - 1 + } +} + +export interface Middleware<Req, Res, Err, Options> { + error: Interceptors<ErrInterceptor<Err, Res, Req, Options>> + request: Interceptors<ReqInterceptor<Req, Options>> + response: Interceptors<ResInterceptor<Res, Req, Options>> +} + +export const createInterceptors = <Req, Res, Err, Options>(): Middleware<Req, Res, Err, Options> => ({ + error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(), + request: new Interceptors<ReqInterceptor<Req, Options>>(), + response: new Interceptors<ResInterceptor<Res, Req, Options>>(), +}) + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: "form", + }, + object: { + explode: true, + style: "deepObject", + }, +}) + +const defaultHeaders = { + "Content-Type": "application/json", +} + +export const createConfig = <T extends ClientOptions = ClientOptions>( + override: Config<Omit<ClientOptions, keyof T> & T> = {}, +): Config<Omit<ClientOptions, keyof T> & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: "auto", + querySerializer: defaultQuerySerializer, + ...override, +}) diff --git a/packages/sdk/js/src/v2/gen/core/auth.gen.ts b/packages/sdk/js/src/v2/gen/core/auth.gen.ts new file mode 100644 index 000000000..bc7b230f4 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/auth.gen.ts @@ -0,0 +1,41 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AuthToken = string | undefined + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: "header" | "query" | "cookie" + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string + scheme?: "basic" | "bearer" + type: "apiKey" | "http" +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken, +): Promise<string | undefined> => { + const token = typeof callback === "function" ? await callback(auth) : callback + + if (!token) { + return + } + + if (auth.scheme === "bearer") { + return `Bearer ${token}` + } + + if (auth.scheme === "basic") { + return `Basic ${btoa(token)}` + } + + return token +} diff --git a/packages/sdk/js/src/v2/gen/core/bodySerializer.gen.ts b/packages/sdk/js/src/v2/gen/core/bodySerializer.gen.ts new file mode 100644 index 000000000..9678fb08e --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/bodySerializer.gen.ts @@ -0,0 +1,82 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { ArrayStyle, ObjectStyle, SerializerOptions } from "./pathSerializer.gen.js" + +export type QuerySerializer = (query: Record<string, unknown>) => string + +export type BodySerializer = (body: any) => any + +type QuerySerializerOptionsObject = { + allowReserved?: boolean + array?: Partial<SerializerOptions<ArrayStyle>> + object?: Partial<SerializerOptions<ObjectStyle>> +} + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record<string, QuerySerializerOptionsObject> +} + +const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => { + if (typeof value === "string" || value instanceof Blob) { + data.append(key, value) + } else if (value instanceof Date) { + data.append(key, value.toISOString()) + } else { + data.append(key, JSON.stringify(value)) + } +} + +const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => { + if (typeof value === "string") { + data.append(key, value) + } else { + data.append(key, JSON.stringify(value)) + } +} + +export const formDataBodySerializer = { + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): FormData => { + const data = new FormData() + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)) + } else { + serializeFormDataPair(data, key, value) + } + }) + + return data + }, +} + +export const jsonBodySerializer = { + bodySerializer: <T>(body: T): string => + JSON.stringify(body, (_key, value) => (typeof value === "bigint" ? value.toString() : value)), +} + +export const urlSearchParamsBodySerializer = { + bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): string => { + const data = new URLSearchParams() + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)) + } else { + serializeUrlSearchParamsPair(data, key, value) + } + }) + + return data.toString() + }, +} diff --git a/packages/sdk/js/src/v2/gen/core/params.gen.ts b/packages/sdk/js/src/v2/gen/core/params.gen.ts new file mode 100644 index 000000000..6e9d0b9ad --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/params.gen.ts @@ -0,0 +1,169 @@ +// This file is auto-generated by @hey-api/openapi-ts + +type Slot = "body" | "headers" | "path" | "query" + +export type Field = + | { + in: Exclude<Slot, "body"> + /** + * Field name. This is the name we want the user to see and use. + */ + key: string + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string + } + | { + in: Extract<Slot, "body"> + /** + * Key isn't required for bodies. + */ + key?: string + map?: string + } + | { + /** + * Field name. This is the name we want the user to see and use. + */ + key: string + /** + * Field mapped name. This is the name we want to use in the request. + * If `in` is omitted, `map` aliases `key` to the transport layer. + */ + map: Slot + } + +export interface Fields { + allowExtra?: Partial<Record<Slot, boolean>> + args?: ReadonlyArray<Field> +} + +export type FieldsConfig = ReadonlyArray<Field | Fields> + +const extraPrefixesMap: Record<string, Slot> = { + $body_: "body", + $headers_: "headers", + $path_: "path", + $query_: "query", +} +const extraPrefixes = Object.entries(extraPrefixesMap) + +type KeyMap = Map< + string, + | { + in: Slot + map?: string + } + | { + in?: never + map: Slot + } +> + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map() + } + + for (const config of fields) { + if ("in" in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }) + } + } else if ("key" in config) { + map.set(config.key, { + map: config.map, + }) + } else if (config.args) { + buildKeyMap(config.args, map) + } + } + + return map +} + +interface Params { + body: unknown + headers: Record<string, unknown> + path: Record<string, unknown> + query: Record<string, unknown> +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === "object" && !Object.keys(value).length) { + delete params[slot as Slot] + } + } +} + +export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + } + + const map = buildKeyMap(fields) + + let config: FieldsConfig[number] | undefined + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index] + } + + if (!config) { + continue + } + + if ("in" in config) { + if (config.key) { + const field = map.get(config.key)! + const name = field.map || config.key + if (field.in) { + ;(params[field.in] as Record<string, unknown>)[name] = arg + } + } else { + params.body = arg + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key) + + if (field) { + if (field.in) { + const name = field.map || key + ;(params[field.in] as Record<string, unknown>)[name] = value + } else { + params[field.map] = value + } + } else { + const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix)) + + if (extra) { + const [prefix, slot] = extra + ;(params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value + } else if ("allowExtra" in config && config.allowExtra) { + for (const [slot, allowed] of Object.entries(config.allowExtra)) { + if (allowed) { + ;(params[slot as Slot] as Record<string, unknown>)[key] = value + break + } + } + } + } + } + } + } + + stripEmptySlots(params) + + return params +} diff --git a/packages/sdk/js/src/v2/gen/core/pathSerializer.gen.ts b/packages/sdk/js/src/v2/gen/core/pathSerializer.gen.ts new file mode 100644 index 000000000..96be3bc5a --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/pathSerializer.gen.ts @@ -0,0 +1,167 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean + name: string +} + +export interface SerializerOptions<T> { + /** + * @default true + */ + explode: boolean + style: T +} + +export type ArrayStyle = "form" | "spaceDelimited" | "pipeDelimited" +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle +type MatrixStyle = "label" | "matrix" | "simple" +export type ObjectStyle = "form" | "deepObject" +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "label": + return "." + case "matrix": + return ";" + case "simple": + return "," + default: + return "&" + } +} + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "form": + return "," + case "pipeDelimited": + return "|" + case "spaceDelimited": + return "%20" + default: + return "," + } +} + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case "label": + return "." + case "matrix": + return ";" + case "simple": + return "," + default: + return "&" + } +} + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions<ArraySeparatorStyle> & { + value: unknown[] +}) => { + if (!explode) { + const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v as string))).join( + separatorArrayNoExplode(style), + ) + switch (style) { + case "label": + return `.${joinedValues}` + case "matrix": + return `;${name}=${joinedValues}` + case "simple": + return joinedValues + default: + return `${name}=${joinedValues}` + } + } + + const separator = separatorArrayExplode(style) + const joinedValues = value + .map((v) => { + if (style === "label" || style === "simple") { + return allowReserved ? v : encodeURIComponent(v as string) + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }) + }) + .join(separator) + return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues +} + +export const serializePrimitiveParam = ({ allowReserved, name, value }: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return "" + } + + if (typeof value === "object") { + throw new Error( + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.", + ) + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}` +} + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions<ObjectSeparatorStyle> & { + value: Record<string, unknown> | Date + valueOnly?: boolean +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}` + } + + if (style !== "deepObject" && !explode) { + let values: string[] = [] + Object.entries(value).forEach(([key, v]) => { + values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)] + }) + const joinedValues = values.join(",") + switch (style) { + case "form": + return `${name}=${joinedValues}` + case "label": + return `.${joinedValues}` + case "matrix": + return `;${name}=${joinedValues}` + default: + return joinedValues + } + } + + const separator = separatorObjectExplode(style) + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === "deepObject" ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator) + return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues +} diff --git a/packages/sdk/js/src/v2/gen/core/queryKeySerializer.gen.ts b/packages/sdk/js/src/v2/gen/core/queryKeySerializer.gen.ts new file mode 100644 index 000000000..320204aef --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/queryKeySerializer.gen.ts @@ -0,0 +1,111 @@ +// This file is auto-generated by @hey-api/openapi-ts + +/** + * JSON-friendly union that mirrors what Pinia Colada can hash. + */ +export type JsonValue = null | string | number | boolean | JsonValue[] | { [key: string]: JsonValue } + +/** + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. + */ +export const queryKeyJsonReplacer = (_key: string, value: unknown) => { + if (value === undefined || typeof value === "function" || typeof value === "symbol") { + return undefined + } + if (typeof value === "bigint") { + return value.toString() + } + if (value instanceof Date) { + return value.toISOString() + } + return value +} + +/** + * Safely stringifies a value and parses it back into a JsonValue. + */ +export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { + try { + const json = JSON.stringify(input, queryKeyJsonReplacer) + if (json === undefined) { + return undefined + } + return JSON.parse(json) as JsonValue + } catch { + return undefined + } +} + +/** + * Detects plain objects (including objects with a null prototype). + */ +const isPlainObject = (value: unknown): value is Record<string, unknown> => { + if (value === null || typeof value !== "object") { + return false + } + const prototype = Object.getPrototypeOf(value as object) + return prototype === Object.prototype || prototype === null +} + +/** + * Turns URLSearchParams into a sorted JSON object for deterministic keys. + */ +const serializeSearchParams = (params: URLSearchParams): JsonValue => { + const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b)) + const result: Record<string, JsonValue> = {} + + for (const [key, value] of entries) { + const existing = result[key] + if (existing === undefined) { + result[key] = value + continue + } + + if (Array.isArray(existing)) { + ;(existing as string[]).push(value) + } else { + result[key] = [existing, value] + } + } + + return result +} + +/** + * Normalizes any accepted value into a JSON-friendly shape for query keys. + */ +export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => { + if (value === null) { + return null + } + + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + return value + } + + if (value === undefined || typeof value === "function" || typeof value === "symbol") { + return undefined + } + + if (typeof value === "bigint") { + return value.toString() + } + + if (value instanceof Date) { + return value.toISOString() + } + + if (Array.isArray(value)) { + return stringifyToJsonValue(value) + } + + if (typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams) { + return serializeSearchParams(value) + } + + if (isPlainObject(value)) { + return stringifyToJsonValue(value) + } + + return undefined +} diff --git a/packages/sdk/js/src/v2/gen/core/serverSentEvents.gen.ts b/packages/sdk/js/src/v2/gen/core/serverSentEvents.gen.ts new file mode 100644 index 000000000..09ef3fb39 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/serverSentEvents.gen.ts @@ -0,0 +1,237 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from "./types.gen.js" + +export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method"> & + Pick<Config, "method" | "responseTransformer" | "responseValidator"> & { + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch + /** + * Implementing clients can call request interceptors inside this hook. + */ + onRequest?: (url: string, init: RequestInit) => Promise<Request> + /** + * Callback invoked when a network or parsing error occurs during streaming. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param error The error that occurred. + */ + onSseError?: (error: unknown) => void + /** + * Callback invoked when an event is streamed from the server. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param event Event streamed from the server. + * @returns Nothing (void). + */ + onSseEvent?: (event: StreamEvent<TData>) => void + serializedBody?: RequestInit["body"] + /** + * Default retry delay in milliseconds. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 3000 + */ + sseDefaultRetryDelay?: number + /** + * Maximum number of retry attempts before giving up. + */ + sseMaxRetryAttempts?: number + /** + * Maximum retry delay in milliseconds. + * + * Applies only when exponential backoff is used. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 30000 + */ + sseMaxRetryDelay?: number + /** + * Optional sleep function for retry backoff. + * + * Defaults to using `setTimeout`. + */ + sseSleepFn?: (ms: number) => Promise<void> + url: string + } + +export interface StreamEvent<TData = unknown> { + data: TData + event?: string + id?: string + retry?: number +} + +export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = { + stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext> +} + +export const createSseClient = <TData = unknown>({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult<TData> => { + let lastEventId: string | undefined + + const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))) + + const createStream = async function* () { + let retryDelay: number = sseDefaultRetryDelay ?? 3000 + let attempt = 0 + const signal = options.signal ?? new AbortController().signal + + while (true) { + if (signal.aborted) break + + attempt++ + + const headers = + options.headers instanceof Headers + ? options.headers + : new Headers(options.headers as Record<string, string> | undefined) + + if (lastEventId !== undefined) { + headers.set("Last-Event-ID", lastEventId) + } + + try { + const requestInit: RequestInit = { + redirect: "follow", + ...options, + body: options.serializedBody, + headers, + signal, + } + let request = new Request(url, requestInit) + if (onRequest) { + request = await onRequest(url, requestInit) + } + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = options.fetch ?? globalThis.fetch + const response = await _fetch(request) + + if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`) + + if (!response.body) throw new Error("No body in SSE response") + + const reader = response.body.pipeThrough(new TextDecoderStream()).getReader() + + let buffer = "" + + const abortHandler = () => { + try { + reader.cancel() + } catch { + // noop + } + } + + signal.addEventListener("abort", abortHandler) + + try { + while (true) { + const { done, value } = await reader.read() + if (done) break + buffer += value + + const chunks = buffer.split("\n\n") + buffer = chunks.pop() ?? "" + + for (const chunk of chunks) { + const lines = chunk.split("\n") + const dataLines: Array<string> = [] + let eventName: string | undefined + + for (const line of lines) { + if (line.startsWith("data:")) { + dataLines.push(line.replace(/^data:\s*/, "")) + } else if (line.startsWith("event:")) { + eventName = line.replace(/^event:\s*/, "") + } else if (line.startsWith("id:")) { + lastEventId = line.replace(/^id:\s*/, "") + } else if (line.startsWith("retry:")) { + const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10) + if (!Number.isNaN(parsed)) { + retryDelay = parsed + } + } + } + + let data: unknown + let parsedJson = false + + if (dataLines.length) { + const rawData = dataLines.join("\n") + try { + data = JSON.parse(rawData) + parsedJson = true + } catch { + data = rawData + } + } + + if (parsedJson) { + if (responseValidator) { + await responseValidator(data) + } + + if (responseTransformer) { + data = await responseTransformer(data) + } + } + + onSseEvent?.({ + data, + event: eventName, + id: lastEventId, + retry: retryDelay, + }) + + if (dataLines.length) { + yield data as any + } + } + } + } finally { + signal.removeEventListener("abort", abortHandler) + reader.releaseLock() + } + + break // exit loop on normal completion + } catch (error) { + // connection failed or aborted; retry after delay + onSseError?.(error) + + if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) { + break // stop after firing error + } + + // exponential backoff: double retry each attempt, cap at 30s + const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000) + await sleep(backoff) + } + } + } + + const stream = createStream() + + return { stream } +} diff --git a/packages/sdk/js/src/v2/gen/core/types.gen.ts b/packages/sdk/js/src/v2/gen/core/types.gen.ts new file mode 100644 index 000000000..bfa77b8ac --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/types.gen.ts @@ -0,0 +1,86 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from "./auth.gen.js" +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer.gen.js" + +export type HttpMethod = "connect" | "delete" | "get" | "head" | "options" | "patch" | "post" | "put" | "trace" + +export type Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never, SseFn = never> = { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn + getConfig: () => Config + request: RequestFn + setConfig: (config: Config) => Config +} & { + [K in HttpMethod]: MethodFn +} & ([SseFn] extends [never] ? { sse?: never } : { sse: { [K in HttpMethod]: SseFn } }) + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit["headers"] + | Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown> + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: Uppercase<HttpMethod> + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise<unknown> + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise<unknown> + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise<unknown> +} + +type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false + +export type OmitNever<T extends Record<string, unknown>> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true ? never : K]: T[K] +} diff --git a/packages/sdk/js/src/v2/gen/core/utils.gen.ts b/packages/sdk/js/src/v2/gen/core/utils.gen.ts new file mode 100644 index 000000000..8a45f7269 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/core/utils.gen.ts @@ -0,0 +1,137 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from "./bodySerializer.gen.js" +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from "./pathSerializer.gen.js" + +export interface PathSerializer { + path: Record<string, unknown> + url: string +} + +export const PATH_PARAM_RE = /\{[^{}]+\}/g + +export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { + let url = _url + const matches = _url.match(PATH_PARAM_RE) + if (matches) { + for (const match of matches) { + let explode = false + let name = match.substring(1, match.length - 1) + let style: ArraySeparatorStyle = "simple" + + if (name.endsWith("*")) { + explode = true + name = name.substring(0, name.length - 1) + } + + if (name.startsWith(".")) { + name = name.substring(1) + style = "label" + } else if (name.startsWith(";")) { + name = name.substring(1) + style = "matrix" + } + + const value = path[name] + + if (value === undefined || value === null) { + continue + } + + if (Array.isArray(value)) { + url = url.replace(match, serializeArrayParam({ explode, name, style, value })) + continue + } + + if (typeof value === "object") { + url = url.replace( + match, + serializeObjectParam({ + explode, + name, + style, + value: value as Record<string, unknown>, + valueOnly: true, + }), + ) + continue + } + + if (style === "matrix") { + url = url.replace( + match, + `;${serializePrimitiveParam({ + name, + value: value as string, + })}`, + ) + continue + } + + const replaceValue = encodeURIComponent(style === "label" ? `.${value as string}` : (value as string)) + url = url.replace(match, replaceValue) + } + } + return url +} + +export const getUrl = ({ + baseUrl, + path, + query, + querySerializer, + url: _url, +}: { + baseUrl?: string + path?: Record<string, unknown> + query?: Record<string, unknown> + querySerializer: QuerySerializer + url: string +}) => { + const pathUrl = _url.startsWith("/") ? _url : `/${_url}` + let url = (baseUrl ?? "") + pathUrl + if (path) { + url = defaultPathSerializer({ path, url }) + } + let search = query ? querySerializer(query) : "" + if (search.startsWith("?")) { + search = search.substring(1) + } + if (search) { + url += `?${search}` + } + return url +} + +export function getValidRequestBody(options: { + body?: unknown + bodySerializer?: BodySerializer | null + serializedBody?: unknown +}) { + const hasBody = options.body !== undefined + const isSerializedBody = hasBody && options.bodySerializer + + if (isSerializedBody) { + if ("serializedBody" in options) { + const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== "" + + return hasSerializedBody ? options.serializedBody : null + } + + // not all clients implement a serializedBody property (i.e. client-axios) + return options.body !== "" ? options.body : null + } + + // plain/text body + if (hasBody) { + return options.body + } + + // no body was provided + return undefined +} diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts new file mode 100644 index 000000000..caf6c9d00 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -0,0 +1,2343 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { client } from "./client.gen.js" +import { buildClientParams, type Client, type Options as Options2, type TDataShape } from "./client/index.js" +import type { + AgentPartInput, + AppAgentsResponses, + AppLogErrors, + AppLogResponses, + Auth as Auth2, + AuthSetErrors, + AuthSetResponses, + CommandListResponses, + Config as Config2, + ConfigGetResponses, + ConfigProvidersResponses, + ConfigUpdateErrors, + ConfigUpdateResponses, + EventSubscribeResponses, + EventTuiCommandExecute, + EventTuiPromptAppend, + EventTuiToastShow, + FileListResponses, + FilePartInput, + FileReadResponses, + FileStatusResponses, + FindFilesResponses, + FindSymbolsResponses, + FindTextResponses, + FormatterStatusResponses, + GlobalEventResponses, + InstanceDisposeResponses, + LspStatusResponses, + McpAddErrors, + McpAddResponses, + McpAuthAuthenticateErrors, + McpAuthAuthenticateResponses, + McpAuthCallbackErrors, + McpAuthCallbackResponses, + McpAuthRemoveErrors, + McpAuthRemoveResponses, + McpAuthStartErrors, + McpAuthStartResponses, + McpLocalConfig, + McpRemoteConfig, + McpStatusResponses, + PathGetResponses, + PermissionRespondErrors, + PermissionRespondResponses, + ProjectCurrentResponses, + ProjectListResponses, + ProviderAuthResponses, + ProviderListResponses, + ProviderOauthAuthorizeErrors, + ProviderOauthAuthorizeResponses, + ProviderOauthCallbackErrors, + ProviderOauthCallbackResponses, + PtyConnectErrors, + PtyConnectResponses, + PtyCreateErrors, + PtyCreateResponses, + PtyGetErrors, + PtyGetResponses, + PtyListResponses, + PtyRemoveErrors, + PtyRemoveResponses, + PtyUpdateErrors, + PtyUpdateResponses, + SessionAbortErrors, + SessionAbortResponses, + SessionChildrenErrors, + SessionChildrenResponses, + SessionCommandErrors, + SessionCommandResponses, + SessionCreateErrors, + SessionCreateResponses, + SessionDeleteErrors, + SessionDeleteResponses, + SessionDiffErrors, + SessionDiffResponses, + SessionForkResponses, + SessionGetErrors, + SessionGetResponses, + SessionInitErrors, + SessionInitResponses, + SessionListResponses, + SessionMessageErrors, + SessionMessageResponses, + SessionMessagesErrors, + SessionMessagesResponses, + SessionPromptAsyncErrors, + SessionPromptAsyncResponses, + SessionPromptErrors, + SessionPromptResponses, + SessionRevertErrors, + SessionRevertResponses, + SessionShareErrors, + SessionShareResponses, + SessionShellErrors, + SessionShellResponses, + SessionStatusErrors, + SessionStatusResponses, + SessionSummarizeErrors, + SessionSummarizeResponses, + SessionTodoErrors, + SessionTodoResponses, + SessionUnrevertErrors, + SessionUnrevertResponses, + SessionUnshareErrors, + SessionUnshareResponses, + SessionUpdateErrors, + SessionUpdateResponses, + SubtaskPartInput, + TextPartInput, + ToolIdsErrors, + ToolIdsResponses, + ToolListErrors, + ToolListResponses, + TuiAppendPromptErrors, + TuiAppendPromptResponses, + TuiClearPromptResponses, + TuiControlNextResponses, + TuiControlResponseResponses, + TuiExecuteCommandErrors, + TuiExecuteCommandResponses, + TuiOpenHelpResponses, + TuiOpenModelsResponses, + TuiOpenSessionsResponses, + TuiOpenThemesResponses, + TuiPublishErrors, + TuiPublishResponses, + TuiShowToastResponses, + TuiSubmitPromptResponses, + VcsGetResponses, +} from "./types.gen.js" + +export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2< + TData, + ThrowOnError +> & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record<string, unknown> +} + +class HeyApiClient { + protected client: Client + + constructor(args?: { client?: Client }) { + this.client = args?.client ?? client + } +} + +class HeyApiRegistry<T> { + private readonly defaultKey = "default" + + private readonly instances: Map<string, T> = new Map() + + get(key?: string): T { + const instance = this.instances.get(key ?? this.defaultKey) + if (!instance) { + throw new Error(`No SDK client found. Create one with "new OpencodeClient()" to fix this error.`) + } + return instance + } + + set(value: T, key?: string): void { + this.instances.set(key ?? this.defaultKey, value) + } +} + +export class Global extends HeyApiClient { + /** + * Get events + */ + public event<ThrowOnError extends boolean = false>(options?: Options<never, ThrowOnError>) { + return (options?.client ?? this.client).sse.get<GlobalEventResponses, unknown, ThrowOnError>({ + url: "/global/event", + ...options, + }) + } +} + +export class Project extends HeyApiClient { + /** + * List all projects + */ + public list<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ProjectListResponses, unknown, ThrowOnError>({ + url: "/project", + ...options, + ...params, + }) + } + + /** + * Get the current project + */ + public current<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ProjectCurrentResponses, unknown, ThrowOnError>({ + url: "/project/current", + ...options, + ...params, + }) + } +} + +export class Pty extends HeyApiClient { + /** + * List all PTY sessions + */ + public list<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<PtyListResponses, unknown, ThrowOnError>({ + url: "/pty", + ...options, + ...params, + }) + } + + /** + * Create a new PTY session + */ + public create<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + command?: string + args?: Array<string> + cwd?: string + title?: string + env?: { + [key: string]: string + } + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "command" }, + { in: "body", key: "args" }, + { in: "body", key: "cwd" }, + { in: "body", key: "title" }, + { in: "body", key: "env" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<PtyCreateResponses, PtyCreateErrors, ThrowOnError>({ + url: "/pty", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Remove a PTY session + */ + public remove<ThrowOnError extends boolean = false>( + parameters: { + ptyID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "ptyID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete<PtyRemoveResponses, PtyRemoveErrors, ThrowOnError>({ + url: "/pty/{ptyID}", + ...options, + ...params, + }) + } + + /** + * Get PTY session info + */ + public get<ThrowOnError extends boolean = false>( + parameters: { + ptyID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "ptyID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<PtyGetResponses, PtyGetErrors, ThrowOnError>({ + url: "/pty/{ptyID}", + ...options, + ...params, + }) + } + + /** + * Update PTY session + */ + public update<ThrowOnError extends boolean = false>( + parameters: { + ptyID: string + directory?: string + title?: string + size?: { + rows: number + cols: number + } + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "ptyID" }, + { in: "query", key: "directory" }, + { in: "body", key: "title" }, + { in: "body", key: "size" }, + ], + }, + ], + ) + return (options?.client ?? this.client).put<PtyUpdateResponses, PtyUpdateErrors, ThrowOnError>({ + url: "/pty/{ptyID}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Connect to a PTY session + */ + public connect<ThrowOnError extends boolean = false>( + parameters: { + ptyID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "ptyID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<PtyConnectResponses, PtyConnectErrors, ThrowOnError>({ + url: "/pty/{ptyID}/connect", + ...options, + ...params, + }) + } +} + +export class Config extends HeyApiClient { + /** + * Get config info + */ + public get<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ConfigGetResponses, unknown, ThrowOnError>({ + url: "/config", + ...options, + ...params, + }) + } + + /** + * Update config + */ + public update<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + config?: Config2 + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { key: "config", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch<ConfigUpdateResponses, ConfigUpdateErrors, ThrowOnError>({ + url: "/config", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * List all providers + */ + public providers<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ConfigProvidersResponses, unknown, ThrowOnError>({ + url: "/config/providers", + ...options, + ...params, + }) + } +} + +export class Tool extends HeyApiClient { + /** + * List all tool IDs (including built-in and dynamically registered) + */ + public ids<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ToolIdsResponses, ToolIdsErrors, ThrowOnError>({ + url: "/experimental/tool/ids", + ...options, + ...params, + }) + } + + /** + * List tools with JSON schema parameters for a provider/model + */ + public list<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + provider: string + model: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "provider" }, + { in: "query", key: "model" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<ToolListResponses, ToolListErrors, ThrowOnError>({ + url: "/experimental/tool", + ...options, + ...params, + }) + } +} + +export class Instance extends HeyApiClient { + /** + * Dispose the current instance + */ + public dispose<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<InstanceDisposeResponses, unknown, ThrowOnError>({ + url: "/instance/dispose", + ...options, + ...params, + }) + } +} + +export class Path extends HeyApiClient { + /** + * Get the current path + */ + public get<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<PathGetResponses, unknown, ThrowOnError>({ + url: "/path", + ...options, + ...params, + }) + } +} + +export class Vcs extends HeyApiClient { + /** + * Get VCS info for the current instance + */ + public get<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<VcsGetResponses, unknown, ThrowOnError>({ + url: "/vcs", + ...options, + ...params, + }) + } +} + +export class Session extends HeyApiClient { + /** + * List all sessions + */ + public list<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<SessionListResponses, unknown, ThrowOnError>({ + url: "/session", + ...options, + ...params, + }) + } + + /** + * Create a new session + */ + public create<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + parentID?: string + title?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "parentID" }, + { in: "body", key: "title" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionCreateResponses, SessionCreateErrors, ThrowOnError>({ + url: "/session", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Get session status + */ + public status<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<SessionStatusResponses, SessionStatusErrors, ThrowOnError>({ + url: "/session/status", + ...options, + ...params, + }) + } + + /** + * Delete a session and all its data + */ + public delete<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete<SessionDeleteResponses, SessionDeleteErrors, ThrowOnError>({ + url: "/session/{sessionID}", + ...options, + ...params, + }) + } + + /** + * Get session + */ + public get<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionGetResponses, SessionGetErrors, ThrowOnError>({ + url: "/session/{sessionID}", + ...options, + ...params, + }) + } + + /** + * Update session properties + */ + public update<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + title?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "title" }, + ], + }, + ], + ) + return (options?.client ?? this.client).patch<SessionUpdateResponses, SessionUpdateErrors, ThrowOnError>({ + url: "/session/{sessionID}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Get a session's children + */ + public children<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionChildrenResponses, SessionChildrenErrors, ThrowOnError>({ + url: "/session/{sessionID}/children", + ...options, + ...params, + }) + } + + /** + * Get the todo list for a session + */ + public todo<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionTodoResponses, SessionTodoErrors, ThrowOnError>({ + url: "/session/{sessionID}/todo", + ...options, + ...params, + }) + } + + /** + * Analyze the app and create an AGENTS.md file + */ + public init<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + modelID?: string + providerID?: string + messageID?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "modelID" }, + { in: "body", key: "providerID" }, + { in: "body", key: "messageID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionInitResponses, SessionInitErrors, ThrowOnError>({ + url: "/session/{sessionID}/init", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Fork an existing session at a specific message + */ + public fork<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "messageID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionForkResponses, unknown, ThrowOnError>({ + url: "/session/{sessionID}/fork", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Abort a session + */ + public abort<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionAbortResponses, SessionAbortErrors, ThrowOnError>({ + url: "/session/{sessionID}/abort", + ...options, + ...params, + }) + } + + /** + * Unshare the session + */ + public unshare<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete<SessionUnshareResponses, SessionUnshareErrors, ThrowOnError>({ + url: "/session/{sessionID}/share", + ...options, + ...params, + }) + } + + /** + * Share a session + */ + public share<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionShareResponses, SessionShareErrors, ThrowOnError>({ + url: "/session/{sessionID}/share", + ...options, + ...params, + }) + } + + /** + * Get the diff for this session + */ + public diff<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "query", key: "messageID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionDiffResponses, SessionDiffErrors, ThrowOnError>({ + url: "/session/{sessionID}/diff", + ...options, + ...params, + }) + } + + /** + * Summarize the session + */ + public summarize<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + providerID?: string + modelID?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "providerID" }, + { in: "body", key: "modelID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionSummarizeResponses, SessionSummarizeErrors, ThrowOnError>({ + url: "/session/{sessionID}/summarize", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * List messages for a session + */ + public messages<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + limit?: number + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "query", key: "limit" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionMessagesResponses, SessionMessagesErrors, ThrowOnError>({ + url: "/session/{sessionID}/message", + ...options, + ...params, + }) + } + + /** + * Create and send a new message to a session + */ + public prompt<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + model?: { + providerID: string + modelID: string + } + agent?: string + noReply?: boolean + system?: string + tools?: { + [key: string]: boolean + } + parts?: Array<TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput> + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "messageID" }, + { in: "body", key: "model" }, + { in: "body", key: "agent" }, + { in: "body", key: "noReply" }, + { in: "body", key: "system" }, + { in: "body", key: "tools" }, + { in: "body", key: "parts" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionPromptResponses, SessionPromptErrors, ThrowOnError>({ + url: "/session/{sessionID}/message", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Get a message from a session + */ + public message<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + messageID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "messageID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<SessionMessageResponses, SessionMessageErrors, ThrowOnError>({ + url: "/session/{sessionID}/message/{messageID}", + ...options, + ...params, + }) + } + + /** + * Create and send a new message to a session, start if needed and return immediately + */ + public promptAsync<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + model?: { + providerID: string + modelID: string + } + agent?: string + noReply?: boolean + system?: string + tools?: { + [key: string]: boolean + } + parts?: Array<TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput> + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "messageID" }, + { in: "body", key: "model" }, + { in: "body", key: "agent" }, + { in: "body", key: "noReply" }, + { in: "body", key: "system" }, + { in: "body", key: "tools" }, + { in: "body", key: "parts" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionPromptAsyncResponses, SessionPromptAsyncErrors, ThrowOnError>({ + url: "/session/{sessionID}/prompt_async", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Send a new command to a session + */ + public command<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + agent?: string + model?: string + arguments?: string + command?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "messageID" }, + { in: "body", key: "agent" }, + { in: "body", key: "model" }, + { in: "body", key: "arguments" }, + { in: "body", key: "command" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionCommandResponses, SessionCommandErrors, ThrowOnError>({ + url: "/session/{sessionID}/command", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Run a shell command + */ + public shell<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + agent?: string + model?: { + providerID: string + modelID: string + } + command?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "agent" }, + { in: "body", key: "model" }, + { in: "body", key: "command" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionShellResponses, SessionShellErrors, ThrowOnError>({ + url: "/session/{sessionID}/shell", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Revert a message + */ + public revert<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + messageID?: string + partID?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "messageID" }, + { in: "body", key: "partID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionRevertResponses, SessionRevertErrors, ThrowOnError>({ + url: "/session/{sessionID}/revert", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Restore all reverted messages + */ + public unrevert<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<SessionUnrevertResponses, SessionUnrevertErrors, ThrowOnError>({ + url: "/session/{sessionID}/unrevert", + ...options, + ...params, + }) + } +} + +export class Permission extends HeyApiClient { + /** + * Respond to a permission request + */ + public respond<ThrowOnError extends boolean = false>( + parameters: { + sessionID: string + permissionID: string + directory?: string + response?: "once" | "always" | "reject" + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "permissionID" }, + { in: "query", key: "directory" }, + { in: "body", key: "response" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<PermissionRespondResponses, PermissionRespondErrors, ThrowOnError>({ + url: "/session/{sessionID}/permissions/{permissionID}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + +export class Command extends HeyApiClient { + /** + * List all commands + */ + public list<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<CommandListResponses, unknown, ThrowOnError>({ + url: "/command", + ...options, + ...params, + }) + } +} + +export class Oauth extends HeyApiClient { + /** + * Authorize a provider using OAuth + */ + public authorize<ThrowOnError extends boolean = false>( + parameters: { + providerID: string + directory?: string + method?: number + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "providerID" }, + { in: "query", key: "directory" }, + { in: "body", key: "method" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + ProviderOauthAuthorizeResponses, + ProviderOauthAuthorizeErrors, + ThrowOnError + >({ + url: "/provider/{providerID}/oauth/authorize", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Handle OAuth callback for a provider + */ + public callback<ThrowOnError extends boolean = false>( + parameters: { + providerID: string + directory?: string + method?: number + code?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "providerID" }, + { in: "query", key: "directory" }, + { in: "body", key: "method" }, + { in: "body", key: "code" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post< + ProviderOauthCallbackResponses, + ProviderOauthCallbackErrors, + ThrowOnError + >({ + url: "/provider/{providerID}/oauth/callback", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + +export class Provider extends HeyApiClient { + /** + * List all providers + */ + public list<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ProviderListResponses, unknown, ThrowOnError>({ + url: "/provider", + ...options, + ...params, + }) + } + + /** + * Get provider authentication methods + */ + public auth<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<ProviderAuthResponses, unknown, ThrowOnError>({ + url: "/provider/auth", + ...options, + ...params, + }) + } + + oauth = new Oauth({ client: this.client }) +} + +export class Find extends HeyApiClient { + /** + * Find text in files + */ + public text<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + pattern: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "pattern" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<FindTextResponses, unknown, ThrowOnError>({ + url: "/find", + ...options, + ...params, + }) + } + + /** + * Find files + */ + public files<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + query: string + dirs?: "true" | "false" + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "query" }, + { in: "query", key: "dirs" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<FindFilesResponses, unknown, ThrowOnError>({ + url: "/find/file", + ...options, + ...params, + }) + } + + /** + * Find workspace symbols + */ + public symbols<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + query: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "query" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<FindSymbolsResponses, unknown, ThrowOnError>({ + url: "/find/symbol", + ...options, + ...params, + }) + } +} + +export class File extends HeyApiClient { + /** + * List files and directories + */ + public list<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + path: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "path" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<FileListResponses, unknown, ThrowOnError>({ + url: "/file", + ...options, + ...params, + }) + } + + /** + * Read a file + */ + public read<ThrowOnError extends boolean = false>( + parameters: { + directory?: string + path: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "path" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get<FileReadResponses, unknown, ThrowOnError>({ + url: "/file/content", + ...options, + ...params, + }) + } + + /** + * Get file status + */ + public status<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<FileStatusResponses, unknown, ThrowOnError>({ + url: "/file/status", + ...options, + ...params, + }) + } +} + +export class App extends HeyApiClient { + /** + * Write a log entry to the server logs + */ + public log<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + service?: string + level?: "debug" | "info" | "error" | "warn" + message?: string + extra?: { + [key: string]: unknown + } + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "service" }, + { in: "body", key: "level" }, + { in: "body", key: "message" }, + { in: "body", key: "extra" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<AppLogResponses, AppLogErrors, ThrowOnError>({ + url: "/log", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * List all agents + */ + public agents<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<AppAgentsResponses, unknown, ThrowOnError>({ + url: "/agent", + ...options, + ...params, + }) + } +} + +export class Auth extends HeyApiClient { + /** + * Remove OAuth credentials for an MCP server + */ + public remove<ThrowOnError extends boolean = false>( + parameters: { + name: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "name" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).delete<McpAuthRemoveResponses, McpAuthRemoveErrors, ThrowOnError>({ + url: "/mcp/{name}/auth", + ...options, + ...params, + }) + } + + /** + * Start OAuth authentication flow for an MCP server + */ + public start<ThrowOnError extends boolean = false>( + parameters: { + name: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "name" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<McpAuthStartResponses, McpAuthStartErrors, ThrowOnError>({ + url: "/mcp/{name}/auth", + ...options, + ...params, + }) + } + + /** + * Complete OAuth authentication with authorization code + */ + public callback<ThrowOnError extends boolean = false>( + parameters: { + name: string + directory?: string + code?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "name" }, + { in: "query", key: "directory" }, + { in: "body", key: "code" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<McpAuthCallbackResponses, McpAuthCallbackErrors, ThrowOnError>({ + url: "/mcp/{name}/auth/callback", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Start OAuth flow and wait for callback (opens browser) + */ + public authenticate<ThrowOnError extends boolean = false>( + parameters: { + name: string + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "name" }, + { in: "query", key: "directory" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<McpAuthAuthenticateResponses, McpAuthAuthenticateErrors, ThrowOnError>( + { + url: "/mcp/{name}/auth/authenticate", + ...options, + ...params, + }, + ) + } + + /** + * Set authentication credentials + */ + public set<ThrowOnError extends boolean = false>( + parameters: { + providerID: string + directory?: string + auth?: Auth2 + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "providerID" }, + { in: "query", key: "directory" }, + { key: "auth", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).put<AuthSetResponses, AuthSetErrors, ThrowOnError>({ + url: "/auth/{providerID}", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + +export class Mcp extends HeyApiClient { + /** + * Get MCP server status + */ + public status<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<McpStatusResponses, unknown, ThrowOnError>({ + url: "/mcp", + ...options, + ...params, + }) + } + + /** + * Add MCP server dynamically + */ + public add<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + name?: string + config?: McpLocalConfig | McpRemoteConfig + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "name" }, + { in: "body", key: "config" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<McpAddResponses, McpAddErrors, ThrowOnError>({ + url: "/mcp", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + auth = new Auth({ client: this.client }) +} + +export class Lsp extends HeyApiClient { + /** + * Get LSP server status + */ + public status<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<LspStatusResponses, unknown, ThrowOnError>({ + url: "/lsp", + ...options, + ...params, + }) + } +} + +export class Formatter extends HeyApiClient { + /** + * Get formatter status + */ + public status<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<FormatterStatusResponses, unknown, ThrowOnError>({ + url: "/formatter", + ...options, + ...params, + }) + } +} + +export class Control extends HeyApiClient { + /** + * Get the next TUI request from the queue + */ + public next<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).get<TuiControlNextResponses, unknown, ThrowOnError>({ + url: "/tui/control/next", + ...options, + ...params, + }) + } + + /** + * Submit a response to the TUI request queue + */ + public response<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + body?: unknown + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }, { in: "body" }] }]) + return (options?.client ?? this.client).post<TuiControlResponseResponses, unknown, ThrowOnError>({ + url: "/tui/control/response", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + +export class Tui extends HeyApiClient { + /** + * Append prompt to the TUI + */ + public appendPrompt<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + text?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "text" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<TuiAppendPromptResponses, TuiAppendPromptErrors, ThrowOnError>({ + url: "/tui/append-prompt", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Open the help dialog + */ + public openHelp<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiOpenHelpResponses, unknown, ThrowOnError>({ + url: "/tui/open-help", + ...options, + ...params, + }) + } + + /** + * Open the session dialog + */ + public openSessions<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiOpenSessionsResponses, unknown, ThrowOnError>({ + url: "/tui/open-sessions", + ...options, + ...params, + }) + } + + /** + * Open the theme dialog + */ + public openThemes<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiOpenThemesResponses, unknown, ThrowOnError>({ + url: "/tui/open-themes", + ...options, + ...params, + }) + } + + /** + * Open the model dialog + */ + public openModels<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiOpenModelsResponses, unknown, ThrowOnError>({ + url: "/tui/open-models", + ...options, + ...params, + }) + } + + /** + * Submit the prompt + */ + public submitPrompt<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiSubmitPromptResponses, unknown, ThrowOnError>({ + url: "/tui/submit-prompt", + ...options, + ...params, + }) + } + + /** + * Clear the prompt + */ + public clearPrompt<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).post<TuiClearPromptResponses, unknown, ThrowOnError>({ + url: "/tui/clear-prompt", + ...options, + ...params, + }) + } + + /** + * Execute a TUI command (e.g. agent_cycle) + */ + public executeCommand<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + command?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "command" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<TuiExecuteCommandResponses, TuiExecuteCommandErrors, ThrowOnError>({ + url: "/tui/execute-command", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Show a toast notification in the TUI + */ + public showToast<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + title?: string + message?: string + variant?: "info" | "success" | "warning" | "error" + duration?: number + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "body", key: "title" }, + { in: "body", key: "message" }, + { in: "body", key: "variant" }, + { in: "body", key: "duration" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post<TuiShowToastResponses, unknown, ThrowOnError>({ + url: "/tui/show-toast", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Publish a TUI event + */ + public publish<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }, { in: "body" }] }]) + return (options?.client ?? this.client).post<TuiPublishResponses, TuiPublishErrors, ThrowOnError>({ + url: "/tui/publish", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + control = new Control({ client: this.client }) +} + +export class Event extends HeyApiClient { + /** + * Get events + */ + public subscribe<ThrowOnError extends boolean = false>( + parameters?: { + directory?: string + }, + options?: Options<never, ThrowOnError>, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "directory" }] }]) + return (options?.client ?? this.client).sse.get<EventSubscribeResponses, unknown, ThrowOnError>({ + url: "/event", + ...options, + ...params, + }) + } +} + +export class OpencodeClient extends HeyApiClient { + public static readonly __registry = new HeyApiRegistry<OpencodeClient>() + + constructor(args?: { client?: Client; key?: string }) { + super(args) + OpencodeClient.__registry.set(this, args?.key) + } + + global = new Global({ client: this.client }) + + project = new Project({ client: this.client }) + + pty = new Pty({ client: this.client }) + + config = new Config({ client: this.client }) + + tool = new Tool({ client: this.client }) + + instance = new Instance({ client: this.client }) + + path = new Path({ client: this.client }) + + vcs = new Vcs({ client: this.client }) + + session = new Session({ client: this.client }) + + permission = new Permission({ client: this.client }) + + command = new Command({ client: this.client }) + + provider = new Provider({ client: this.client }) + + find = new Find({ client: this.client }) + + file = new File({ client: this.client }) + + app = new App({ client: this.client }) + + mcp = new Mcp({ client: this.client }) + + lsp = new Lsp({ client: this.client }) + + formatter = new Formatter({ client: this.client }) + + tui = new Tui({ client: this.client }) + + auth = new Auth({ client: this.client }) + + event = new Event({ client: this.client }) +} diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts new file mode 100644 index 000000000..8bbfa40a3 --- /dev/null +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -0,0 +1,3845 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}) +} + +export type EventServerInstanceDisposed = { + type: "server.instance.disposed" + properties: { + directory: string + } +} + +export type EventInstallationUpdated = { + type: "installation.updated" + properties: { + version: string + } +} + +export type EventInstallationUpdateAvailable = { + type: "installation.update-available" + properties: { + version: string + } +} + +export type EventLspClientDiagnostics = { + type: "lsp.client.diagnostics" + properties: { + serverID: string + path: string + } +} + +export type EventLspUpdated = { + type: "lsp.updated" + properties: { + [key: string]: unknown + } +} + +export type FileDiff = { + file: string + before: string + after: string + additions: number + deletions: number +} + +export type UserMessage = { + id: string + sessionID: string + role: "user" + time: { + created: number + } + summary?: { + title?: string + body?: string + diffs: Array<FileDiff> + } + agent: string + model: { + providerID: string + modelID: string + } + system?: string + tools?: { + [key: string]: boolean + } +} + +export type ProviderAuthError = { + name: "ProviderAuthError" + data: { + providerID: string + message: string + } +} + +export type UnknownError = { + name: "UnknownError" + data: { + message: string + } +} + +export type MessageOutputLengthError = { + name: "MessageOutputLengthError" + data: { + [key: string]: unknown + } +} + +export type MessageAbortedError = { + name: "MessageAbortedError" + data: { + message: string + } +} + +export type ApiError = { + name: "APIError" + data: { + message: string + statusCode?: number + isRetryable: boolean + responseHeaders?: { + [key: string]: string + } + responseBody?: string + } +} + +export type AssistantMessage = { + id: string + sessionID: string + role: "assistant" + time: { + created: number + completed?: number + } + error?: ProviderAuthError | UnknownError | MessageOutputLengthError | MessageAbortedError | ApiError + parentID: string + modelID: string + providerID: string + mode: string + path: { + cwd: string + root: string + } + summary?: boolean + cost: number + tokens: { + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + finish?: string +} + +export type Message = UserMessage | AssistantMessage + +export type EventMessageUpdated = { + type: "message.updated" + properties: { + info: Message + } +} + +export type EventMessageRemoved = { + type: "message.removed" + properties: { + sessionID: string + messageID: string + } +} + +export type TextPart = { + id: string + sessionID: string + messageID: string + type: "text" + text: string + synthetic?: boolean + ignored?: boolean + time?: { + start: number + end?: number + } + metadata?: { + [key: string]: unknown + } +} + +export type ReasoningPart = { + id: string + sessionID: string + messageID: string + type: "reasoning" + text: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end?: number + } +} + +export type FilePartSourceText = { + value: string + start: number + end: number +} + +export type FileSource = { + text: FilePartSourceText + type: "file" + path: string +} + +export type Range = { + start: { + line: number + character: number + } + end: { + line: number + character: number + } +} + +export type SymbolSource = { + text: FilePartSourceText + type: "symbol" + path: string + range: Range + name: string + kind: number +} + +export type FilePartSource = FileSource | SymbolSource + +export type FilePart = { + id: string + sessionID: string + messageID: string + type: "file" + mime: string + filename?: string + url: string + source?: FilePartSource +} + +export type ToolStatePending = { + status: "pending" + input: { + [key: string]: unknown + } + raw: string +} + +export type ToolStateRunning = { + status: "running" + input: { + [key: string]: unknown + } + title?: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + } +} + +export type ToolStateCompleted = { + status: "completed" + input: { + [key: string]: unknown + } + output: string + title: string + metadata: { + [key: string]: unknown + } + time: { + start: number + end: number + compacted?: number + } + attachments?: Array<FilePart> +} + +export type ToolStateError = { + status: "error" + input: { + [key: string]: unknown + } + error: string + metadata?: { + [key: string]: unknown + } + time: { + start: number + end: number + } +} + +export type ToolState = ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError + +export type ToolPart = { + id: string + sessionID: string + messageID: string + type: "tool" + callID: string + tool: string + state: ToolState + metadata?: { + [key: string]: unknown + } +} + +export type StepStartPart = { + id: string + sessionID: string + messageID: string + type: "step-start" + snapshot?: string +} + +export type StepFinishPart = { + id: string + sessionID: string + messageID: string + type: "step-finish" + reason: string + snapshot?: 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: "snapshot" + snapshot: string +} + +export type PatchPart = { + id: string + sessionID: string + messageID: string + type: "patch" + hash: string + files: Array<string> +} + +export type AgentPart = { + id: string + sessionID: string + messageID: string + type: "agent" + name: string + source?: { + value: string + start: number + end: number + } +} + +export type RetryPart = { + id: string + sessionID: string + messageID: string + type: "retry" + attempt: number + error: ApiError + time: { + created: number + } +} + +export type CompactionPart = { + id: string + sessionID: string + messageID: string + type: "compaction" + auto: boolean +} + +export type Part = + | TextPart + | { + id: string + sessionID: string + messageID: string + type: "subtask" + prompt: string + description: string + agent: string + } + | ReasoningPart + | FilePart + | ToolPart + | StepStartPart + | StepFinishPart + | SnapshotPart + | PatchPart + | AgentPart + | RetryPart + | CompactionPart + +export type EventMessagePartUpdated = { + type: "message.part.updated" + properties: { + part: Part + delta?: string + } +} + +export type EventMessagePartRemoved = { + type: "message.part.removed" + properties: { + sessionID: string + messageID: string + partID: string + } +} + +export type Permission = { + id: string + type: string + pattern?: string | Array<string> + sessionID: string + messageID: string + callID?: string + title: string + metadata: { + [key: string]: unknown + } + time: { + created: number + } +} + +export type EventPermissionUpdated = { + type: "permission.updated" + properties: Permission +} + +export type EventPermissionReplied = { + type: "permission.replied" + properties: { + sessionID: string + permissionID: string + response: string + } +} + +export type SessionStatus = + | { + type: "idle" + } + | { + type: "retry" + attempt: number + message: string + next: number + } + | { + type: "busy" + } + +export type EventSessionStatus = { + type: "session.status" + properties: { + sessionID: string + status: SessionStatus + } +} + +export type EventSessionIdle = { + type: "session.idle" + properties: { + sessionID: string + } +} + +export type EventSessionCompacted = { + type: "session.compacted" + properties: { + sessionID: string + } +} + +export type EventFileEdited = { + type: "file.edited" + properties: { + file: string + } +} + +export type Todo = { + /** + * Brief description of the task + */ + content: string + /** + * Current status of the task: pending, in_progress, completed, cancelled + */ + status: string + /** + * Priority level of the task: high, medium, low + */ + priority: string + /** + * Unique identifier for the todo item + */ + id: string +} + +export type EventTodoUpdated = { + type: "todo.updated" + properties: { + sessionID: string + todos: Array<Todo> + } +} + +export type EventCommandExecuted = { + type: "command.executed" + properties: { + name: string + sessionID: string + arguments: string + messageID: string + } +} + +export type Session = { + id: string + projectID: string + directory: string + parentID?: string + summary?: { + additions: number + deletions: number + files: number + diffs?: Array<FileDiff> + } + share?: { + url: string + } + title: string + version: string + time: { + created: number + updated: number + compacting?: number + } + revert?: { + messageID: string + partID?: string + snapshot?: string + diff?: string + } +} + +export type EventSessionCreated = { + type: "session.created" + properties: { + info: Session + } +} + +export type EventSessionUpdated = { + type: "session.updated" + properties: { + info: Session + } +} + +export type EventSessionDeleted = { + type: "session.deleted" + properties: { + info: Session + } +} + +export type EventSessionDiff = { + type: "session.diff" + properties: { + sessionID: string + diff: Array<FileDiff> + } +} + +export type EventSessionError = { + type: "session.error" + properties: { + sessionID?: string + error?: ProviderAuthError | UnknownError | MessageOutputLengthError | MessageAbortedError | ApiError + } +} + +export type EventFileWatcherUpdated = { + type: "file.watcher.updated" + properties: { + file: string + event: "add" | "change" | "unlink" + } +} + +export type EventVcsBranchUpdated = { + type: "vcs.branch.updated" + properties: { + branch?: string + } +} + +export type EventTuiPromptAppend = { + type: "tui.prompt.append" + properties: { + text: string + } +} + +export type EventTuiCommandExecute = { + type: "tui.command.execute" + properties: { + command: + | "session.list" + | "session.new" + | "session.share" + | "session.interrupt" + | "session.compact" + | "session.page.up" + | "session.page.down" + | "session.half.page.up" + | "session.half.page.down" + | "session.first" + | "session.last" + | "prompt.clear" + | "prompt.submit" + | "agent.cycle" + | string + } +} + +export type EventTuiToastShow = { + type: "tui.toast.show" + properties: { + title?: string + message: string + variant: "info" | "success" | "warning" | "error" + /** + * Duration in milliseconds + */ + duration?: number + } +} + +export type Pty = { + id: string + title: string + command: string + args: Array<string> + cwd: string + status: "running" | "exited" + pid: number +} + +export type EventPtyCreated = { + type: "pty.created" + properties: { + info: Pty + } +} + +export type EventPtyUpdated = { + type: "pty.updated" + properties: { + info: Pty + } +} + +export type EventPtyExited = { + type: "pty.exited" + properties: { + id: string + exitCode: number + } +} + +export type EventPtyDeleted = { + type: "pty.deleted" + properties: { + id: string + } +} + +export type EventServerConnected = { + type: "server.connected" + properties: { + [key: string]: unknown + } +} + +export type Event = + | EventServerInstanceDisposed + | EventInstallationUpdated + | EventInstallationUpdateAvailable + | EventLspClientDiagnostics + | EventLspUpdated + | EventMessageUpdated + | EventMessageRemoved + | EventMessagePartUpdated + | EventMessagePartRemoved + | EventPermissionUpdated + | EventPermissionReplied + | EventSessionStatus + | EventSessionIdle + | EventSessionCompacted + | EventFileEdited + | EventTodoUpdated + | EventCommandExecuted + | EventSessionCreated + | EventSessionUpdated + | EventSessionDeleted + | EventSessionDiff + | EventSessionError + | EventFileWatcherUpdated + | EventVcsBranchUpdated + | EventTuiPromptAppend + | EventTuiCommandExecute + | EventTuiToastShow + | EventPtyCreated + | EventPtyUpdated + | EventPtyExited + | EventPtyDeleted + | EventServerConnected + +export type GlobalEvent = { + directory: string + payload: Event +} + +export type Project = { + id: string + worktree: string + vcsDir?: string + vcs?: "git" + time: { + created: number + initialized?: number + } +} + +export type BadRequestError = { + data: unknown + errors: Array<{ + [key: string]: unknown + }> + success: false +} + +export type NotFoundError = { + name: "NotFoundError" + data: { + message: string + } +} + +/** + * Custom keybind configurations + */ +export type KeybindsConfig = { + /** + * Leader key for keybind combinations + */ + leader?: string + /** + * Exit the application + */ + app_exit?: string + /** + * Open external editor + */ + editor_open?: string + /** + * List available themes + */ + theme_list?: string + /** + * Toggle sidebar + */ + sidebar_toggle?: string + /** + * Toggle session scrollbar + */ + scrollbar_toggle?: string + /** + * Toggle username visibility + */ + username_toggle?: string + /** + * View status + */ + status_view?: string + /** + * Export session to editor + */ + session_export?: string + /** + * Create a new session + */ + session_new?: string + /** + * List all sessions + */ + session_list?: string + /** + * Show session timeline + */ + session_timeline?: 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 + /** + * 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 first message + */ + messages_first?: string + /** + * Navigate to last message + */ + messages_last?: string + /** + * Navigate to last user message + */ + messages_last_user?: string + /** + * Copy message + */ + messages_copy?: string + /** + * Undo message + */ + messages_undo?: string + /** + * Redo message + */ + messages_redo?: string + /** + * Toggle code block concealment in messages + */ + messages_toggle_conceal?: string + /** + * Toggle tool details visibility + */ + tool_details?: string + /** + * List available models + */ + model_list?: string + /** + * Next recently used model + */ + model_cycle_recent?: string + /** + * Previous recently used model + */ + model_cycle_recent_reverse?: string + /** + * List available commands + */ + command_list?: string + /** + * List agents + */ + agent_list?: string + /** + * Next agent + */ + agent_cycle?: string + /** + * Previous agent + */ + agent_cycle_reverse?: string + /** + * Clear input field + */ + input_clear?: string + /** + * Forward delete + */ + input_forward_delete?: string + /** + * Paste from clipboard + */ + input_paste?: string + /** + * Submit input + */ + input_submit?: string + /** + * Insert newline in input + */ + input_newline?: string + /** + * Previous history item + */ + history_previous?: string + /** + * Next history item + */ + history_next?: string + /** + * Next child session + */ + session_child_cycle?: string + /** + * Previous child session + */ + session_child_cycle_reverse?: string + /** + * Suspend terminal + */ + terminal_suspend?: string +} + +export type AgentConfig = { + model?: string + temperature?: number + top_p?: number + prompt?: string + tools?: { + [key: string]: boolean + } + disable?: boolean + /** + * Description of when to use the agent + */ + description?: string + mode?: "subagent" | "primary" | "all" + /** + * Hex color code for the agent (e.g., #FF5733) + */ + color?: string + /** + * Maximum number of agentic iterations before forcing text-only response + */ + maxSteps?: number + permission?: { + edit?: "ask" | "allow" | "deny" + bash?: + | "ask" + | "allow" + | "deny" + | { + [key: string]: "ask" | "allow" | "deny" + } + webfetch?: "ask" | "allow" | "deny" + doom_loop?: "ask" | "allow" | "deny" + external_directory?: "ask" | "allow" | "deny" + } + [key: string]: + | unknown + | string + | number + | { + [key: string]: boolean + } + | boolean + | "subagent" + | "primary" + | "all" + | string + | number + | { + edit?: "ask" | "allow" | "deny" + bash?: + | "ask" + | "allow" + | "deny" + | { + [key: string]: "ask" | "allow" | "deny" + } + webfetch?: "ask" | "allow" | "deny" + doom_loop?: "ask" | "allow" | "deny" + external_directory?: "ask" | "allow" | "deny" + } + | undefined +} + +export type ProviderConfig = { + api?: string + name?: string + env?: Array<string> + id?: string + npm?: string + models?: { + [key: string]: { + id?: string + name?: string + release_date?: string + attachment?: boolean + reasoning?: boolean + temperature?: boolean + tool_call?: boolean + cost?: { + input: number + output: number + cache_read?: number + cache_write?: number + context_over_200k?: { + input: number + output: number + cache_read?: number + cache_write?: number + } + } + limit?: { + context: number + output: number + } + modalities?: { + input: Array<"text" | "audio" | "image" | "video" | "pdf"> + output: Array<"text" | "audio" | "image" | "video" | "pdf"> + } + experimental?: boolean + status?: "alpha" | "beta" | "deprecated" + options?: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + provider?: { + npm: string + } + } + } + whitelist?: Array<string> + blacklist?: Array<string> + options?: { + apiKey?: string + baseURL?: string + /** + * GitHub Enterprise URL for copilot authentication + */ + enterpriseUrl?: string + /** + * Enable promptCacheKey for this provider (default false) + */ + setCacheKey?: boolean + /** + * Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout. + */ + timeout?: number | false + [key: string]: unknown | string | boolean | number | false | undefined + } +} + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: "local" + /** + * Command and arguments to run the MCP server + */ + command: Array<string> + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string + } + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean + /** + * Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds) if not specified. + */ + timeout?: number +} + +export type McpOAuthConfig = { + /** + * OAuth client ID. If not provided, dynamic client registration (RFC 7591) will be attempted. + */ + clientId?: string + /** + * OAuth client secret (if required by the authorization server) + */ + clientSecret?: string + /** + * OAuth scopes to request during authorization + */ + scope?: string +} + +export type McpRemoteConfig = { + /** + * Type of MCP server connection + */ + type: "remote" + /** + * URL of the remote MCP server + */ + url: string + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean + /** + * Headers to send with the request + */ + headers?: { + [key: string]: string + } + /** + * OAuth authentication configuration for the MCP server. Set to false to disable OAuth auto-detection. + */ + oauth?: McpOAuthConfig | false + /** + * Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds) if not specified. + */ + timeout?: number +} + +/** + * @deprecated Always uses stretch layout. + */ +export type LayoutConfig = "auto" | "stretch" + +export type Config = { + /** + * JSON schema reference for configuration validation + */ + $schema?: string + /** + * Theme name to use for the interface + */ + theme?: string + keybinds?: KeybindsConfig + /** + * TUI specific settings + */ + tui?: { + /** + * TUI scroll speed + */ + scroll_speed?: number + /** + * Scroll acceleration settings + */ + scroll_acceleration?: { + /** + * Enable scroll acceleration + */ + enabled: boolean + } + /** + * Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column + */ + diff_style?: "auto" | "stacked" + } + /** + * Command configuration, see https://opencode.ai/docs/commands + */ + command?: { + [key: string]: { + template: string + description?: string + agent?: string + model?: string + subtask?: boolean + } + } + watcher?: { + ignore?: Array<string> + } + plugin?: Array<string> + snapshot?: boolean + /** + * 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. Set to true to auto-update, false to disable, or 'notify' to show update notifications + */ + autoupdate?: boolean | "notify" + /** + * Disable providers that are loaded automatically + */ + disabled_providers?: Array<string> + /** + * When set, ONLY these providers will be enabled. All other providers will be ignored + */ + enabled_providers?: Array<string> + /** + * Model to use in the format of provider/model, eg anthropic/claude-2 + */ + model?: string + /** + * Small model to use for tasks like title generation in the format of provider/model + */ + small_model?: string + /** + * Custom username to display in conversations instead of system username + */ + username?: string + /** + * @deprecated Use `agent` field instead. + */ + mode?: { + build?: AgentConfig + plan?: AgentConfig + [key: string]: AgentConfig | undefined + } + /** + * Agent configuration, see https://opencode.ai/docs/agent + */ + agent?: { + plan?: AgentConfig + build?: AgentConfig + general?: AgentConfig + explore?: AgentConfig + [key: string]: AgentConfig | undefined + } + /** + * Custom provider configurations and model overrides + */ + provider?: { + [key: string]: ProviderConfig + } + /** + * MCP (Model Context Protocol) server configurations + */ + mcp?: { + [key: string]: McpLocalConfig | McpRemoteConfig + } + formatter?: + | false + | { + [key: string]: { + disabled?: boolean + command?: Array<string> + environment?: { + [key: string]: string + } + extensions?: Array<string> + } + } + lsp?: + | false + | { + [key: string]: + | { + disabled: true + } + | { + command: Array<string> + extensions?: Array<string> + disabled?: boolean + env?: { + [key: string]: string + } + initialization?: { + [key: string]: unknown + } + } + } + /** + * Additional instruction files or patterns to include + */ + instructions?: Array<string> + layout?: LayoutConfig + permission?: { + edit?: "ask" | "allow" | "deny" + bash?: + | "ask" + | "allow" + | "deny" + | { + [key: string]: "ask" | "allow" | "deny" + } + webfetch?: "ask" | "allow" | "deny" + doom_loop?: "ask" | "allow" | "deny" + external_directory?: "ask" | "allow" | "deny" + } + tools?: { + [key: string]: boolean + } + enterprise?: { + /** + * Enterprise URL + */ + url?: string + } + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array<string> + environment?: { + [key: string]: string + } + }> + } + session_completed?: Array<{ + command: Array<string> + environment?: { + [key: string]: string + } + }> + } + /** + * Number of retries for chat completions on failure + */ + chatMaxRetries?: number + disable_paste_summary?: boolean + /** + * Enable the batch tool + */ + batch_tool?: boolean + /** + * Enable OpenTelemetry spans for AI SDK calls (using the 'experimental_telemetry' flag) + */ + openTelemetry?: boolean + /** + * Tools that should only be available to primary agents. + */ + primary_tools?: Array<string> + } +} + +export type ToolIds = Array<string> + +export type ToolListItem = { + id: string + description: string + parameters: unknown +} + +export type ToolList = Array<ToolListItem> + +export type Path = { + state: string + config: string + worktree: string + directory: string +} + +export type VcsInfo = { + branch: string +} + +export type TextPartInput = { + id?: string + type: "text" + text: string + synthetic?: boolean + ignored?: boolean + time?: { + start: number + end?: number + } + metadata?: { + [key: string]: unknown + } +} + +export type FilePartInput = { + id?: string + type: "file" + mime: string + filename?: string + url: string + source?: FilePartSource +} + +export type AgentPartInput = { + id?: string + type: "agent" + name: string + source?: { + value: string + start: number + end: number + } +} + +export type SubtaskPartInput = { + id?: string + type: "subtask" + prompt: string + description: string + agent: string +} + +export type Command = { + name: string + description?: string + agent?: string + model?: string + template: string + subtask?: boolean +} + +export type Model = { + id: string + providerID: string + api: { + id: string + url: string + npm: string + } + name: string + capabilities: { + temperature: boolean + reasoning: boolean + attachment: boolean + toolcall: boolean + input: { + text: boolean + audio: boolean + image: boolean + video: boolean + pdf: boolean + } + output: { + text: boolean + audio: boolean + image: boolean + video: boolean + pdf: boolean + } + } + cost: { + input: number + output: number + cache: { + read: number + write: number + } + experimentalOver200K?: { + input: number + output: number + cache: { + read: number + write: number + } + } + } + limit: { + context: number + output: number + } + status: "alpha" | "beta" | "deprecated" | "active" + options: { + [key: string]: unknown + } + headers: { + [key: string]: string + } +} + +export type Provider = { + id: string + name: string + source: "env" | "config" | "custom" | "api" + env: Array<string> + key?: string + options: { + [key: string]: unknown + } + models: { + [key: string]: Model + } +} + +export type ProviderAuthMethod = { + type: "oauth" | "api" + label: string +} + +export type ProviderAuthAuthorization = { + url: string + method: "auto" | "code" + instructions: string +} + +export type Symbol = { + name: string + kind: number + location: { + uri: string + range: Range + } +} + +export type FileNode = { + name: string + path: string + absolute: string + type: "file" | "directory" + ignored: boolean +} + +export type FileContent = { + type: "text" + content: string + diff?: string + patch?: { + oldFileName: string + newFileName: string + oldHeader?: string + newHeader?: string + hunks: Array<{ + oldStart: number + oldLines: number + newStart: number + newLines: number + lines: Array<string> + }> + index?: string + } + encoding?: "base64" + mimeType?: string +} + +export type File = { + path: string + added: number + removed: number + status: "added" | "deleted" | "modified" +} + +export type Agent = { + name: string + description?: string + mode: "subagent" | "primary" | "all" + builtIn: boolean + topP?: number + temperature?: number + color?: string + permission: { + edit: "ask" | "allow" | "deny" + bash: { + [key: string]: "ask" | "allow" | "deny" + } + webfetch?: "ask" | "allow" | "deny" + doom_loop?: "ask" | "allow" | "deny" + external_directory?: "ask" | "allow" | "deny" + } + model?: { + modelID: string + providerID: string + } + prompt?: string + tools: { + [key: string]: boolean + } + options: { + [key: string]: unknown + } + maxSteps?: number +} + +export type McpStatusConnected = { + status: "connected" +} + +export type McpStatusDisabled = { + status: "disabled" +} + +export type McpStatusFailed = { + status: "failed" + error: string +} + +export type McpStatusNeedsAuth = { + status: "needs_auth" +} + +export type McpStatusNeedsClientRegistration = { + status: "needs_client_registration" + error: string +} + +export type McpStatus = + | McpStatusConnected + | McpStatusDisabled + | McpStatusFailed + | McpStatusNeedsAuth + | McpStatusNeedsClientRegistration + +export type LspStatus = { + id: string + name: string + root: string + status: "connected" | "error" +} + +export type FormatterStatus = { + name: string + extensions: Array<string> + enabled: boolean +} + +export type OAuth = { + type: "oauth" + refresh: string + access: string + expires: number + enterpriseUrl?: string +} + +export type ApiAuth = { + type: "api" + key: string +} + +export type WellKnownAuth = { + type: "wellknown" + key: string + token: string +} + +export type Auth = OAuth | ApiAuth | WellKnownAuth + +export type GlobalEventData = { + body?: never + path?: never + query?: never + url: "/global/event" +} + +export type GlobalEventResponses = { + /** + * Event stream + */ + 200: GlobalEvent +} + +export type GlobalEventResponse = GlobalEventResponses[keyof GlobalEventResponses] + +export type ProjectListData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/project" +} + +export type ProjectListResponses = { + /** + * List of projects + */ + 200: Array<Project> +} + +export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses] + +export type ProjectCurrentData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/project/current" +} + +export type ProjectCurrentResponses = { + /** + * Current project + */ + 200: Project +} + +export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses] + +export type PtyListData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/pty" +} + +export type PtyListResponses = { + /** + * List of sessions + */ + 200: Array<Pty> +} + +export type PtyListResponse = PtyListResponses[keyof PtyListResponses] + +export type PtyCreateData = { + body?: { + command?: string + args?: Array<string> + cwd?: string + title?: string + env?: { + [key: string]: string + } + } + path?: never + query?: { + directory?: string + } + url: "/pty" +} + +export type PtyCreateErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type PtyCreateError = PtyCreateErrors[keyof PtyCreateErrors] + +export type PtyCreateResponses = { + /** + * Created session + */ + 200: Pty +} + +export type PtyCreateResponse = PtyCreateResponses[keyof PtyCreateResponses] + +export type PtyRemoveData = { + body?: never + path: { + ptyID: string + } + query?: { + directory?: string + } + url: "/pty/{ptyID}" +} + +export type PtyRemoveErrors = { + /** + * Not found + */ + 404: NotFoundError +} + +export type PtyRemoveError = PtyRemoveErrors[keyof PtyRemoveErrors] + +export type PtyRemoveResponses = { + /** + * Session removed + */ + 200: boolean +} + +export type PtyRemoveResponse = PtyRemoveResponses[keyof PtyRemoveResponses] + +export type PtyGetData = { + body?: never + path: { + ptyID: string + } + query?: { + directory?: string + } + url: "/pty/{ptyID}" +} + +export type PtyGetErrors = { + /** + * Not found + */ + 404: NotFoundError +} + +export type PtyGetError = PtyGetErrors[keyof PtyGetErrors] + +export type PtyGetResponses = { + /** + * Session info + */ + 200: Pty +} + +export type PtyGetResponse = PtyGetResponses[keyof PtyGetResponses] + +export type PtyUpdateData = { + body?: { + title?: string + size?: { + rows: number + cols: number + } + } + path: { + ptyID: string + } + query?: { + directory?: string + } + url: "/pty/{ptyID}" +} + +export type PtyUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type PtyUpdateError = PtyUpdateErrors[keyof PtyUpdateErrors] + +export type PtyUpdateResponses = { + /** + * Updated session + */ + 200: Pty +} + +export type PtyUpdateResponse = PtyUpdateResponses[keyof PtyUpdateResponses] + +export type PtyConnectData = { + body?: never + path: { + ptyID: string + } + query?: { + directory?: string + } + url: "/pty/{ptyID}/connect" +} + +export type PtyConnectErrors = { + /** + * Not found + */ + 404: NotFoundError +} + +export type PtyConnectError = PtyConnectErrors[keyof PtyConnectErrors] + +export type PtyConnectResponses = { + /** + * Connected session + */ + 200: boolean +} + +export type PtyConnectResponse = PtyConnectResponses[keyof PtyConnectResponses] + +export type ConfigGetData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/config" +} + +export type ConfigGetResponses = { + /** + * Get config info + */ + 200: Config +} + +export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses] + +export type ConfigUpdateData = { + body?: Config + path?: never + query?: { + directory?: string + } + url: "/config" +} + +export type ConfigUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type ConfigUpdateError = ConfigUpdateErrors[keyof ConfigUpdateErrors] + +export type ConfigUpdateResponses = { + /** + * Successfully updated config + */ + 200: Config +} + +export type ConfigUpdateResponse = ConfigUpdateResponses[keyof ConfigUpdateResponses] + +export type ToolIdsData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/experimental/tool/ids" +} + +export type ToolIdsErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type ToolIdsError = ToolIdsErrors[keyof ToolIdsErrors] + +export type ToolIdsResponses = { + /** + * Tool IDs + */ + 200: ToolIds +} + +export type ToolIdsResponse = ToolIdsResponses[keyof ToolIdsResponses] + +export type ToolListData = { + body?: never + path?: never + query: { + directory?: string + provider: string + model: string + } + url: "/experimental/tool" +} + +export type ToolListErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type ToolListError = ToolListErrors[keyof ToolListErrors] + +export type ToolListResponses = { + /** + * Tools + */ + 200: ToolList +} + +export type ToolListResponse = ToolListResponses[keyof ToolListResponses] + +export type InstanceDisposeData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/instance/dispose" +} + +export type InstanceDisposeResponses = { + /** + * Instance disposed + */ + 200: boolean +} + +export type InstanceDisposeResponse = InstanceDisposeResponses[keyof InstanceDisposeResponses] + +export type PathGetData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/path" +} + +export type PathGetResponses = { + /** + * Path + */ + 200: Path +} + +export type PathGetResponse = PathGetResponses[keyof PathGetResponses] + +export type VcsGetData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/vcs" +} + +export type VcsGetResponses = { + /** + * VCS info + */ + 200: VcsInfo +} + +export type VcsGetResponse = VcsGetResponses[keyof VcsGetResponses] + +export type SessionListData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/session" +} + +export type SessionListResponses = { + /** + * List of sessions + */ + 200: Array<Session> +} + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses] + +export type SessionCreateData = { + body?: { + parentID?: string + title?: string + } + path?: never + query?: { + directory?: string + } + url: "/session" +} + +export type SessionCreateErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type SessionCreateError = SessionCreateErrors[keyof SessionCreateErrors] + +export type SessionCreateResponses = { + /** + * Successfully created session + */ + 200: Session +} + +export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses] + +export type SessionStatusData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/session/status" +} + +export type SessionStatusErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type SessionStatusError = SessionStatusErrors[keyof SessionStatusErrors] + +export type SessionStatusResponses = { + /** + * Get session status + */ + 200: { + [key: string]: SessionStatus + } +} + +export type SessionStatusResponse = SessionStatusResponses[keyof SessionStatusResponses] + +export type SessionDeleteData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}" +} + +export type SessionDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionDeleteError = SessionDeleteErrors[keyof SessionDeleteErrors] + +export type SessionDeleteResponses = { + /** + * Successfully deleted session + */ + 200: boolean +} + +export type SessionDeleteResponse = SessionDeleteResponses[keyof SessionDeleteResponses] + +export type SessionGetData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}" +} + +export type SessionGetErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionGetError = SessionGetErrors[keyof SessionGetErrors] + +export type SessionGetResponses = { + /** + * Get session + */ + 200: Session +} + +export type SessionGetResponse = SessionGetResponses[keyof SessionGetResponses] + +export type SessionUpdateData = { + body?: { + title?: string + } + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}" +} + +export type SessionUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionUpdateError = SessionUpdateErrors[keyof SessionUpdateErrors] + +export type SessionUpdateResponses = { + /** + * Successfully updated session + */ + 200: Session +} + +export type SessionUpdateResponse = SessionUpdateResponses[keyof SessionUpdateResponses] + +export type SessionChildrenData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/children" +} + +export type SessionChildrenErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionChildrenError = SessionChildrenErrors[keyof SessionChildrenErrors] + +export type SessionChildrenResponses = { + /** + * List of children + */ + 200: Array<Session> +} + +export type SessionChildrenResponse = SessionChildrenResponses[keyof SessionChildrenResponses] + +export type SessionTodoData = { + body?: never + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/todo" +} + +export type SessionTodoErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionTodoError = SessionTodoErrors[keyof SessionTodoErrors] + +export type SessionTodoResponses = { + /** + * Todo list + */ + 200: Array<Todo> +} + +export type SessionTodoResponse = SessionTodoResponses[keyof SessionTodoResponses] + +export type SessionInitData = { + body?: { + modelID: string + providerID: string + messageID: string + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/init" +} + +export type SessionInitErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionInitError = SessionInitErrors[keyof SessionInitErrors] + +export type SessionInitResponses = { + /** + * 200 + */ + 200: boolean +} + +export type SessionInitResponse = SessionInitResponses[keyof SessionInitResponses] + +export type SessionForkData = { + body?: { + messageID?: string + } + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/fork" +} + +export type SessionForkResponses = { + /** + * 200 + */ + 200: Session +} + +export type SessionForkResponse = SessionForkResponses[keyof SessionForkResponses] + +export type SessionAbortData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/abort" +} + +export type SessionAbortErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionAbortError = SessionAbortErrors[keyof SessionAbortErrors] + +export type SessionAbortResponses = { + /** + * Aborted session + */ + 200: boolean +} + +export type SessionAbortResponse = SessionAbortResponses[keyof SessionAbortResponses] + +export type SessionUnshareData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/share" +} + +export type SessionUnshareErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionUnshareError = SessionUnshareErrors[keyof SessionUnshareErrors] + +export type SessionUnshareResponses = { + /** + * Successfully unshared session + */ + 200: Session +} + +export type SessionUnshareResponse = SessionUnshareResponses[keyof SessionUnshareResponses] + +export type SessionShareData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/share" +} + +export type SessionShareErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionShareError = SessionShareErrors[keyof SessionShareErrors] + +export type SessionShareResponses = { + /** + * Successfully shared session + */ + 200: Session +} + +export type SessionShareResponse = SessionShareResponses[keyof SessionShareResponses] + +export type SessionDiffData = { + body?: never + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + messageID?: string + } + url: "/session/{sessionID}/diff" +} + +export type SessionDiffErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionDiffError = SessionDiffErrors[keyof SessionDiffErrors] + +export type SessionDiffResponses = { + /** + * List of diffs + */ + 200: Array<FileDiff> +} + +export type SessionDiffResponse = SessionDiffResponses[keyof SessionDiffResponses] + +export type SessionSummarizeData = { + body?: { + providerID: string + modelID: string + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/summarize" +} + +export type SessionSummarizeErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionSummarizeError = SessionSummarizeErrors[keyof SessionSummarizeErrors] + +export type SessionSummarizeResponses = { + /** + * Summarized session + */ + 200: boolean +} + +export type SessionSummarizeResponse = SessionSummarizeResponses[keyof SessionSummarizeResponses] + +export type SessionMessagesData = { + body?: never + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + limit?: number + } + url: "/session/{sessionID}/message" +} + +export type SessionMessagesErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionMessagesError = SessionMessagesErrors[keyof SessionMessagesErrors] + +export type SessionMessagesResponses = { + /** + * List of messages + */ + 200: Array<{ + info: Message + parts: Array<Part> + }> +} + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses] + +export type SessionPromptData = { + body?: { + messageID?: string + model?: { + providerID: string + modelID: string + } + agent?: string + noReply?: boolean + system?: string + tools?: { + [key: string]: boolean + } + parts: Array<TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput> + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/message" +} + +export type SessionPromptErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionPromptError = SessionPromptErrors[keyof SessionPromptErrors] + +export type SessionPromptResponses = { + /** + * Created message + */ + 200: { + info: AssistantMessage + parts: Array<Part> + } +} + +export type SessionPromptResponse = SessionPromptResponses[keyof SessionPromptResponses] + +export type SessionMessageData = { + body?: never + path: { + /** + * Session ID + */ + sessionID: string + /** + * Message ID + */ + messageID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/message/{messageID}" +} + +export type SessionMessageErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionMessageError = SessionMessageErrors[keyof SessionMessageErrors] + +export type SessionMessageResponses = { + /** + * Message + */ + 200: { + info: Message + parts: Array<Part> + } +} + +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses] + +export type SessionPromptAsyncData = { + body?: { + messageID?: string + model?: { + providerID: string + modelID: string + } + agent?: string + noReply?: boolean + system?: string + tools?: { + [key: string]: boolean + } + parts: Array<TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput> + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/prompt_async" +} + +export type SessionPromptAsyncErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionPromptAsyncError = SessionPromptAsyncErrors[keyof SessionPromptAsyncErrors] + +export type SessionPromptAsyncResponses = { + /** + * Prompt accepted + */ + 204: void +} + +export type SessionPromptAsyncResponse = SessionPromptAsyncResponses[keyof SessionPromptAsyncResponses] + +export type SessionCommandData = { + body?: { + messageID?: string + agent?: string + model?: string + arguments: string + command: string + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/command" +} + +export type SessionCommandErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionCommandError = SessionCommandErrors[keyof SessionCommandErrors] + +export type SessionCommandResponses = { + /** + * Created message + */ + 200: { + info: AssistantMessage + parts: Array<Part> + } +} + +export type SessionCommandResponse = SessionCommandResponses[keyof SessionCommandResponses] + +export type SessionShellData = { + body?: { + agent: string + model?: { + providerID: string + modelID: string + } + command: string + } + path: { + /** + * Session ID + */ + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/shell" +} + +export type SessionShellErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionShellError = SessionShellErrors[keyof SessionShellErrors] + +export type SessionShellResponses = { + /** + * Created message + */ + 200: AssistantMessage +} + +export type SessionShellResponse = SessionShellResponses[keyof SessionShellResponses] + +export type SessionRevertData = { + body?: { + messageID: string + partID?: string + } + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/revert" +} + +export type SessionRevertErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionRevertError = SessionRevertErrors[keyof SessionRevertErrors] + +export type SessionRevertResponses = { + /** + * Updated session + */ + 200: Session +} + +export type SessionRevertResponse = SessionRevertResponses[keyof SessionRevertResponses] + +export type SessionUnrevertData = { + body?: never + path: { + sessionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/unrevert" +} + +export type SessionUnrevertErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionUnrevertError = SessionUnrevertErrors[keyof SessionUnrevertErrors] + +export type SessionUnrevertResponses = { + /** + * Updated session + */ + 200: Session +} + +export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses] + +export type PermissionRespondData = { + body?: { + response: "once" | "always" | "reject" + } + path: { + sessionID: string + permissionID: string + } + query?: { + directory?: string + } + url: "/session/{sessionID}/permissions/{permissionID}" +} + +export type PermissionRespondErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type PermissionRespondError = PermissionRespondErrors[keyof PermissionRespondErrors] + +export type PermissionRespondResponses = { + /** + * Permission processed successfully + */ + 200: boolean +} + +export type PermissionRespondResponse = PermissionRespondResponses[keyof PermissionRespondResponses] + +export type CommandListData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/command" +} + +export type CommandListResponses = { + /** + * List of commands + */ + 200: Array<Command> +} + +export type CommandListResponse = CommandListResponses[keyof CommandListResponses] + +export type ConfigProvidersData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/config/providers" +} + +export type ConfigProvidersResponses = { + /** + * List of providers + */ + 200: { + providers: Array<Provider> + default: { + [key: string]: string + } + } +} + +export type ConfigProvidersResponse = ConfigProvidersResponses[keyof ConfigProvidersResponses] + +export type ProviderListData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/provider" +} + +export type ProviderListResponses = { + /** + * List of providers + */ + 200: { + all: Array<{ + api?: string + name: string + env: Array<string> + id: string + npm?: string + models: { + [key: string]: { + id: string + name: string + release_date: string + attachment: boolean + reasoning: boolean + temperature: boolean + tool_call: boolean + cost?: { + input: number + output: number + cache_read?: number + cache_write?: number + context_over_200k?: { + input: number + output: number + cache_read?: number + cache_write?: number + } + } + limit: { + context: number + output: number + } + modalities?: { + input: Array<"text" | "audio" | "image" | "video" | "pdf"> + output: Array<"text" | "audio" | "image" | "video" | "pdf"> + } + experimental?: boolean + status?: "alpha" | "beta" | "deprecated" + options: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + provider?: { + npm: string + } + } + } + }> + default: { + [key: string]: string + } + connected: Array<string> + } +} + +export type ProviderListResponse = ProviderListResponses[keyof ProviderListResponses] + +export type ProviderAuthData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/provider/auth" +} + +export type ProviderAuthResponses = { + /** + * Provider auth methods + */ + 200: { + [key: string]: Array<ProviderAuthMethod> + } +} + +export type ProviderAuthResponse = ProviderAuthResponses[keyof ProviderAuthResponses] + +export type ProviderOauthAuthorizeData = { + body?: { + /** + * Auth method index + */ + method: number + } + path: { + /** + * Provider ID + */ + providerID: string + } + query?: { + directory?: string + } + url: "/provider/{providerID}/oauth/authorize" +} + +export type ProviderOauthAuthorizeErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type ProviderOauthAuthorizeError = ProviderOauthAuthorizeErrors[keyof ProviderOauthAuthorizeErrors] + +export type ProviderOauthAuthorizeResponses = { + /** + * Authorization URL and method + */ + 200: ProviderAuthAuthorization +} + +export type ProviderOauthAuthorizeResponse = ProviderOauthAuthorizeResponses[keyof ProviderOauthAuthorizeResponses] + +export type ProviderOauthCallbackData = { + body?: { + /** + * Auth method index + */ + method: number + /** + * OAuth authorization code + */ + code?: string + } + path: { + /** + * Provider ID + */ + providerID: string + } + query?: { + directory?: string + } + url: "/provider/{providerID}/oauth/callback" +} + +export type ProviderOauthCallbackErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type ProviderOauthCallbackError = ProviderOauthCallbackErrors[keyof ProviderOauthCallbackErrors] + +export type ProviderOauthCallbackResponses = { + /** + * OAuth callback processed successfully + */ + 200: boolean +} + +export type ProviderOauthCallbackResponse = ProviderOauthCallbackResponses[keyof ProviderOauthCallbackResponses] + +export type FindTextData = { + body?: never + path?: never + query: { + directory?: string + pattern: string + } + url: "/find" +} + +export type FindTextResponses = { + /** + * Matches + */ + 200: Array<{ + path: { + text: string + } + lines: { + text: string + } + line_number: number + absolute_offset: number + submatches: Array<{ + match: { + text: string + } + start: number + end: number + }> + }> +} + +export type FindTextResponse = FindTextResponses[keyof FindTextResponses] + +export type FindFilesData = { + body?: never + path?: never + query: { + directory?: string + query: string + dirs?: "true" | "false" + } + url: "/find/file" +} + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array<string> +} + +export type FindFilesResponse = FindFilesResponses[keyof FindFilesResponses] + +export type FindSymbolsData = { + body?: never + path?: never + query: { + directory?: string + query: string + } + url: "/find/symbol" +} + +export type FindSymbolsResponses = { + /** + * Symbols + */ + 200: Array<Symbol> +} + +export type FindSymbolsResponse = FindSymbolsResponses[keyof FindSymbolsResponses] + +export type FileListData = { + body?: never + path?: never + query: { + directory?: string + path: string + } + url: "/file" +} + +export type FileListResponses = { + /** + * Files and directories + */ + 200: Array<FileNode> +} + +export type FileListResponse = FileListResponses[keyof FileListResponses] + +export type FileReadData = { + body?: never + path?: never + query: { + directory?: string + path: string + } + url: "/file/content" +} + +export type FileReadResponses = { + /** + * File content + */ + 200: FileContent +} + +export type FileReadResponse = FileReadResponses[keyof FileReadResponses] + +export type FileStatusData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/file/status" +} + +export type FileStatusResponses = { + /** + * File status + */ + 200: Array<File> +} + +export type FileStatusResponse = FileStatusResponses[keyof FileStatusResponses] + +export type AppLogData = { + body?: { + /** + * Service name for the log entry + */ + service: string + /** + * Log level + */ + level: "debug" | "info" | "error" | "warn" + /** + * Log message + */ + message: string + /** + * Additional metadata for the log entry + */ + extra?: { + [key: string]: unknown + } + } + path?: never + query?: { + directory?: string + } + url: "/log" +} + +export type AppLogErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type AppLogError = AppLogErrors[keyof AppLogErrors] + +export type AppLogResponses = { + /** + * Log entry written successfully + */ + 200: boolean +} + +export type AppLogResponse = AppLogResponses[keyof AppLogResponses] + +export type AppAgentsData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/agent" +} + +export type AppAgentsResponses = { + /** + * List of agents + */ + 200: Array<Agent> +} + +export type AppAgentsResponse = AppAgentsResponses[keyof AppAgentsResponses] + +export type McpStatusData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/mcp" +} + +export type McpStatusResponses = { + /** + * MCP server status + */ + 200: { + [key: string]: McpStatus + } +} + +export type McpStatusResponse = McpStatusResponses[keyof McpStatusResponses] + +export type McpAddData = { + body?: { + name: string + config: McpLocalConfig | McpRemoteConfig + } + path?: never + query?: { + directory?: string + } + url: "/mcp" +} + +export type McpAddErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type McpAddError = McpAddErrors[keyof McpAddErrors] + +export type McpAddResponses = { + /** + * MCP server added successfully + */ + 200: { + [key: string]: McpStatus + } +} + +export type McpAddResponse = McpAddResponses[keyof McpAddResponses] + +export type McpAuthRemoveData = { + body?: never + path: { + name: string + } + query?: { + directory?: string + } + url: "/mcp/{name}/auth" +} + +export type McpAuthRemoveErrors = { + /** + * Not found + */ + 404: NotFoundError +} + +export type McpAuthRemoveError = McpAuthRemoveErrors[keyof McpAuthRemoveErrors] + +export type McpAuthRemoveResponses = { + /** + * OAuth credentials removed + */ + 200: { + success: true + } +} + +export type McpAuthRemoveResponse = McpAuthRemoveResponses[keyof McpAuthRemoveResponses] + +export type McpAuthStartData = { + body?: never + path: { + name: string + } + query?: { + directory?: string + } + url: "/mcp/{name}/auth" +} + +export type McpAuthStartErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type McpAuthStartError = McpAuthStartErrors[keyof McpAuthStartErrors] + +export type McpAuthStartResponses = { + /** + * OAuth flow started + */ + 200: { + /** + * URL to open in browser for authorization + */ + authorizationUrl: string + } +} + +export type McpAuthStartResponse = McpAuthStartResponses[keyof McpAuthStartResponses] + +export type McpAuthCallbackData = { + body?: { + /** + * Authorization code from OAuth callback + */ + code: string + } + path: { + name: string + } + query?: { + directory?: string + } + url: "/mcp/{name}/auth/callback" +} + +export type McpAuthCallbackErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type McpAuthCallbackError = McpAuthCallbackErrors[keyof McpAuthCallbackErrors] + +export type McpAuthCallbackResponses = { + /** + * OAuth authentication completed + */ + 200: McpStatus +} + +export type McpAuthCallbackResponse = McpAuthCallbackResponses[keyof McpAuthCallbackResponses] + +export type McpAuthAuthenticateData = { + body?: never + path: { + name: string + } + query?: { + directory?: string + } + url: "/mcp/{name}/auth/authenticate" +} + +export type McpAuthAuthenticateErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type McpAuthAuthenticateError = McpAuthAuthenticateErrors[keyof McpAuthAuthenticateErrors] + +export type McpAuthAuthenticateResponses = { + /** + * OAuth authentication completed + */ + 200: McpStatus +} + +export type McpAuthAuthenticateResponse = McpAuthAuthenticateResponses[keyof McpAuthAuthenticateResponses] + +export type LspStatusData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/lsp" +} + +export type LspStatusResponses = { + /** + * LSP server status + */ + 200: Array<LspStatus> +} + +export type LspStatusResponse = LspStatusResponses[keyof LspStatusResponses] + +export type FormatterStatusData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/formatter" +} + +export type FormatterStatusResponses = { + /** + * Formatter status + */ + 200: Array<FormatterStatus> +} + +export type FormatterStatusResponse = FormatterStatusResponses[keyof FormatterStatusResponses] + +export type TuiAppendPromptData = { + body?: { + text: string + } + path?: never + query?: { + directory?: string + } + url: "/tui/append-prompt" +} + +export type TuiAppendPromptErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type TuiAppendPromptError = TuiAppendPromptErrors[keyof TuiAppendPromptErrors] + +export type TuiAppendPromptResponses = { + /** + * Prompt processed successfully + */ + 200: boolean +} + +export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPromptResponses] + +export type TuiOpenHelpData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/open-help" +} + +export type TuiOpenHelpResponses = { + /** + * Help dialog opened successfully + */ + 200: boolean +} + +export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponses] + +export type TuiOpenSessionsData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/open-sessions" +} + +export type TuiOpenSessionsResponses = { + /** + * Session dialog opened successfully + */ + 200: boolean +} + +export type TuiOpenSessionsResponse = TuiOpenSessionsResponses[keyof TuiOpenSessionsResponses] + +export type TuiOpenThemesData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/open-themes" +} + +export type TuiOpenThemesResponses = { + /** + * Theme dialog opened successfully + */ + 200: boolean +} + +export type TuiOpenThemesResponse = TuiOpenThemesResponses[keyof TuiOpenThemesResponses] + +export type TuiOpenModelsData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/open-models" +} + +export type TuiOpenModelsResponses = { + /** + * Model dialog opened successfully + */ + 200: boolean +} + +export type TuiOpenModelsResponse = TuiOpenModelsResponses[keyof TuiOpenModelsResponses] + +export type TuiSubmitPromptData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/submit-prompt" +} + +export type TuiSubmitPromptResponses = { + /** + * Prompt submitted successfully + */ + 200: boolean +} + +export type TuiSubmitPromptResponse = TuiSubmitPromptResponses[keyof TuiSubmitPromptResponses] + +export type TuiClearPromptData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/clear-prompt" +} + +export type TuiClearPromptResponses = { + /** + * Prompt cleared successfully + */ + 200: boolean +} + +export type TuiClearPromptResponse = TuiClearPromptResponses[keyof TuiClearPromptResponses] + +export type TuiExecuteCommandData = { + body?: { + command: string + } + path?: never + query?: { + directory?: string + } + url: "/tui/execute-command" +} + +export type TuiExecuteCommandErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type TuiExecuteCommandError = TuiExecuteCommandErrors[keyof TuiExecuteCommandErrors] + +export type TuiExecuteCommandResponses = { + /** + * Command executed successfully + */ + 200: boolean +} + +export type TuiExecuteCommandResponse = TuiExecuteCommandResponses[keyof TuiExecuteCommandResponses] + +export type TuiShowToastData = { + body?: { + title?: string + message: string + variant: "info" | "success" | "warning" | "error" + /** + * Duration in milliseconds + */ + duration?: number + } + path?: never + query?: { + directory?: string + } + url: "/tui/show-toast" +} + +export type TuiShowToastResponses = { + /** + * Toast notification shown successfully + */ + 200: boolean +} + +export type TuiShowToastResponse = TuiShowToastResponses[keyof TuiShowToastResponses] + +export type TuiPublishData = { + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow + path?: never + query?: { + directory?: string + } + url: "/tui/publish" +} + +export type TuiPublishErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type TuiPublishError = TuiPublishErrors[keyof TuiPublishErrors] + +export type TuiPublishResponses = { + /** + * Event published successfully + */ + 200: boolean +} + +export type TuiPublishResponse = TuiPublishResponses[keyof TuiPublishResponses] + +export type TuiControlNextData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/tui/control/next" +} + +export type TuiControlNextResponses = { + /** + * Next TUI request + */ + 200: { + path: string + body: unknown + } +} + +export type TuiControlNextResponse = TuiControlNextResponses[keyof TuiControlNextResponses] + +export type TuiControlResponseData = { + body?: unknown + path?: never + query?: { + directory?: string + } + url: "/tui/control/response" +} + +export type TuiControlResponseResponses = { + /** + * Response submitted successfully + */ + 200: boolean +} + +export type TuiControlResponseResponse = TuiControlResponseResponses[keyof TuiControlResponseResponses] + +export type AuthSetData = { + body?: Auth + path: { + providerID: string + } + query?: { + directory?: string + } + url: "/auth/{providerID}" +} + +export type AuthSetErrors = { + /** + * Bad request + */ + 400: BadRequestError +} + +export type AuthSetError = AuthSetErrors[keyof AuthSetErrors] + +export type AuthSetResponses = { + /** + * Successfully set authentication credentials + */ + 200: boolean +} + +export type AuthSetResponse = AuthSetResponses[keyof AuthSetResponses] + +export type EventSubscribeData = { + body?: never + path?: never + query?: { + directory?: string + } + url: "/event" +} + +export type EventSubscribeResponses = { + /** + * Event stream + */ + 200: Event +} + +export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses] diff --git a/packages/sdk/js/src/v2/index.ts b/packages/sdk/js/src/v2/index.ts new file mode 100644 index 000000000..d044f5ad6 --- /dev/null +++ b/packages/sdk/js/src/v2/index.ts @@ -0,0 +1,21 @@ +export * from "./client.js" +export * from "./server.js" + +import { createOpencodeClient } from "./client.js" +import { createOpencodeServer } from "./server.js" +import type { ServerOptions } from "./server.js" + +export async function createOpencode(options?: ServerOptions) { + const server = await createOpencodeServer({ + ...options, + }) + + const client = createOpencodeClient({ + baseUrl: server.url, + }) + + return { + client, + server, + } +} diff --git a/packages/sdk/js/src/v2/server.ts b/packages/sdk/js/src/v2/server.ts new file mode 100644 index 000000000..a09e14ab2 --- /dev/null +++ b/packages/sdk/js/src/v2/server.ts @@ -0,0 +1,120 @@ +import { spawn } from "node:child_process" +import { type Config } from "./gen/types.gen.js" + +export type ServerOptions = { + hostname?: string + port?: number + signal?: AbortSignal + timeout?: number + config?: Config +} + +export type TuiOptions = { + project?: string + model?: string + session?: string + agent?: string + signal?: AbortSignal + config?: Config +} + +export async function createOpencodeServer(options?: ServerOptions) { + options = Object.assign( + { + hostname: "127.0.0.1", + port: 4096, + timeout: 5000, + }, + options ?? {}, + ) + + const proc = spawn(`opencode`, [`serve`, `--hostname=${options.hostname}`, `--port=${options.port}`], { + signal: options.signal, + env: { + ...process.env, + OPENCODE_CONFIG_CONTENT: JSON.stringify(options.config ?? {}), + }, + }) + + const url = await new Promise<string>((resolve, reject) => { + const id = setTimeout(() => { + reject(new Error(`Timeout waiting for server to start after ${options.timeout}ms`)) + }, options.timeout) + let output = "" + proc.stdout?.on("data", (chunk) => { + output += chunk.toString() + const lines = output.split("\n") + for (const line of lines) { + if (line.startsWith("opencode server listening")) { + const match = line.match(/on\s+(https?:\/\/[^\s]+)/) + if (!match) { + throw new Error(`Failed to parse server url from output: ${line}`) + } + clearTimeout(id) + resolve(match[1]!) + return + } + } + }) + proc.stderr?.on("data", (chunk) => { + output += chunk.toString() + }) + proc.on("exit", (code) => { + clearTimeout(id) + let msg = `Server exited with code ${code}` + if (output.trim()) { + msg += `\nServer output: ${output}` + } + reject(new Error(msg)) + }) + proc.on("error", (error) => { + clearTimeout(id) + reject(error) + }) + if (options.signal) { + options.signal.addEventListener("abort", () => { + clearTimeout(id) + reject(new Error("Aborted")) + }) + } + }) + + return { + url, + close() { + proc.kill() + }, + } +} + +export function createOpencodeTui(options?: TuiOptions) { + const args = [] + + if (options?.project) { + args.push(`--project=${options.project}`) + } + if (options?.model) { + args.push(`--model=${options.model}`) + } + if (options?.session) { + args.push(`--session=${options.session}`) + } + if (options?.agent) { + args.push(`--agent=${options.agent}`) + } + + const proc = spawn(`opencode`, args, { + signal: options?.signal, + stdio: "inherit", + env: { + ...process.env, + OPENCODE_CONFIG_CONTENT: JSON.stringify(options?.config ?? {}), + }, + }) + + return { + close() { + proc.kill() + }, + } +} diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 96675912d..b74f1a034 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -181,7 +181,7 @@ } } }, - "/pty/{id}": { + "/pty/{ptyID}": { "get": { "operationId": "pty.get", "parameters": [ @@ -194,7 +194,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -237,7 +237,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -286,7 +286,10 @@ "type": "number" } }, - "required": ["rows", "cols"] + "required": [ + "rows", + "cols" + ] } } } @@ -306,7 +309,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -338,7 +341,7 @@ } } }, - "/pty/{id}/connect": { + "/pty/{ptyID}/connect": { "get": { "operationId": "pty.connect", "parameters": [ @@ -351,7 +354,7 @@ }, { "in": "path", - "name": "id", + "name": "ptyID", "schema": { "type": "string" }, @@ -751,7 +754,7 @@ } } }, - "/session/{id}": { + "/session/{sessionID}": { "get": { "operationId": "session.get", "parameters": [ @@ -764,7 +767,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -818,7 +821,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -872,7 +875,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -928,7 +931,7 @@ } } }, - "/session/{id}/children": { + "/session/{sessionID}/children": { "get": { "operationId": "session.children", "parameters": [ @@ -941,7 +944,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -987,7 +990,7 @@ } } }, - "/session/{id}/todo": { + "/session/{sessionID}/todo": { "get": { "operationId": "session.todo", "parameters": [ @@ -1000,7 +1003,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1046,7 +1049,7 @@ } } }, - "/session/{id}/init": { + "/session/{sessionID}/init": { "post": { "operationId": "session.init", "parameters": [ @@ -1059,7 +1062,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1117,14 +1120,18 @@ "pattern": "^msg.*" } }, - "required": ["modelID", "providerID", "messageID"] + "required": [ + "modelID", + "providerID", + "messageID" + ] } } } } } }, - "/session/{id}/fork": { + "/session/{sessionID}/fork": { "post": { "operationId": "session.fork", "parameters": [ @@ -1137,7 +1144,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -1175,7 +1182,7 @@ } } }, - "/session/{id}/abort": { + "/session/{sessionID}/abort": { "post": { "operationId": "session.abort", "parameters": [ @@ -1188,7 +1195,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1230,7 +1237,7 @@ } } }, - "/session/{id}/share": { + "/session/{sessionID}/share": { "post": { "operationId": "session.share", "parameters": [ @@ -1243,7 +1250,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1296,7 +1303,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string", "pattern": "^ses.*" @@ -1339,7 +1346,7 @@ } } }, - "/session/{id}/diff": { + "/session/{sessionID}/diff": { "get": { "operationId": "session.diff", "parameters": [ @@ -1352,7 +1359,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1406,7 +1413,7 @@ } } }, - "/session/{id}/summarize": { + "/session/{sessionID}/summarize": { "post": { "operationId": "session.summarize", "parameters": [ @@ -1419,7 +1426,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1473,14 +1480,17 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] } } } } } }, - "/session/{id}/message": { + "/session/{sessionID}/message": { "get": { "operationId": "session.messages", "parameters": [ @@ -1493,7 +1503,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1529,7 +1539,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1569,7 +1582,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1596,7 +1609,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1642,7 +1658,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "agent": { "type": "string" @@ -1682,14 +1701,16 @@ } } }, - "required": ["parts"] + "required": [ + "parts" + ] } } } } } }, - "/session/{id}/message/{messageID}": { + "/session/{sessionID}/message/{messageID}": { "get": { "operationId": "session.message", "parameters": [ @@ -1702,7 +1723,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1738,7 +1759,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1766,7 +1790,7 @@ } } }, - "/session/{id}/prompt_async": { + "/session/{sessionID}/prompt_async": { "post": { "operationId": "session.prompt_async", "parameters": [ @@ -1779,7 +1803,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1833,7 +1857,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "agent": { "type": "string" @@ -1873,14 +1900,16 @@ } } }, - "required": ["parts"] + "required": [ + "parts" + ] } } } } } }, - "/session/{id}/command": { + "/session/{sessionID}/command": { "post": { "operationId": "session.command", "parameters": [ @@ -1893,7 +1922,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -1920,7 +1949,10 @@ } } }, - "required": ["info", "parts"] + "required": [ + "info", + "parts" + ] } } } @@ -1969,14 +2001,17 @@ "type": "string" } }, - "required": ["arguments", "command"] + "required": [ + "arguments", + "command" + ] } } } } } }, - "/session/{id}/shell": { + "/session/{sessionID}/shell": { "post": { "operationId": "session.shell", "parameters": [ @@ -1989,7 +2024,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2049,20 +2084,26 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "command": { "type": "string" } }, - "required": ["agent", "command"] + "required": [ + "agent", + "command" + ] } } } } } }, - "/session/{id}/revert": { + "/session/{sessionID}/revert": { "post": { "operationId": "session.revert", "parameters": [ @@ -2075,7 +2116,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2130,14 +2171,16 @@ "pattern": "^prt.*" } }, - "required": ["messageID"] + "required": [ + "messageID" + ] } } } } } }, - "/session/{id}/unrevert": { + "/session/{sessionID}/unrevert": { "post": { "operationId": "session.unrevert", "parameters": [ @@ -2150,7 +2193,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2192,9 +2235,9 @@ } } }, - "/session/{id}/permissions/{permissionID}": { + "/session/{sessionID}/permissions/{permissionID}": { "post": { - "operationId": "postSession:idPermissions:permissionID", + "operationId": "permission.respond", "parameters": [ { "in": "query", @@ -2205,7 +2248,7 @@ }, { "in": "path", - "name": "id", + "name": "sessionID", "schema": { "type": "string" }, @@ -2261,10 +2304,16 @@ "properties": { "response": { "type": "string", - "enum": ["once", "always", "reject"] + "enum": [ + "once", + "always", + "reject" + ] } }, - "required": ["response"] + "required": [ + "response" + ] } } } @@ -2338,7 +2387,10 @@ } } }, - "required": ["providers", "default"] + "required": [ + "providers", + "default" + ] } } } @@ -2450,10 +2502,16 @@ "type": "number" } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "limit": { "type": "object", @@ -2465,7 +2523,10 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "modalities": { "type": "object", @@ -2474,25 +2535,44 @@ "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, "output": { "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "experimental": { "type": "boolean" }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated"] + "enum": [ + "alpha", + "beta", + "deprecated" + ] }, "options": { "type": "object", @@ -2517,7 +2597,9 @@ "type": "string" } }, - "required": ["npm"] + "required": [ + "npm" + ] } }, "required": [ @@ -2534,7 +2616,12 @@ } } }, - "required": ["name", "env", "id", "models"] + "required": [ + "name", + "env", + "id", + "models" + ] } }, "default": { @@ -2553,7 +2640,11 @@ } } }, - "required": ["all", "default", "connected"] + "required": [ + "all", + "default", + "connected" + ] } } } @@ -2597,7 +2688,7 @@ } } }, - "/provider/{id}/oauth/authorize": { + "/provider/{providerID}/oauth/authorize": { "post": { "operationId": "provider.oauth.authorize", "parameters": [ @@ -2610,7 +2701,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -2652,14 +2743,16 @@ "type": "number" } }, - "required": ["method"] + "required": [ + "method" + ] } } } } } }, - "/provider/{id}/oauth/callback": { + "/provider/{providerID}/oauth/callback": { "post": { "operationId": "provider.oauth.callback", "parameters": [ @@ -2672,7 +2765,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -2718,7 +2811,9 @@ "type": "string" } }, - "required": ["method"] + "required": [ + "method" + ] } } } @@ -2763,7 +2858,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "lines": { "type": "object", @@ -2772,7 +2869,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "line_number": { "type": "number" @@ -2792,7 +2891,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] }, "start": { "type": "number" @@ -2801,11 +2902,21 @@ "type": "number" } }, - "required": ["match", "start", "end"] + "required": [ + "match", + "start", + "end" + ] } } }, - "required": ["path", "lines", "line_number", "absolute_offset", "submatches"] + "required": [ + "path", + "lines", + "line_number", + "absolute_offset", + "submatches" + ] } } } @@ -2838,7 +2949,10 @@ "name": "dirs", "schema": { "type": "string", - "enum": ["true", "false"] + "enum": [ + "true", + "false" + ] } } ], @@ -3049,7 +3163,12 @@ "level": { "description": "Log level", "type": "string", - "enum": ["debug", "info", "error", "warn"] + "enum": [ + "debug", + "info", + "error", + "warn" + ] }, "message": { "description": "Log message", @@ -3064,7 +3183,11 @@ "additionalProperties": {} } }, - "required": ["service", "level", "message"] + "required": [ + "service", + "level", + "message" + ] } } } @@ -3193,7 +3316,10 @@ ] } }, - "required": ["name", "config"] + "required": [ + "name", + "config" + ] } } } @@ -3234,7 +3360,9 @@ "type": "string" } }, - "required": ["authorizationUrl"] + "required": [ + "authorizationUrl" + ] } } } @@ -3294,7 +3422,9 @@ "const": true } }, - "required": ["success"] + "required": [ + "success" + ] } } } @@ -3376,7 +3506,9 @@ "type": "string" } }, - "required": ["code"] + "required": [ + "code" + ] } } } @@ -3543,7 +3675,9 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] } } } @@ -3757,7 +3891,9 @@ "type": "string" } }, - "required": ["command"] + "required": [ + "command" + ] } } } @@ -3803,7 +3939,12 @@ }, "variant": { "type": "string", - "enum": ["info", "success", "warning", "error"] + "enum": [ + "info", + "success", + "warning", + "error" + ] }, "duration": { "description": "Duration in milliseconds", @@ -3811,7 +3952,10 @@ "type": "number" } }, - "required": ["message", "variant"] + "required": [ + "message", + "variant" + ] } } } @@ -3900,7 +4044,10 @@ }, "body": {} }, - "required": ["path", "body"] + "required": [ + "path", + "body" + ] } } } @@ -3942,7 +4089,7 @@ } } }, - "/auth/{id}": { + "/auth/{providerID}": { "put": { "operationId": "auth.set", "parameters": [ @@ -3955,7 +4102,7 @@ }, { "in": "path", - "name": "id", + "name": "providerID", "schema": { "type": "string" }, @@ -4040,10 +4187,15 @@ "type": "string" } }, - "required": ["directory"] + "required": [ + "directory" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.installation.updated": { "type": "object", @@ -4059,10 +4211,15 @@ "type": "string" } }, - "required": ["version"] + "required": [ + "version" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.installation.update-available": { "type": "object", @@ -4078,10 +4235,15 @@ "type": "string" } }, - "required": ["version"] + "required": [ + "version" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.lsp.client.diagnostics": { "type": "object", @@ -4100,10 +4262,16 @@ "type": "string" } }, - "required": ["serverID", "path"] + "required": [ + "serverID", + "path" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.lsp.updated": { "type": "object", @@ -4117,7 +4285,10 @@ "properties": {} } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "FileDiff": { "type": "object", @@ -4138,7 +4309,13 @@ "type": "number" } }, - "required": ["file", "before", "after", "additions", "deletions"] + "required": [ + "file", + "before", + "after", + "additions", + "deletions" + ] }, "UserMessage": { "type": "object", @@ -4160,7 +4337,9 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] }, "summary": { "type": "object", @@ -4178,7 +4357,9 @@ } } }, - "required": ["diffs"] + "required": [ + "diffs" + ] }, "agent": { "type": "string" @@ -4193,7 +4374,10 @@ "type": "string" } }, - "required": ["providerID", "modelID"] + "required": [ + "providerID", + "modelID" + ] }, "system": { "type": "string" @@ -4208,7 +4392,14 @@ } } }, - "required": ["id", "sessionID", "role", "time", "agent", "model"] + "required": [ + "id", + "sessionID", + "role", + "time", + "agent", + "model" + ] }, "ProviderAuthError": { "type": "object", @@ -4227,10 +4418,16 @@ "type": "string" } }, - "required": ["providerID", "message"] + "required": [ + "providerID", + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "UnknownError": { "type": "object", @@ -4246,10 +4443,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "MessageOutputLengthError": { "type": "object", @@ -4263,7 +4465,10 @@ "properties": {} } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "MessageAbortedError": { "type": "object", @@ -4279,10 +4484,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "APIError": { "type": "object", @@ -4316,10 +4526,16 @@ "type": "string" } }, - "required": ["message", "isRetryable"] + "required": [ + "message", + "isRetryable" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "AssistantMessage": { "type": "object", @@ -4344,7 +4560,9 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] }, "error": { "anyOf": [ @@ -4387,7 +4605,10 @@ "type": "string" } }, - "required": ["cwd", "root"] + "required": [ + "cwd", + "root" + ] }, "summary": { "type": "boolean" @@ -4417,10 +4638,18 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "reasoning", "cache"] + "required": [ + "input", + "output", + "reasoning", + "cache" + ] }, "finish": { "type": "string" @@ -4464,10 +4693,15 @@ "$ref": "#/components/schemas/Message" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.message.removed": { "type": "object", @@ -4486,10 +4720,16 @@ "type": "string" } }, - "required": ["sessionID", "messageID"] + "required": [ + "sessionID", + "messageID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "TextPart": { "type": "object", @@ -4526,7 +4766,9 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] }, "metadata": { "type": "object", @@ -4536,7 +4778,13 @@ "additionalProperties": {} } }, - "required": ["id", "sessionID", "messageID", "type", "text"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "text" + ] }, "ReasoningPart": { "type": "object", @@ -4574,10 +4822,19 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "text", "time"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "text", + "time" + ] }, "FilePartSourceText": { "type": "object", @@ -4596,7 +4853,11 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] }, "FileSource": { "type": "object", @@ -4612,7 +4873,11 @@ "type": "string" } }, - "required": ["text", "type", "path"] + "required": [ + "text", + "type", + "path" + ] }, "Range": { "type": "object", @@ -4627,7 +4892,10 @@ "type": "number" } }, - "required": ["line", "character"] + "required": [ + "line", + "character" + ] }, "end": { "type": "object", @@ -4639,10 +4907,16 @@ "type": "number" } }, - "required": ["line", "character"] + "required": [ + "line", + "character" + ] } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] }, "SymbolSource": { "type": "object", @@ -4669,7 +4943,14 @@ "maximum": 9007199254740991 } }, - "required": ["text", "type", "path", "range", "name", "kind"] + "required": [ + "text", + "type", + "path", + "range", + "name", + "kind" + ] }, "FilePartSource": { "anyOf": [ @@ -4710,7 +4991,14 @@ "$ref": "#/components/schemas/FilePartSource" } }, - "required": ["id", "sessionID", "messageID", "type", "mime", "url"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "mime", + "url" + ] }, "ToolStatePending": { "type": "object", @@ -4730,7 +5018,11 @@ "type": "string" } }, - "required": ["status", "input", "raw"] + "required": [ + "status", + "input", + "raw" + ] }, "ToolStateRunning": { "type": "object", @@ -4763,10 +5055,16 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] } }, - "required": ["status", "input", "time"] + "required": [ + "status", + "input", + "time" + ] }, "ToolStateCompleted": { "type": "object", @@ -4808,7 +5106,10 @@ "type": "number" } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] }, "attachments": { "type": "array", @@ -4817,7 +5118,14 @@ } } }, - "required": ["status", "input", "output", "title", "metadata", "time"] + "required": [ + "status", + "input", + "output", + "title", + "metadata", + "time" + ] }, "ToolStateError": { "type": "object", @@ -4853,10 +5161,18 @@ "type": "number" } }, - "required": ["start", "end"] + "required": [ + "start", + "end" + ] } }, - "required": ["status", "input", "error", "time"] + "required": [ + "status", + "input", + "error", + "time" + ] }, "ToolState": { "anyOf": [ @@ -4907,7 +5223,15 @@ "additionalProperties": {} } }, - "required": ["id", "sessionID", "messageID", "type", "callID", "tool", "state"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "callID", + "tool", + "state" + ] }, "StepStartPart": { "type": "object", @@ -4929,7 +5253,12 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type"] + "required": [ + "id", + "sessionID", + "messageID", + "type" + ] }, "StepFinishPart": { "type": "object", @@ -4978,13 +5307,29 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "reasoning", "cache"] + "required": [ + "input", + "output", + "reasoning", + "cache" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "reason", "cost", "tokens"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "reason", + "cost", + "tokens" + ] }, "SnapshotPart": { "type": "object", @@ -5006,7 +5351,13 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type", "snapshot"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "snapshot" + ] }, "PatchPart": { "type": "object", @@ -5034,7 +5385,14 @@ } } }, - "required": ["id", "sessionID", "messageID", "type", "hash", "files"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "hash", + "files" + ] }, "AgentPart": { "type": "object", @@ -5072,10 +5430,20 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "name"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "name" + ] }, "RetryPart": { "type": "object", @@ -5106,10 +5474,20 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "sessionID", "messageID", "type", "attempt", "error", "time"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "attempt", + "error", + "time" + ] }, "CompactionPart": { "type": "object", @@ -5131,7 +5509,13 @@ "type": "boolean" } }, - "required": ["id", "sessionID", "messageID", "type", "auto"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "auto" + ] }, "Part": { "anyOf": [ @@ -5164,7 +5548,15 @@ "type": "string" } }, - "required": ["id", "sessionID", "messageID", "type", "prompt", "description", "agent"] + "required": [ + "id", + "sessionID", + "messageID", + "type", + "prompt", + "description", + "agent" + ] }, { "$ref": "#/components/schemas/ReasoningPart" @@ -5215,10 +5607,15 @@ "type": "string" } }, - "required": ["part"] + "required": [ + "part" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.message.part.removed": { "type": "object", @@ -5240,10 +5637,17 @@ "type": "string" } }, - "required": ["sessionID", "messageID", "partID"] + "required": [ + "sessionID", + "messageID", + "partID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Permission": { "type": "object", @@ -5293,10 +5697,20 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "type", "sessionID", "messageID", "title", "metadata", "time"] + "required": [ + "id", + "type", + "sessionID", + "messageID", + "title", + "metadata", + "time" + ] }, "Event.permission.updated": { "type": "object", @@ -5309,7 +5723,10 @@ "$ref": "#/components/schemas/Permission" } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.permission.replied": { "type": "object", @@ -5331,10 +5748,17 @@ "type": "string" } }, - "required": ["sessionID", "permissionID", "response"] + "required": [ + "sessionID", + "permissionID", + "response" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "SessionStatus": { "anyOf": [ @@ -5346,7 +5770,9 @@ "const": "idle" } }, - "required": ["type"] + "required": [ + "type" + ] }, { "type": "object", @@ -5365,7 +5791,12 @@ "type": "number" } }, - "required": ["type", "attempt", "message", "next"] + "required": [ + "type", + "attempt", + "message", + "next" + ] }, { "type": "object", @@ -5375,7 +5806,9 @@ "const": "busy" } }, - "required": ["type"] + "required": [ + "type" + ] } ] }, @@ -5396,10 +5829,16 @@ "$ref": "#/components/schemas/SessionStatus" } }, - "required": ["sessionID", "status"] + "required": [ + "sessionID", + "status" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.idle": { "type": "object", @@ -5415,10 +5854,15 @@ "type": "string" } }, - "required": ["sessionID"] + "required": [ + "sessionID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.compacted": { "type": "object", @@ -5434,10 +5878,15 @@ "type": "string" } }, - "required": ["sessionID"] + "required": [ + "sessionID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.file.edited": { "type": "object", @@ -5453,10 +5902,15 @@ "type": "string" } }, - "required": ["file"] + "required": [ + "file" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Todo": { "type": "object", @@ -5478,7 +5932,12 @@ "type": "string" } }, - "required": ["content", "status", "priority", "id"] + "required": [ + "content", + "status", + "priority", + "id" + ] }, "Event.todo.updated": { "type": "object", @@ -5500,10 +5959,16 @@ } } }, - "required": ["sessionID", "todos"] + "required": [ + "sessionID", + "todos" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.command.executed": { "type": "object", @@ -5530,10 +5995,18 @@ "pattern": "^msg.*" } }, - "required": ["name", "sessionID", "arguments", "messageID"] + "required": [ + "name", + "sessionID", + "arguments", + "messageID" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Session": { "type": "object", @@ -5571,7 +6044,11 @@ } } }, - "required": ["additions", "deletions", "files"] + "required": [ + "additions", + "deletions", + "files" + ] }, "share": { "type": "object", @@ -5580,7 +6057,9 @@ "type": "string" } }, - "required": ["url"] + "required": [ + "url" + ] }, "title": { "type": "string" @@ -5601,7 +6080,10 @@ "type": "number" } }, - "required": ["created", "updated"] + "required": [ + "created", + "updated" + ] }, "revert": { "type": "object", @@ -5619,10 +6101,19 @@ "type": "string" } }, - "required": ["messageID"] + "required": [ + "messageID" + ] } }, - "required": ["id", "projectID", "directory", "title", "version", "time"] + "required": [ + "id", + "projectID", + "directory", + "title", + "version", + "time" + ] }, "Event.session.created": { "type": "object", @@ -5638,10 +6129,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.updated": { "type": "object", @@ -5657,10 +6153,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.deleted": { "type": "object", @@ -5676,10 +6177,15 @@ "$ref": "#/components/schemas/Session" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.diff": { "type": "object", @@ -5701,10 +6207,16 @@ } } }, - "required": ["sessionID", "diff"] + "required": [ + "sessionID", + "diff" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.session.error": { "type": "object", @@ -5741,7 +6253,10 @@ } } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.file.watcher.updated": { "type": "object", @@ -5773,10 +6288,16 @@ ] } }, - "required": ["file", "event"] + "required": [ + "file", + "event" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.vcs.branch.updated": { "type": "object", @@ -5794,7 +6315,10 @@ } } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.prompt.append": { "type": "object", @@ -5810,10 +6334,15 @@ "type": "string" } }, - "required": ["text"] + "required": [ + "text" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.command.execute": { "type": "object", @@ -5852,10 +6381,15 @@ ] } }, - "required": ["command"] + "required": [ + "command" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.tui.toast.show": { "type": "object", @@ -5875,7 +6409,12 @@ }, "variant": { "type": "string", - "enum": ["info", "success", "warning", "error"] + "enum": [ + "info", + "success", + "warning", + "error" + ] }, "duration": { "description": "Duration in milliseconds", @@ -5883,10 +6422,16 @@ "type": "number" } }, - "required": ["message", "variant"] + "required": [ + "message", + "variant" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Pty": { "type": "object", @@ -5912,13 +6457,24 @@ }, "status": { "type": "string", - "enum": ["running", "exited"] + "enum": [ + "running", + "exited" + ] }, "pid": { "type": "number" } }, - "required": ["id", "title", "command", "args", "cwd", "status", "pid"] + "required": [ + "id", + "title", + "command", + "args", + "cwd", + "status", + "pid" + ] }, "Event.pty.created": { "type": "object", @@ -5934,10 +6490,15 @@ "$ref": "#/components/schemas/Pty" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.updated": { "type": "object", @@ -5953,10 +6514,15 @@ "$ref": "#/components/schemas/Pty" } }, - "required": ["info"] + "required": [ + "info" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.exited": { "type": "object", @@ -5976,10 +6542,16 @@ "type": "number" } }, - "required": ["id", "exitCode"] + "required": [ + "id", + "exitCode" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.pty.deleted": { "type": "object", @@ -5996,10 +6568,15 @@ "pattern": "^pty.*" } }, - "required": ["id"] + "required": [ + "id" + ] } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event.server.connected": { "type": "object", @@ -6013,7 +6590,10 @@ "properties": {} } }, - "required": ["type", "properties"] + "required": [ + "type", + "properties" + ] }, "Event": { "anyOf": [ @@ -6125,7 +6705,10 @@ "$ref": "#/components/schemas/Event" } }, - "required": ["directory", "payload"] + "required": [ + "directory", + "payload" + ] }, "Project": { "type": "object", @@ -6153,10 +6736,16 @@ "type": "number" } }, - "required": ["created"] + "required": [ + "created" + ] } }, - "required": ["id", "worktree", "time"] + "required": [ + "id", + "worktree", + "time" + ] }, "BadRequestError": { "type": "object", @@ -6177,7 +6766,11 @@ "const": false } }, - "required": ["data", "errors", "success"] + "required": [ + "data", + "errors", + "success" + ] }, "NotFoundError": { "type": "object", @@ -6193,10 +6786,15 @@ "type": "string" } }, - "required": ["message"] + "required": [ + "message" + ] } }, - "required": ["name", "data"] + "required": [ + "name", + "data" + ] }, "KeybindsConfig": { "description": "Custom keybind configurations", @@ -6463,7 +7061,11 @@ }, "mode": { "type": "string", - "enum": ["subagent", "primary", "all"] + "enum": [ + "subagent", + "primary", + "all" + ] }, "color": { "description": "Hex color code for the agent (e.g., #FF5733)", @@ -6481,13 +7083,21 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "anyOf": [ { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, { "type": "object", @@ -6496,22 +7106,38 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } ] }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } } @@ -6599,10 +7225,16 @@ "type": "number" } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "limit": { "type": "object", @@ -6614,7 +7246,10 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "modalities": { "type": "object", @@ -6623,25 +7258,44 @@ "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, "output": { "type": "array", "items": { "type": "string", - "enum": ["text", "audio", "image", "video", "pdf"] + "enum": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } } }, - "required": ["input", "output"] + "required": [ + "input", + "output" + ] }, "experimental": { "type": "boolean" }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated"] + "enum": [ + "alpha", + "beta", + "deprecated" + ] }, "options": { "type": "object", @@ -6666,7 +7320,9 @@ "type": "string" } }, - "required": ["npm"] + "required": [ + "npm" + ] } } } @@ -6758,7 +7414,10 @@ "maximum": 9007199254740991 } }, - "required": ["type", "command"], + "required": [ + "type", + "command" + ], "additionalProperties": false }, "McpOAuthConfig": { @@ -6824,13 +7483,19 @@ "maximum": 9007199254740991 } }, - "required": ["type", "url"], + "required": [ + "type", + "url" + ], "additionalProperties": false }, "LayoutConfig": { "description": "@deprecated Always uses stretch layout.", "type": "string", - "enum": ["auto", "stretch"] + "enum": [ + "auto", + "stretch" + ] }, "Config": { "type": "object", @@ -6864,12 +7529,17 @@ "type": "boolean" } }, - "required": ["enabled"] + "required": [ + "enabled" + ] }, "diff_style": { "description": "Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column", "type": "string", - "enum": ["auto", "stacked"] + "enum": [ + "auto", + "stacked" + ] } } }, @@ -6898,7 +7568,9 @@ "type": "boolean" } }, - "required": ["template"] + "required": [ + "template" + ] } }, "watcher": { @@ -6924,7 +7596,11 @@ "share": { "description": "Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing", "type": "string", - "enum": ["manual", "auto", "disabled"] + "enum": [ + "manual", + "auto", + "disabled" + ] }, "autoshare": { "description": "@deprecated Use 'share' field instead. Share newly created sessions automatically", @@ -7095,7 +7771,9 @@ "const": true } }, - "required": ["disabled"] + "required": [ + "disabled" + ] }, { "type": "object", @@ -7132,7 +7810,9 @@ "additionalProperties": {} } }, - "required": ["command"] + "required": [ + "command" + ] } ] } @@ -7154,13 +7834,21 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "anyOf": [ { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, { "type": "object", @@ -7169,22 +7857,38 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } ] }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } } }, @@ -7238,7 +7942,9 @@ } } }, - "required": ["command"] + "required": [ + "command" + ] } } }, @@ -7263,7 +7969,9 @@ } } }, - "required": ["command"] + "required": [ + "command" + ] } } } @@ -7312,7 +8020,11 @@ }, "parameters": {} }, - "required": ["id", "description", "parameters"] + "required": [ + "id", + "description", + "parameters" + ] }, "ToolList": { "type": "array", @@ -7336,7 +8048,12 @@ "type": "string" } }, - "required": ["state", "config", "worktree", "directory"] + "required": [ + "state", + "config", + "worktree", + "directory" + ] }, "VcsInfo": { "type": "object", @@ -7345,7 +8062,9 @@ "type": "string" } }, - "required": ["branch"] + "required": [ + "branch" + ] }, "TextPartInput": { "type": "object", @@ -7376,7 +8095,9 @@ "type": "number" } }, - "required": ["start"] + "required": [ + "start" + ] }, "metadata": { "type": "object", @@ -7386,7 +8107,10 @@ "additionalProperties": {} } }, - "required": ["type", "text"] + "required": [ + "type", + "text" + ] }, "FilePartInput": { "type": "object", @@ -7411,7 +8135,11 @@ "$ref": "#/components/schemas/FilePartSource" } }, - "required": ["type", "mime", "url"] + "required": [ + "type", + "mime", + "url" + ] }, "AgentPartInput": { "type": "object", @@ -7443,10 +8171,17 @@ "maximum": 9007199254740991 } }, - "required": ["value", "start", "end"] + "required": [ + "value", + "start", + "end" + ] } }, - "required": ["type", "name"] + "required": [ + "type", + "name" + ] }, "SubtaskPartInput": { "type": "object", @@ -7468,7 +8203,12 @@ "type": "string" } }, - "required": ["type", "prompt", "description", "agent"] + "required": [ + "type", + "prompt", + "description", + "agent" + ] }, "Command": { "type": "object", @@ -7492,7 +8232,10 @@ "type": "boolean" } }, - "required": ["name", "template"] + "required": [ + "name", + "template" + ] }, "Model": { "type": "object", @@ -7516,7 +8259,11 @@ "type": "string" } }, - "required": ["id", "url", "npm"] + "required": [ + "id", + "url", + "npm" + ] }, "name": { "type": "string" @@ -7555,7 +8302,13 @@ "type": "boolean" } }, - "required": ["text", "audio", "image", "video", "pdf"] + "required": [ + "text", + "audio", + "image", + "video", + "pdf" + ] }, "output": { "type": "object", @@ -7576,10 +8329,23 @@ "type": "boolean" } }, - "required": ["text", "audio", "image", "video", "pdf"] + "required": [ + "text", + "audio", + "image", + "video", + "pdf" + ] } }, - "required": ["temperature", "reasoning", "attachment", "toolcall", "input", "output"] + "required": [ + "temperature", + "reasoning", + "attachment", + "toolcall", + "input", + "output" + ] }, "cost": { "type": "object", @@ -7600,7 +8366,10 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] }, "experimentalOver200K": { "type": "object", @@ -7621,13 +8390,24 @@ "type": "number" } }, - "required": ["read", "write"] + "required": [ + "read", + "write" + ] } }, - "required": ["input", "output", "cache"] + "required": [ + "input", + "output", + "cache" + ] } }, - "required": ["input", "output", "cache"] + "required": [ + "input", + "output", + "cache" + ] }, "limit": { "type": "object", @@ -7639,11 +8419,19 @@ "type": "number" } }, - "required": ["context", "output"] + "required": [ + "context", + "output" + ] }, "status": { "type": "string", - "enum": ["alpha", "beta", "deprecated", "active"] + "enum": [ + "alpha", + "beta", + "deprecated", + "active" + ] }, "options": { "type": "object", @@ -7662,7 +8450,18 @@ } } }, - "required": ["id", "providerID", "api", "name", "capabilities", "cost", "limit", "status", "options", "headers"] + "required": [ + "id", + "providerID", + "api", + "name", + "capabilities", + "cost", + "limit", + "status", + "options", + "headers" + ] }, "Provider": { "type": "object", @@ -7675,7 +8474,12 @@ }, "source": { "type": "string", - "enum": ["env", "config", "custom", "api"] + "enum": [ + "env", + "config", + "custom", + "api" + ] }, "env": { "type": "array", @@ -7703,7 +8507,14 @@ } } }, - "required": ["id", "name", "source", "env", "options", "models"] + "required": [ + "id", + "name", + "source", + "env", + "options", + "models" + ] }, "ProviderAuthMethod": { "type": "object", @@ -7724,7 +8535,10 @@ "type": "string" } }, - "required": ["type", "label"] + "required": [ + "type", + "label" + ] }, "ProviderAuthAuthorization": { "type": "object", @@ -7748,7 +8562,11 @@ "type": "string" } }, - "required": ["url", "method", "instructions"] + "required": [ + "url", + "method", + "instructions" + ] }, "Symbol": { "type": "object", @@ -7769,10 +8587,17 @@ "$ref": "#/components/schemas/Range" } }, - "required": ["uri", "range"] + "required": [ + "uri", + "range" + ] } }, - "required": ["name", "kind", "location"] + "required": [ + "name", + "kind", + "location" + ] }, "FileNode": { "type": "object", @@ -7788,13 +8613,22 @@ }, "type": { "type": "string", - "enum": ["file", "directory"] + "enum": [ + "file", + "directory" + ] }, "ignored": { "type": "boolean" } }, - "required": ["name", "path", "absolute", "type", "ignored"] + "required": [ + "name", + "path", + "absolute", + "type", + "ignored" + ] }, "FileContent": { "type": "object", @@ -7848,14 +8682,24 @@ } } }, - "required": ["oldStart", "oldLines", "newStart", "newLines", "lines"] + "required": [ + "oldStart", + "oldLines", + "newStart", + "newLines", + "lines" + ] } }, "index": { "type": "string" } }, - "required": ["oldFileName", "newFileName", "hunks"] + "required": [ + "oldFileName", + "newFileName", + "hunks" + ] }, "encoding": { "type": "string", @@ -7865,7 +8709,10 @@ "type": "string" } }, - "required": ["type", "content"] + "required": [ + "type", + "content" + ] }, "File": { "type": "object", @@ -7885,10 +8732,19 @@ }, "status": { "type": "string", - "enum": ["added", "deleted", "modified"] + "enum": [ + "added", + "deleted", + "modified" + ] } }, - "required": ["path", "added", "removed", "status"] + "required": [ + "path", + "added", + "removed", + "status" + ] }, "Agent": { "type": "object", @@ -7901,7 +8757,11 @@ }, "mode": { "type": "string", - "enum": ["subagent", "primary", "all"] + "enum": [ + "subagent", + "primary", + "all" + ] }, "builtIn": { "type": "boolean" @@ -7920,7 +8780,11 @@ "properties": { "edit": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "bash": { "type": "object", @@ -7929,23 +8793,42 @@ }, "additionalProperties": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } }, "webfetch": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "doom_loop": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] }, "external_directory": { "type": "string", - "enum": ["ask", "allow", "deny"] + "enum": [ + "ask", + "allow", + "deny" + ] } }, - "required": ["edit", "bash"] + "required": [ + "edit", + "bash" + ] }, "model": { "type": "object", @@ -7957,7 +8840,10 @@ "type": "string" } }, - "required": ["modelID", "providerID"] + "required": [ + "modelID", + "providerID" + ] }, "prompt": { "type": "string" @@ -7984,7 +8870,14 @@ "maximum": 9007199254740991 } }, - "required": ["name", "mode", "builtIn", "permission", "tools", "options"] + "required": [ + "name", + "mode", + "builtIn", + "permission", + "tools", + "options" + ] }, "MCPStatusConnected": { "type": "object", @@ -7994,7 +8887,9 @@ "const": "connected" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusDisabled": { "type": "object", @@ -8004,7 +8899,9 @@ "const": "disabled" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusFailed": { "type": "object", @@ -8017,7 +8914,10 @@ "type": "string" } }, - "required": ["status", "error"] + "required": [ + "status", + "error" + ] }, "MCPStatusNeedsAuth": { "type": "object", @@ -8027,7 +8927,9 @@ "const": "needs_auth" } }, - "required": ["status"] + "required": [ + "status" + ] }, "MCPStatusNeedsClientRegistration": { "type": "object", @@ -8040,7 +8942,10 @@ "type": "string" } }, - "required": ["status", "error"] + "required": [ + "status", + "error" + ] }, "MCPStatus": { "anyOf": [ @@ -8086,7 +8991,12 @@ ] } }, - "required": ["id", "name", "root", "status"] + "required": [ + "id", + "name", + "root", + "status" + ] }, "FormatterStatus": { "type": "object", @@ -8104,7 +9014,11 @@ "type": "boolean" } }, - "required": ["name", "extensions", "enabled"] + "required": [ + "name", + "extensions", + "enabled" + ] }, "OAuth": { "type": "object", @@ -8126,7 +9040,12 @@ "type": "string" } }, - "required": ["type", "refresh", "access", "expires"] + "required": [ + "type", + "refresh", + "access", + "expires" + ] }, "ApiAuth": { "type": "object", @@ -8139,7 +9058,10 @@ "type": "string" } }, - "required": ["type", "key"] + "required": [ + "type", + "key" + ] }, "WellKnownAuth": { "type": "object", @@ -8155,7 +9077,11 @@ "type": "string" } }, - "required": ["type", "key", "token"] + "required": [ + "type", + "key", + "token" + ] }, "Auth": { "anyOf": [ @@ -8172,4 +9098,4 @@ } } } -} +}
\ No newline at end of file |
